Przejdź do treści

Przewodnik programisty

Wysyłaj posty do Amaposta z własnego potoku treści: prześlij multimedia, utwórz post dla każdego kanału, zaplanuj go i otrzymaj informację, gdy zostanie opublikowany.

Uwierzytelnianie

Utwórz klucz API w panelu w Ustawieniach, w sekcji API i webhooki. Klucze zaczynają się od ss_live_, należą do jednej przestrzeni roboczej i mogą być ograniczone do wybranych projektów. Wysyłaj klucz jako token Bearer w każdym żądaniu:

Sprawdź klucz
curl https://www.amaposta.com/api/v1/me \
  -H "Authorization: Bearer ss_live_…"

Odpowiedź podaje nazwę klucza, jego zakresy uprawnień i przestrzeń roboczą. Każdy klucz ma co najmniej jeden zakres:

Zakres uprawnieńZezwala na
content:readOdczyt projektów, kanałów, postów i multimediów.
content:writePrzesyłanie multimediów oraz tworzenie lub edycja postów.
posts:publishPlanowanie i publikowanie bez weryfikacji. Bez tego uprawnienia posty trafiają do skrzynki weryfikacji w projektach z zatwierdzaniem, a w pozostałych pozostają szkicami.

Każdy klucz może wykonać 120 żądań na minutę. Po przekroczeniu limitu otrzymasz 429 z kodem rate_limited; odczekaj chwilę i spróbuj ponownie.

Projekty i kanały

Posty należą do projektu. Wyświetl projekty dostępne dla Twojego klucza, a następnie kanały jednego z nich. Identyfikator kanału jest potrzebny, aby wybrać go jako cel lub nadpisać jego tekst.

Wyświetl projekty i kanały
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"

Kanał ma pola provider (youtube, instagram, tiktok, x, facebook, custom lub sandbox), status (active, expiring, needs_reconnect, error lub disabled) oraz obsługiwane rodzaje postów w polu supports.

Prześlij multimedia

Obrazy i filmy przesyła się raz do projektu, a następnie można ich używać w dowolnej liczbie postów. Są trzy sposoby ich dodawania.

Przesyłanie bezpośrednie

Wyślij plik jako dane formularza multipart w polu o nazwie file. Najlepiej sprawdza się przy plikach do kilkuset MB.

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]"

Podpisany adres przesyłania dużych plików

Poproś o adres URL do przesyłania, wyślij bajty bezpośrednio do magazynu metodą PUT, a potem powiadom Amaposta o zakończeniu.

Trzy żądania
# 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"

Importuj z adresu URL

Podaj Amaposta publiczny adres URL, a pobierze plik w tle. Możesz też pominąć ten krok i podać media_url podczas tworzenia posta.

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"}'

Każde przesłanie zwraca obiekt multimedialny. Jego status zmienia się z pending na processing, a następnie ready (lub failed, z polem error). Po przetworzeniu zawiera pola width, height, duration_ms i miniaturę. Odpytuj GET /api/v1/media/{id} lub nasłuchuj webhooka media.ready. Zwracany url jest podpisany i ważny przez 12 godzin.

Utwórz post

POST /api/v1/projects/{project_id}/posts tworzy jeden post z osobną wysyłką dla każdego kanału. Amaposta dostosowuje go do platformy: tytuły trafiają tylko tam, gdzie jest pole tytułu, a hashtagi stają się tagami w YouTube i częścią tekstu na pozostałych platformach.

Utwórz post z filmem i dodaj go do kolejki
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

Pola

PoleCo robi
kindtext, image lub video. Wymagane.
titleUżywane przez platformy z polem tytułu: YouTube, posty ze zdjęciami TikTok, filmy Facebook.
descriptionPodpis, opis lub tekst posta. Akceptowane również jako body, caption lub text.
hashtagsLista, ze znakiem # lub bez niego.
media_id, media_urlIdentyfikator przesłanego pliku multimedialnego lub publiczny adres URL, z którego Amaposta go pobierze. Wymagane w postach z obrazem lub filmem.
cover_media_id, cover_urlOkładka filmu, jeśli platforma ją obsługuje.
channelsIdentyfikatory kanałów docelowych. Pomiń to pole, aby użyć każdego aktywnego kanału w projekcie, który obsługuje ten rodzaj posta.
overridesZmiany dla poszczególnych kanałów, z identyfikatorem kanału jako kluczem: title, description, hashtags i ustawienia platformy options, np. privacy dla YouTube.
schedulemode to at (z polem at w formacie ISO 8601), now lub queue, aby wybrać następny wolny termin publikacji. Pomiń to pole, aby utworzyć szkic.
external_refTwój własny identyfikator referencyjny, zwracany w poście i wysyłkach Własne API.
metadataDowolne dane JSON zapisywane z postem. Dodaj "pipeline", aby oznaczyć wygenerowane treści; panel wyświetli to oznaczenie, a webhooki podadzą źródło jako pipeline.

Odpowiedź zawiera post, w tym po jednym wpisie w deliveries na kanał.

Bezpieczne ponawianie prób

W sieci żądania czasem giną. Podczas tworzenia posta wyślij nagłówek Idempotency-Key, a ponowienie z tym samym kluczem zwróci post z pierwszej próby zamiast tworzyć kolejny. Użyj stałej wartości ze swojego systemu, np. identyfikatora zadania lub odcinka. Klucze są przycinane do 200 znaków.

Planowanie i publikowanie

Zaplanuj szkic, opublikuj go teraz, dodaj do kolejki lub usuń z kalendarza za pomocą POST /api/v1/posts/{post_id}/schedule.

Zaplanuj na wybrany termin
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"}'
  • atPublikuje w podanym terminie, z wyprzedzeniem do dwóch lat.
  • nowPublikuje od razu.
  • queueWybiera następny wolny termin publikacji dla kanałów posta w ciągu najbliższych 12 tygodni.
  • unschedulePrzenosi post z powrotem do szkiców.

Przed zaplanowaniem czegokolwiek wykonywane są te same kontrole co w edytorze. Jeśli któraś się nie powiedzie, żądanie zwraca 400 z komunikatem takim jak Popraw to przed zaplanowaniem: YouTube wymaga tytułu. Planowanie wymaga uprawnienia posts:publish lub projektu z włączonym zatwierdzaniem — wtedy post czeka w skrzynce weryfikacji.

Odczyt postów i wysyłek

Wyświetl posty projektu, filtrując według status (statusy oddzielone przecinkami lub inbox, queue albo history), zakresu from/to, limit i offset. Odpowiedź ma postać {"items": […], "total": n}.

Co nadchodzi i jeden post w szczegółach
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"

Post ma ogólny status (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial lub failed) i po jednej wysyłce na kanał:

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
  }
]

Statusy wysyłki to pending, scheduled, publishing, processing, published, failed i cancelled. DELETE /api/v1/posts/{post_id} usuwa post.

Błędy

Każdy błąd ma tę samą strukturę: obiekt error ze stałym polem code, komunikatem message do pokazania użytkownikom i czasami polami fields (komunikaty dla poszczególnych pól) oraz hint.

422 Unprocessable Entity
{
  "error": {
    "code": "validation",
    "message": "Please fix the highlighted fields.",
    "fields": {
      "kind": "Use text, image or video."
    }
  }
}
StatusKodZnaczenie
400bad_requestNie można wykonać żądania w podanej formie, np. zaplanować posta, który nie przechodzi kontroli.
401unauthorizedBrakuje klucza API, jest nieprawidłowy lub został unieważniony.
402plan_limitPlan przestrzeni roboczej na to nie pozwala; pole limit wskazuje, który limit został osiągnięty.
403forbiddenKlucz nie ma wymaganego uprawnienia lub dostępu do projektu.
404not_foundNie ma takiego projektu, posta, pliku multimedialnego ani punktu końcowego.
409conflictZmiana koliduje z obecnym stanem, np. edycja posta, którego publikowanie już trwa.
422validationCo najmniej jedno pole wymaga poprawy; zobacz fields.
429rate_limitedPonad 120 żądań na minutę dla tego klucza.
502provider_errorPlatforma odmówiła lub wystąpił na niej błąd; pole hint podpowiada, co zrobić.

Webhooki

Dodaj punkt końcowy w Ustawieniach, w sekcji API i webhooki, wybierz zdarzenia i skopiuj jego sekret podpisu. Amaposta wysyła dla każdego zdarzenia żądanie POST z danymi JSON na Twój adres URL. Każda odpowiedź inna niż 2xx lub brak odpowiedzi przez 15 sekund powoduje ponowienie z rosnącym odstępem. Punkty końcowe, w których błędy się powtarzają, są wyłączane, a administratorzy otrzymują powiadomienie.

ZdarzenieWysyłane, gdy
post.createdUtworzono post (w panelu lub przez API)
post.scheduledZaplanowano publikację posta
post.approvedPost został zatwierdzony
post.publishedPost został opublikowany w kanale
post.failedNie udało się opublikować posta w kanale
channel.connectedKanał został połączony lub połączony ponownie
channel.disconnectedKanał utracił połączenie
media.readyZakończono przetwarzanie przesłanego pliku
media.failedNie udało się przetworzyć przesłanego pliku
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=…"
  }
}

Sprawdź podpis

X-Amaposta-Signature ma postać t=<unix seconds>,v1=<hex>, gdzie v1 to HMAC_SHA256(secret, t + "." + body) obliczony dla surowej treści żądania. Oblicz go samodzielnie, porównaj w stałym czasie i odrzucaj stare znaczniki czasu, aby zapobiec powtórzeniom żądań.

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", ""))

Kanały Własne API

Kanał Własne API publikuje w utrzymywanym przez Ciebie punkcie końcowym HTTPS: w Twoim CMS, narzędziu do newsletterów lub na platformie, której Amaposta jeszcze nie obsługuje. Pojawia się w kalendarzu i podlega kontrolom, zatwierdzaniu i ponownym próbom tak jak każdy inny kanał. Gdy nadchodzi czas publikacji, Amaposta wysyła jedno żądanie POST na każdą wysyłkę:

Co otrzymuje Twój punkt końcowy
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" }
}

Jak odpowiadać

  • 2xxOpublikowano. Opcjonalnie zwróć {"id": "…", "url": "…"}, a link pojawi się przy poście.
  • 401, 403Klucz został odrzucony. Kanał zostaje oznaczony jako wymagający ponownego połączenia, a administratorzy otrzymują powiadomienie. Nie używaj tych kodów przy nieprawidłowym podpisie.
  • 5xx, 408, 429Błąd tymczasowy. Amaposta ponawia próby z rosnącym odstępem.
  • Inne 4xxPost otrzymuje status niepowodzenia z Twoim komunikatem, a ktoś może go poprawić i nacisnąć Ponów.
Odbiornik w 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 });
});

Twój punkt końcowy musi być dostępny z internetu; przekierowania nie są śledzone. Podczas łączenia kanału Amaposta sprawdza go żądaniem GET do adresu kontroli stanu, jeśli został ustawiony, lub żądaniem OPTIONS do punktu końcowego.

Kanały Sandbox

Kanał testowy zachowuje się jak prawdziwy, ale nic nie opuszcza Amaposta. Zbuduj i przetestuj w nim integrację od początku do końca: posty są planowane, trafiają na antenę, publikują się lub kończą błędem i wywołują te same webhooki. Kanały testowe są bezpłatne w każdym planie i nie wliczają się do limitów kanałów.

Wybierz zachowanie po dodaniu:

  • Zawsze kończ powodzeniemKażdy post zostaje opublikowany.
  • Czasem kończ błędemZobacz błędy i ponowne próby bez czekania na prawdziwą awarię.
  • Zawsze kończ błędemPrzetestuj obsługę zdarzenia post.failed.
  • Połączenie wygasłoSprawdź wygląd alertów i linków do ponownego połączenia po wygaśnięciu dostępu.

Reguły platformy

Wymagania poszczególnych typów kanałów. Kontrole używają tych samych limitów, więc większość problemów pojawia się przed zaplanowaniem posta, a nie dopiero przy publikacji.

Platforma Post Tytuł Tekst Hashtagi Multimedia
YouTube Film TytułWymagane, limit znaków: 100 OpisLimit znaków: 5000 Wysyłane jako tagi, maksymalnie 60 MP4, MOV, WebM, AVI, MKV; do 256 GB; Od 1 s do 12 godz.
Konta bez zweryfikowanego numeru telefonu mogą przesyłać filmy do 15 minut i nie mogą ustawiać własnych miniatur. Każde przesłanie zużywa limit API; domyślny limit Google pozwala na około sześć przesłań dziennie na aplikację.
Instagram Obraz Brak tytułu PodpisLimit znaków: 2200 Dodawane do tekstu, maksymalnie 30 JPEG; do 8 MB
Film Brak tytułu PodpisLimit znaków: 2200 Dodawane do tekstu, maksymalnie 30 MP4, MOV; do 300 MB; Od 3 s do 15 min
Wymaga konta Instagram Business lub Creator. Instagram pozwala opublikować przez API 50 postów na konto w każdym ruchomym okresie 24 godzin. Na Instagram nie można publikować postów zawierających tylko tekst.
TikTok Obraz TytułLimit znaków: 90 OpisLimit znaków: 4000 Dodawane do tekstu JPEG, WebP; do 20 MB
Film Brak tytułu PodpisLimit znaków: 2200 Dodawane do tekstu MP4, MOV, WebM; do 4 GB; Od 3 s do 10 min
Posty z aplikacji, które nie przeszły audytu TikTok, są widoczne tylko dla autora. TikTok wybiera okładkę z klatki filmu; własne obrazy okładek nie są obsługiwane. Na TikTok nie można publikować postów zawierających tylko tekst.
X Tekst Brak tytułu PostWymagane, do 280 (linki liczą się jako 23 znaki, emoji jako 2) Dodawane do tekstu Brak
Obraz Brak tytułu PostDo 280 (linki liczą się jako 23 znaki, emoji jako 2) Dodawane do tekstu JPEG, PNG, WebP, GIF; do 5 MB
Film Brak tytułu PostDo 280 (linki liczą się jako 23 znaki, emoji jako 2) Dodawane do tekstu MP4, MOV; do 512 MB; Od 0,5 s do 2:20 min
Jeśli używasz własnej aplikacji deweloperskiej X, posty zużywają jej środki na API w modelu płatności za użycie. Hashtagi wliczają się do limitu znaków.
Facebook Tekst Brak tytułu PostWymagane, limit znaków: 63 206 Dodawane do tekstu Brak
Obraz Brak tytułu PodpisLimit znaków: 63 206 Dodawane do tekstu JPEG, PNG, GIF, WebP; do 10 MB
Film TytułLimit znaków: 255 OpisLimit znaków: 63 206 Dodawane do tekstu MP4, MOV; do 1 GB; Od 1 s do 20 min
Publikuje tylko na stronach; API nie pozwala publikować w profilach osobistych.
Własne API Tekst TytułBez limitu długości OpisBez limitu długości Wysyłane jako tagi Brak
Obraz TytułBez limitu długości OpisBez limitu długości Wysyłane jako tagi JPEG, PNG, WebP, GIF
Film TytułBez limitu długości OpisBez limitu długości Wysyłane jako tagi MP4, MOV, WebM
Każde żądanie jest podpisane nagłówkiem HMAC-SHA256, aby można było sprawdzić, czy pochodzi z Amaposta. Odpowiedz kodem 2xx i opcjonalnymi danymi JSON {"id": "…", "url": "…"}. Odpowiedzi 408, 429 i 5xx powodują ponowienie z rosnącym odstępem; 401/403 oznaczają kanał jako wymagający ponownego połączenia; inne 4xx kończą wysyłkę błędem, aby można było rozwiązać problem i spróbować ponownie.
Sandbox Tekst TytułLimit znaków: 200 OpisLimit znaków: 5000 Dodawane do tekstu, maksymalnie 30 Brak
Obraz TytułLimit znaków: 200 OpisLimit znaków: 5000 Dodawane do tekstu, maksymalnie 30 JPEG, PNG, WebP, GIF
Film TytułLimit znaków: 200 OpisLimit znaków: 5000 Dodawane do tekstu, maksymalnie 30 MP4, MOV, WebM
Publikowanie zajmuje chwilę, aby można było obserwować zmianę statusu na żywo.