Перейти к содержимому

Руководство разработчика

Передавайте публикации в Amaposta из собственного конвейера контента: загружайте медиафайлы, создавайте публикации для всех каналов, планируйте их и получайте уведомления о выходе.

Аутентификация

Создайте ключ 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. Подходит для файлов размером до нескольких сотен МБ.

POST /api/v1/projects/{project_id}/media
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 при создании публикации.

POST /api/v1/projects/{project_id}/media/import
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

Поля

ПолеЧто делает
kindtext, 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.
schedulemode принимает значение at (с полем at в формате ISO 8601), now или queue для следующего свободного слота. Не указывайте его, чтобы создать черновик.
external_refВаш собственный идентификатор, возвращаемый в публикации и отправках пользовательского API.
metadataJSON произвольной структуры, сохраняемый с публикацией. Включите "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[]
"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.

422 Unprocessable Entity
{
  "error": {
    "code": "validation",
    "message": "Please fix the highlighted fields.",
    "fields": {
      "kind": "Use text, image or video."
    }
  }
}
СтатусКодЗначение
400bad_requestЗапрос нельзя выполнить в указанном виде, например запланировать публикацию, не прошедшую проверки.
401unauthorizedКлюч API отсутствует, неверен или отозван.
402plan_limitТариф рабочего пространства не позволяет это действие; limit указывает лимит.
403forbiddenУ ключа нет нужного разрешения или доступа к проекту.
404not_foundТакого проекта, публикации, медиафайла или конечной точки нет.
409conflictИзменение конфликтует с текущим состоянием, например редактируется публикация, которая уже выходит.
422validationНужно исправить одно или несколько полей; см. fields.
429rate_limitedБолее 120 запросов в минуту с этим ключом.
502provider_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.published
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) для исходного тела запроса. Вычисляйте подпись самостоятельно, сравнивайте за постоянное время и отклоняйте старые временные метки для защиты от повторной отправки.

Node.js
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);
}
Python
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", ""))

Каналы с пользовательским API

Канал с пользовательским 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" }
}

Как отвечать

  • 2xxОпубликовано. При желании верните {"id": "…", "url": "…"}, и ссылка появится в публикации.
  • 401, 403Ключ отклонён. Канал помечается для повторного подключения, администраторы получают уведомление. Не используйте эти статусы для неверной подписи.
  • 5xx, 408, 429Временный сбой. Amaposta повторит попытку с увеличенным интервалом.
  • Другие 4xxПубликация помечается как неудачная с вашим сообщением; её можно исправить и нажать «Повторить».
Обработчик в Express
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-запросом к конечной точке.

Каналы песочницы

Канал песочницы работает как настоящий, но никакие данные не покидают Amaposta. С его помощью можно создать и проверить интеграцию целиком: публикации планируются, выходят в эфир, публикуются или завершаются ошибкой и вызывают те же вебхуки. Каналы песочницы бесплатны на любом тарифе и не учитываются в лимите каналов.

Выберите поведение при добавлении:

  • Всегда успешноВсе публикации выходят успешно.
  • Иногда завершать с ошибкойПосмотрите на сбои и повторные попытки, не дожидаясь настоящей аварии.
  • Всегда завершать с ошибкойПроверьте обработку post.failed.
  • Срок подключения истёкПосмотрите, как выглядят уведомления и ссылки для повторного подключения при истечении доступа.

Подключите X через собственное приложение

X взимает плату за каждый вызов API, включая каждую публикацию, с приложения разработчика, которое выполняет этот вызов, списывая её из предоплаченных кредитов приложения. Поэтому X подключается через ваше собственное приложение разработчика X: настройте его один раз для рабочего пространства, а затем подключайте сколько угодно аккаунтов X. В каждый аккаунт нужно войти на X, а его публикации оплачиваются из кредитов вашего приложения.

Полезно знать

  • Приложение сохраняется для всего рабочего пространства, а его секрет шифруется. Любой другой аккаунт X можно подключить одним нажатием из любого проекта.
  • Каналы сохраняют приложение, через которое были подключены. При повторном подключении канала, в том числе по ссылке для клиента, снова используется это приложение; ваш клиент его не видит.
  • Чтобы сменить приложение, выберите «Использовать другое приложение» при подключении X. Если вы создадите новый Client Secret, введите его там и переподключите свои каналы X.
  • Консоль X выдаёт токены только для аккаунта, которому принадлежит приложение. Чтобы подключить аккаунты клиентов, нужно войти через ваше приложение; для собственного аккаунта по-прежнему можно ввести токены вручную.

Правила платформ

Требования каждого типа канала. Проверки используют те же лимиты, поэтому большинство проблем обнаруживается до планирования, а не при выходе публикации.

Платформа Публикация Заголовок Текст Хештеги Медиафайлы
YouTube Видео ЗаголовокОбязательно, до 100 символов ОписаниеДо 5 000 символов Передаются как теги, до 60 MP4, MOV, WebM, AVI, MKV; до 256 GB; От 1 с до 12 ч
Аккаунты без подтверждённого номера телефона могут загружать видео длительностью до 15 минут и не могут задавать собственные миниатюры. Каждая загрузка расходует квоту API; стандартной квоты Google хватает примерно на шесть загрузок в день на приложение.
Instagram Изображение Без заголовка ПодписьДо 2 200 символов Добавляются в текст, до 30 JPEG; до 8 MB
Видео Без заголовка ПодписьДо 2 200 символов Добавляются в текст, до 30 MP4, MOV; до 300 MB; От 3 с до 15 мин
Требуется бизнес-аккаунт Instagram или аккаунт автора. Instagram разрешает 50 публикаций через API на аккаунт за скользящий период в 24 часа. В Instagram нельзя публиковать только текст.
TikTok Изображение ЗаголовокДо 90 символов ОписаниеДо 4 000 символов Добавляются в текст JPEG, WebP; до 20 MB
Видео Без заголовка ПодписьДо 2 200 символов Добавляются в текст 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. Хештеги учитываются в лимите символов.
Facebook Текст Без заголовка ПубликацияОбязательно, до 63 206 символов Добавляются в текст Нет
Изображение Без заголовка ПодписьДо 63 206 символов Добавляются в текст JPEG, PNG, GIF, WebP; до 10 MB
Видео ЗаголовокДо 255 символов ОписаниеДо 63 206 символов Добавляются в текст MP4, MOV; до 1 GB; От 1 с до 20 мин
Публикует только на страницах; API не позволяет публиковать в личных профилях.
Пользовательский API Текст ЗаголовокБез ограничения длины ОписаниеБез ограничения длины Передаются как теги Нет
Изображение ЗаголовокБез ограничения длины ОписаниеБез ограничения длины Передаются как теги JPEG, PNG, WebP, GIF
Видео ЗаголовокБез ограничения длины ОписаниеБез ограничения длины Передаются как теги MP4, MOV, WebM
Каждый запрос подписывается заголовком HMAC-SHA256, чтобы вы могли проверить, что он поступил от Amaposta. Ответьте статусом 2xx и при желании JSON {"id": "…", "url": "…"}. Ответы 408, 429 и 5xx вызывают повторные попытки с увеличением интервалов; 401/403 помечают канал для повторного подключения; другие 4xx завершают отправку с ошибкой, чтобы вы могли исправить её и повторить попытку.
Песочница Текст ЗаголовокДо 200 символов ОписаниеДо 5 000 символов Добавляются в текст, до 30 Нет
Изображение ЗаголовокДо 200 символов ОписаниеДо 5 000 символов Добавляются в текст, до 30 JPEG, PNG, WebP, GIF
Видео ЗаголовокДо 200 символов ОписаниеДо 5 000 символов Добавляются в текст, до 30 MP4, MOV, WebM
Публикация занимает некоторое время, чтобы вы могли наблюдать изменение статуса.