Удостоверяване
Създайте API ключ в таблото от Настройки, API и уебхукове. Ключовете започват с ss_live_, принадлежат на едно работно пространство и могат да се ограничат до определени проекти. Изпращайте ключа като bearer токен във всяка заявка:
curl https://www.amaposta.com/api/v1/me \
-H "Authorization: Bearer ss_live_…"
Отговорът посочва ключа, правата му и работното пространство. Всеки ключ има едно или повече права:
| Обхват | Позволява |
|---|---|
content:read | Четене на проекти, канали, публикации и медийни файлове. |
content:write | Качване на медийни файлове и създаване или редактиране на публикации. |
posts:publish | Насрочване и публикуване без преглед. Без това право публикациите отиват във входящата кутия за преглед в проекти с одобрения и остават чернови навсякъде другаде. |
Всеки ключ може да прави 120 заявки в минута. Над това получавате 429 с код rate_limited; изчакайте малко и опитайте отново.
Проекти и канали
Публикациите принадлежат на проект. Избройте проектите, видими за ключа ви, после каналите в един от тях. Ще ви трябва идентификаторът на канал, за да го посочите като цел или да замените текста му.
curl https://www.amaposta.com/api/v1/projects \
-H "Authorization: Bearer $AMAPOSTA_KEY"
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/channels \
-H "Authorization: Bearer $AMAPOSTA_KEY"
Каналът има provider (youtube, instagram, tiktok, x, facebook, custom или sandbox), status (active, expiring, needs_reconnect, error или disabled) и поддържани видове публикации в supports.
Качване на медийни файлове
Изображенията и видеоклиповете се качват веднъж за проект и могат да се използват в неограничен брой публикации. Има три начина за добавяне.
Директно качване
Изпратете файла като multipart form data в поле с име file. Най-подходящо за файлове до няколкостотин MB.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-F "[email protected]"
Предварително подписано качване за големи файлове
Поискайте URL адрес за качване, изпратете байтовете директно в хранилището с PUT и уведомете Amaposta, че сте готови.
# 1. Ask for an upload URL. The response is {"media": { … }, "upload_url": "…"}
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media/uploads \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-H "Content-Type: application/json" \
-d '{"filename": "batch-142.mp4", "content_type": "video/mp4", "size_bytes": 48213844}'
# 2. Upload the bytes to upload_url
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--upload-file batch-142.mp4
# 3. Finish the upload
curl -X POST https://www.amaposta.com/api/v1/media/$MEDIA_ID/complete \
-H "Authorization: Bearer $AMAPOSTA_KEY"
Импортиране от URL адрес
Дайте на Amaposta публичен URL адрес и тя ще изтегли файла във фонов режим. Можете и да пропуснете тази стъпка и да подадете media_url при създаване на публикацията.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media/import \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://cdn.example.com/batch-142.mp4"}'
Всяко качване връща медиен обект. Неговият status преминава от pending през processing до ready (или failed с error). След обработка съдържа width, height, duration_ms и миниатюра. Проверявайте периодично GET /api/v1/media/{id} или слушайте за уебхука media.ready. Върнатият url е подписан и важи 12 часа.
Създаване на публикация
POST /api/v1/projects/{project_id}/posts създава една публикация с отделно изпращане за всеки канал. Amaposta я адаптира за всяка платформа: заглавията отиват само там, където има поле за заглавие, а хаштаговете стават етикети в YouTube и текст в останалите платформи.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/posts \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: episode-142" \
-d @- <<'JSON'
{
"kind": "video",
"title": "How we roast a batch in 12 minutes",
"description": "From green beans to first crack. We filmed one batch start to finish.",
"hashtags": ["coffee", "behindthescenes"],
"media_url": "https://cdn.example.com/batch-142.mp4",
"cover_url": "https://cdn.example.com/batch-142-cover.jpg",
"overrides": {
"<x-channel-id>": {
"description": "Batch 142 is out: green beans to first crack in 12 minutes."
},
"<youtube-channel-id>": {
"options": { "privacy": "unlisted" }
}
},
"schedule": { "mode": "queue" },
"external_ref": "episode-142",
"metadata": {
"pipeline": { "name": "nightly-cut", "run": "2026-10-17" }
}
}
JSON
Полета
| Поле | Какво прави |
|---|---|
kind | text, image или video. Задължително. |
title | Използва се от платформи с поле за заглавие: YouTube, фотопубликации в TikTok, видеоклипове във Facebook. |
description | Надписът, описанието или текстът на публикацията. Приема се също като body, caption или text. |
hashtags | Списък със или без #. |
media_id, media_url | Идентификатор на качен медиен файл или публичен URL адрес, от който Amaposta го изтегля. Нужен е за публикации с изображения и видеоклипове. |
cover_media_id, cover_url | Корица за видеоклипове, когато платформата я поддържа. |
channels | Идентификатори на каналите за публикуване. Пропуснете ги, за да използвате всички активни канали в проекта, които поддържат този вид публикация. |
overrides | Промени за отделни канали с ключ идентификатора на канала: title, description, hashtags и options за платформата, като privacy на YouTube. |
schedule | mode е at (с at в ISO 8601), now или queue за следващия свободен час за публикуване. Пропуснете го, за да създадете чернова. |
external_ref | Ваша собствена референция, връщана в публикацията и при изпращанията към Custom API. |
metadata | JSON със свободна структура, съхраняван с публикацията. Включете "pipeline", за да отбележите генерирано съдържание; таблото го показва, а уебхуковете посочват произхода като pipeline. |
Отговорът е публикацията, включително по един запис в deliveries за всеки канал.
Безопасни повторни опити
Мрежите губят заявки. Изпращайте заглавка Idempotency-Key при създаване на публикация и повторен опит със същия ключ ще върне публикацията от първия опит, вместо да създава втора. Използвайте постоянна стойност от ваша страна, като идентификатор на задача или епизод. Ключовете се отрязват до 200 знака.
Насрочване и публикуване
Насрочете чернова, публикувайте я веднага, добавете я в опашката или я махнете от календара с POST /api/v1/posts/{post_id}/schedule.
curl https://www.amaposta.com/api/v1/posts/$POST_ID/schedule \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-H "Content-Type: application/json" \
-d '{"mode": "at", "at": "2026-10-20T07:00:00Z"}'
atПубликува в зададения час, до две години напред.nowПубликува веднага.queueЗаема следващия свободен час за публикуване за каналите на публикацията в следващите 12 седмици.unscheduleВръща публикацията в черновите.
Преди всяко насрочване се изпълняват същите проверки като в редактора. При неуспешна проверка заявката връща 400 със съобщение като Поправете преди насрочване: YouTube изисква заглавие.
Насрочването изисква правото posts:publish или проект с включени одобрения, при което публикацията чака във входящата кутия за преглед.
Четене на публикации и изпращания
Избройте публикациите в проект, филтрирани по status (статуси, разделени със запетая, или inbox, queue или history), интервал from/to, limit и offset. Отговорът е {"items": […], "total": n}.
curl "https://www.amaposta.com/api/v1/projects/$PROJECT_ID/posts?status=queue" \
-H "Authorization: Bearer $AMAPOSTA_KEY"
curl https://www.amaposta.com/api/v1/posts/$POST_ID \
-H "Authorization: Bearer $AMAPOSTA_KEY"
Публикацията има общ status (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial или failed) и по едно изпращане за всеки канал:
"deliveries": [
{
"id": "0192b7d4-…",
"channel_id": "0192b7a1-…",
"status": "published",
"url": "https://www.youtube.com/watch?v=…",
"error": null,
"published_at": "2026-10-20T07:00:41Z"
},
{
"id": "0192b7d4-…",
"channel_id": "0192b7a9-…",
"status": "failed",
"url": null,
"error": {
"code": "endpoint_unavailable",
"message": "Your endpoint returned 503 Service Unavailable",
"hint": "Amaposta will retry with backoff."
},
"published_at": null
}
]
Статусите на изпращане са pending, scheduled, publishing, processing, published, failed и cancelled. DELETE /api/v1/posts/{post_id} премахва публикация.
Грешки
Всяка грешка има еднакъв формат: обект error с постоянен code, message, което можете да показвате на хората, а понякога и fields (съобщения за отделните полета) и hint.
{
"error": {
"code": "validation",
"message": "Please fix the highlighted fields.",
"fields": {
"kind": "Use text, image or video."
}
}
}
| Статус | Код | Значение |
|---|---|---|
| 400 | bad_request | Заявката не може да се изпълни според искането, например насрочване на публикация с неуспешни проверки. |
| 401 | unauthorized | API ключът липсва, грешен е или е отменен. |
| 402 | plan_limit | Планът на работното пространство не позволява това; limit посочва кое ограничение. |
| 403 | forbidden | Ключът няма нужното право или достъп до проекта. |
| 404 | not_found | Няма такъв проект, публикация, медиен файл или крайна точка. |
| 409 | conflict | Промяната е несъвместима с текущото състояние, например редактиране на публикация, която вече се публикува. |
| 422 | validation | Едно или повече полета се нуждаят от поправка; вижте fields. |
| 429 | rate_limited | Над 120 заявки в минута с този ключ. |
| 502 | provider_error | Платформа отказа или възникна грешка; hint посочва какво да направите. |
Уебхукове
Добавете крайна точка в Настройки, API и уебхукове, изберете желаните събития и копирайте тайната ѝ за подписване. За всяко събитие Amaposta изпраща JSON с POST към вашия URL адрес. При отговор, различен от 2xx, или липса на отговор в рамките на 15 секунди, опитът се повтаря с нарастващо изчакване. Крайни точки, които продължават да дават грешки, се изключват с известие до администраторите.
| Събитие | Изпраща се при |
|---|---|
post.created | Публикация беше създадена (от таблото или API) |
post.scheduled | Публикация беше насрочена |
post.approved | Публикация беше одобрена |
post.published | Публикация излезе в канал |
post.failed | Публикация не беше публикувана успешно в канал |
channel.connected | Канал беше свързан или свързан повторно |
channel.disconnected | Канал загуби връзката си |
media.ready | Обработката на качен файл приключи |
media.failed | Качен файл не можа да бъде обработен |
POST /your/webhook HTTP/1.1
Content-Type: application/json
User-Agent: Amaposta-Webhooks/1.0
X-Amaposta-Event: post.published
X-Amaposta-Event-Id: 0192b7e0-…
X-Amaposta-Signature: t=1792479641,v1=5f2b0c…
{
"id": "0192b7e0-…",
"type": "post.published",
"created_at": "2026-10-20T07:00:41Z",
"project_id": "0192a3f1-…",
"data": {
"post_id": "0192b7c8-…",
"delivery_id": "0192b7d4-…",
"channel_id": "0192b7a1-…",
"provider": "youtube",
"external_id": "…",
"url": "https://www.youtube.com/watch?v=…"
}
}
Проверка на подписа
X-Amaposta-Signature е t=<unix seconds>,v1=<hex>, където v1 е HMAC_SHA256(secret, t + "." + body) върху необработеното тяло на заявката. Изчислете го самостоятелно, сравнете за константно време и отхвърляйте стари времеви отметки, за да предотвратите повторно изпращане.
import crypto from "node:crypto";
// rawBody: the request body exactly as received (string or Buffer).
export function verifySignature(rawBody, header, secret, toleranceSeconds = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
const t = Number(parts.t);
if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(`${t}.${rawBody}`)
.digest();
const given = Buffer.from(parts.v1 ?? "", "hex");
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
}
import hashlib
import hmac
import time
def verify_signature(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
t = int(parts.get("t", "0"))
if abs(time.time() - t) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))
Канали Custom API
Каналът Custom API публикува към HTTPS крайна точка, която управлявате: вашата CMS, инструмент за бюлетини или платформа, която Amaposta още не поддържа. Той се показва в календара и преминава през проверки, одобрения и повторни опити като всеки друг канал. При публикуване Amaposta изпраща по една POST заявка за всяко изпращане:
POST /amaposta/publish HTTP/1.1
Authorization: Bearer <your API key>
Content-Type: application/json
Idempotency-Key: 0192b7d4-…
X-Amaposta-Delivery: 0192b7d4-…
X-Amaposta-Signature: t=1792479600,v1=9ac41e…
{
"id": "0192b7d4-…",
"type": "post.publish",
"created_at": "2026-10-20T07:00:00Z",
"content": {
"kind": "video",
"title": "How we roast a batch in 12 minutes",
"text": "From green beans to first crack. We filmed one batch start to finish.",
"hashtags": ["coffee", "behindthescenes"],
"media": {
"url": "https://…",
"content_type": "video/mp4",
"size_bytes": 48213844,
"width": 1080,
"height": 1920,
"duration_ms": 58000,
"filename": "batch-142.mp4"
},
"cover": null,
"options": {}
},
"post": {
"id": "0192b7c8-…",
"external_ref": "episode-142",
"scheduled_at": "2026-10-20T07:00:00Z",
"metadata": {
"pipeline": { "name": "nightly-cut" }
}
},
"project": { "id": "0192a3f1-…", "name": "Spring launch" },
"channel": { "id": "0192b7a9-…", "name": "api.example.com" }
}
Authorization- Вашият API ключ. Името на заглавката и префиксът (
Bearerпо подразбиране) се задават в канала. Idempotency-Key- Идентификаторът на изпращането. Повторен опит за същото изпращане изпраща същия ключ, за да пропуснете вече свършената работа.
X-Amaposta-Delivery- Идентификаторът на изпращането отново, за вашите дневници.
X-Amaposta-Signature- Подписва се като уебхуковете, с тайната за подписване на канала.
Как да отговорите
- 2xxПубликувано. По избор върнете
{"id": "…", "url": "…"}и връзката ще се покаже в публикацията. - 401, 403Ключът е отхвърлен. Каналът се отбелязва за повторно свързване и администраторите се уведомяват. Не използвайте тези статуси за невалиден подпис.
- 5xx, 408, 429Временно. Amaposta повтаря с нарастващо изчакване.
- Други 4xxПубликацията се отбелязва като неуспешна с вашето съобщение и някой може да я поправи и да натисне Повторен опит.
app.post("/amaposta/publish", express.raw({ type: "application/json" }), async (req, res) => {
const signature = req.get("X-Amaposta-Signature") ?? "";
if (!verifySignature(req.body, signature, process.env.AMAPOSTA_SIGNING_SECRET)) {
return res.status(400).json({ message: "Bad signature" });
}
const delivery = JSON.parse(req.body);
const item = await publishToYourSystem(delivery.content, req.get("Idempotency-Key"));
res.json({ id: item.id, url: item.url });
});
Крайната ви точка трябва да е достъпна от интернет; пренасочвания не се следват. При свързване на канала Amaposta я проверява с GET към URL адреса за изправност, ако сте задали такъв, или с OPTIONS заявка към крайната точка.
Канали Sandbox
Каналът Sandbox се държи като истински, но нищо не напуска Amaposta. Използвайте го, за да изградите и тествате интеграцията си от край до край: публикациите се насрочват, излизат в ефир, публикуват се или се провалят и задействат същите уебхукове. Каналите Sandbox са безплатни във всеки план и не се броят към ограниченията за канали.
Изберете как да се държи при добавяне:
- Винаги успехВсяка публикация се публикува.
- Неуспех от време на времеИзпробвайте неуспехи и повторни опити, без да чакате истински срив.
- Винаги неуспехТествайте обработката на
post.failed. - Изтекла връзкаВижте как изглеждат сигналите и връзките за повторно свързване, когато достъпът изтече.
Правила на платформата
Какво приема всеки вид канал. Проверките използват същите ограничения, затова повечето проблеми се откриват преди насрочването на публикацията, а не при публикуване.
| Платформа | Публикация | Заглавие | Текст | Хаштагове | Медийни файлове |
|---|---|---|---|---|---|
| YouTube | Видео | ЗаглавиеЗадължително, до 100 знака | ОписаниеДо 5000 знака | Изпращат се като етикети, до 60 | MP4, MOV, WebM, AVI, MKV; до 256 GB; от 1 сек до 12 ч |
| Акаунти без потвърден телефонен номер могат да качват до 15 минути и не могат да задават собствени миниатюри. Всяко качване изразходва квота за API; стандартната квота на Google позволява около шест качвания на ден за приложение. | |||||
| Изображение | Без заглавие | НадписДо 2200 знака | Добавят се към текста, до 30 | JPEG; до 8 MB | |
| Видео | Без заглавие | НадписДо 2200 знака | Добавят се към текста, до 30 | MP4, MOV; до 300 MB; от 3 сек до 15 мин | |
| Изисква се Instagram Business или Creator акаунт. Instagram позволява 50 публикации чрез API на акаунт за всеки подвижен период от 24 часа. Публикации само с текст не са възможни в Instagram. | |||||
| TikTok | Изображение | ЗаглавиеДо 90 знака | ОписаниеДо 4000 знака | Добавят се към текста | JPEG, WebP; до 20 MB |
| Видео | Без заглавие | НадписДо 2200 знака | Добавят се към текста | MP4, MOV, WebM; до 4 GB; от 3 сек до 10 мин | |
| Публикациите от приложения, които не са преминали проверката на TikTok, са видими само за създателя. TikTok избира корицата от кадър на видеоклипа; собствени изображения за корица не се поддържат. Публикации само с текст не са възможни в TikTok. | |||||
| X | Текст | Без заглавие | ПубликацияЗадължително, до 280 (връзките са 23 знака, емоджитата — 2) | Добавят се към текста | Няма |
| Изображение | Без заглавие | ПубликацияДо 280 (връзките са 23 знака, емоджитата — 2) | Добавят се към текста | JPEG, PNG, WebP, GIF; до 5 MB | |
| Видео | Без заглавие | ПубликацияДо 280 (връзките са 23 знака, емоджитата — 2) | Добавят се към текста | MP4, MOV; до 512 MB; от 0,5 сек до 2:20 мин | |
| Ако използвате собствено приложение за разработчици на X, публикациите изразходват неговите API кредити с плащане според потреблението. Хаштаговете се броят към ограничението за знаци. | |||||
| Текст | Без заглавие | ПубликацияЗадължително, до 63 206 знака | Добавят се към текста | Няма | |
| Изображение | Без заглавие | НадписДо 63 206 знака | Добавят се към текста | JPEG, PNG, GIF, WebP; до 10 MB | |
| Видео | ЗаглавиеДо 255 знака | ОписаниеДо 63 206 знака | Добавят се към текста | MP4, MOV; до 1 GB; от 1 сек до 20 мин | |
| Публикува само в страници; личните профили не позволяват публикуване чрез API. | |||||
| Custom API | Текст | ЗаглавиеБез ограничение за дължината | ОписаниеБез ограничение за дължината | Изпращат се като етикети | Няма |
| Изображение | ЗаглавиеБез ограничение за дължината | ОписаниеБез ограничение за дължината | Изпращат се като етикети | JPEG, PNG, WebP, GIF | |
| Видео | ЗаглавиеБез ограничение за дължината | ОписаниеБез ограничение за дължината | Изпращат се като етикети | MP4, MOV, WebM | |
| Всяка заявка е подписана със заглавка HMAC-SHA256, за да проверите, че идва от Amaposta. Отговорете с 2xx и по избор JSON {"id": "…", "url": "…"}. Отговори 408, 429 и 5xx се повтарят с нарастващо изчакване; 401/403 отбелязват канала за повторно свързване; други 4xx провалят изпращането, за да го поправите и повторите. | |||||
| Sandbox | Текст | ЗаглавиеДо 200 знака | ОписаниеДо 5000 знака | Добавят се към текста, до 30 | Няма |
| Изображение | ЗаглавиеДо 200 знака | ОписаниеДо 5000 знака | Добавят се към текста, до 30 | JPEG, PNG, WebP, GIF | |
| Видео | ЗаглавиеДо 200 знака | ОписаниеДо 5000 знака | Добавят се към текста, до 30 | MP4, MOV, WebM | |
| Публикуването отнема малко време, за да наблюдавате промяната на статуса на живо. | |||||