Autentisering
Skapa en API-nyckel i kontrollpanelen under Inställningar, API och webhooks. Nycklar börjar med ss_live_, hör till en arbetsyta och kan begränsas till vissa projekt. Skicka nyckeln som en bearer-token med varje begäran:
curl https://www.amaposta.com/api/v1/me \
-H "Authorization: Bearer ss_live_…"
Svaret anger nyckelns namn, dess behörigheter och arbetsytan. Varje nyckel har en eller flera behörigheter:
| Behörighet | Tillåter |
|---|---|
content:read | Läs projekt, kanaler, inlägg och media. |
content:write | Ladda upp media och skapa eller redigera inlägg. |
posts:publish | Schemalägg och publicera utan granskning. Utan denna behörighet går inlägg till granskningsinkorgen i projekt som använder godkännanden och förblir utkast överallt annars. |
Varje nyckel kan göra 120 anrop per minut. Därefter får du 429 med koden rate_limited; vänta en stund och försök igen.
Projekt och kanaler
Inlägg hör till ett projekt. Lista projekten som din nyckel kan se och sedan kanalerna i ett av dem. Du behöver en kanals ID för att välja den som mål eller anpassa dess text.
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"
En kanal har en provider (youtube, instagram, tiktok, x, facebook, custom eller sandbox), en status (active, expiring, needs_reconnect, error eller disabled) och inläggstyper som den supports.
Ladda upp media
Bilder och videor laddas upp en gång per projekt och kan användas i valfritt antal inlägg. Det finns tre sätt att göra det.
Direktuppladdning
Skicka filen som multipart-formulärdata i ett fält med namnet file. Passar bäst för filer upp till några hundra MB.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-F "[email protected]"
Försignerad uppladdning för stora filer
Begär en uppladdnings-URL, skicka byten direkt till lagringen med PUT och meddela sedan Amaposta att du är klar.
# 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"
Importera från en URL
Ge Amaposta en offentlig URL så hämtas filen i bakgrunden. Du kan också hoppa över detta steg och ange media_url när du skapar inlägget.
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"}'
Varje uppladdning returnerar ett mediaobjekt. Dess status går från pending till processing till ready (eller failed, med ett error). Efter bearbetningen innehåller det width, height, duration_ms och en miniatyrbild. Polla GET /api/v1/media/{id} eller lyssna efter webhooken media.ready. Den url som returneras är signerad och giltig i 12 timmar.
Skapa ett inlägg
POST /api/v1/projects/{project_id}/posts skapar ett inlägg med en leverans för varje kanal. Amaposta anpassar det till varje plattform: titlar används bara där det finns ett titelfält, hashtaggar blir taggar på YouTube och löpande text på övriga plattformar.
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
Fält
| Fält | Vad den gör |
|---|---|
kind | text, image eller video. Obligatoriskt. |
title | Används av plattformar med ett titelfält: YouTube, TikToks bildinlägg, Facebook-videor. |
description | Bildtexten, beskrivningen eller inläggstexten. Kan även anges som body, caption eller text. |
hashtags | En lista, med eller utan #. |
media_id, media_url | Ett ID för uppladdat media, eller en offentlig URL som Amaposta hämtar åt dig. Krävs för bild- och videoinlägg. |
cover_media_id, cover_url | En omslagsbild för videor, där plattformen stöder det. |
channels | ID:n för kanaler att publicera till. Utelämna detta för att använda alla aktiva kanaler i projektet som stöder den här typen av inlägg. |
overrides | Ändringar per kanal med kanal-ID som nyckel: title, description, hashtags och plattformens options, till exempel YouTubes privacy. |
schedule | mode är at (med ett ISO 8601-värde i at), now eller queue för nästa lediga publiceringstid. Utelämna det för att skapa ett utkast. |
external_ref | Din egen referens, som återges i inlägget och i leveranser till anpassade API:er. |
metadata | JSON med valfri struktur som lagras med inlägget. Inkludera "pipeline" för att märka genererat innehåll; kontrollpanelen visar det och webhooks anger ursprunget som pipeline. |
Svaret är inlägget, inklusive en post i deliveries per kanal.
Säkra återförsök
Begäranden kan försvinna i nätverket. Skicka en Idempotency-Key-header när du skapar ett inlägg, så returnerar ett nytt försök med samma nyckel inlägget från det första försöket i stället för att skapa ett till. Använd något stabilt från ditt system, till exempel ett jobb- eller avsnitts-ID. Nycklar kapas vid 200 tecken.
Schemalägg och publicera
Schemalägg ett utkast, publicera det direkt, lägg det i kön eller ta bort det från kalendern med 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"}'
atPublicerar vid den angivna tiden, upp till två år i förväg.nowPublicerar direkt.queueVäljer nästa lediga publiceringstid för inläggets kanaler under de kommande 12 veckorna.unscheduleFlyttar tillbaka inlägget till utkast.
Innan något schemaläggs körs samma kontroller som i redigeraren. Om någon misslyckas returnerar begäran 400 med ett meddelande som Åtgärda detta före schemaläggning: YouTube behöver en titel.
Schemaläggning kräver behörigheten posts:publish, eller ett projekt med godkännanden aktiverade, där inlägget då väntar i granskningsinkorgen.
Läs inlägg och leveranser
Lista ett projekts inlägg, filtrerade efter status (kommaseparerade statusvärden, eller inbox, queue eller history), ett intervall med from/to, limit och offset. Svaret är {"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"
Ett inlägg har en övergripande status (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial eller failed) och en leverans per kanal:
"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
}
]
Leveransstatus är pending, scheduled, publishing, processing, published, failed och cancelled. DELETE /api/v1/posts/{post_id} tar bort ett inlägg.
Fel
Alla fel har samma form: ett error-objekt med en stabil code, ett message som du kan visa för användare och ibland fields (meddelanden per fält) och en hint.
{
"error": {
"code": "validation",
"message": "Please fix the highlighted fields.",
"fields": {
"kind": "Use text, image or video."
}
}
}
| Status | Kod | Betydelse |
|---|---|---|
| 400 | bad_request | Begäran kan inte genomföras som angivet, till exempel schemaläggning av ett inlägg som inte klarar kontrollerna. |
| 401 | unauthorized | API-nyckeln saknas, är felaktig eller har återkallats. |
| 402 | plan_limit | Arbetsytans abonnemang tillåter inte detta; limit anger vilken gräns som gäller. |
| 403 | forbidden | Nyckeln saknar en behörighet eller åtkomst till projektet. |
| 404 | not_found | Inget sådant projekt, inlägg, media eller ändpunkt. |
| 409 | conflict | Ändringen är oförenlig med det aktuella tillståndet, till exempel redigering av ett inlägg som redan håller på att publiceras. |
| 422 | validation | Ett eller flera fält behöver rättas; se fields. |
| 429 | rate_limited | Fler än 120 anrop per minut med den här nyckeln. |
| 502 | provider_error | En plattform avvisade begäran eller misslyckades; hint anger vad du kan göra. |
Webhooks
Lägg till en ändpunkt under Inställningar, API och webhooks, välj önskade händelser och kopiera dess signeringshemlighet. Amaposta skickar JSON med POST till din URL för varje händelse. Alla svar utom 2xx, eller uteblivna svar inom 15 sekunder, leder till nya försök med ökande väntetid. Ändpunkter som fortsätter att misslyckas stängs av och administratörer meddelas.
| Händelse | Skickas när |
|---|---|
post.created | Ett inlägg skapades (kontrollpanel eller API) |
post.scheduled | Ett inlägg schemalades |
post.approved | Ett inlägg godkändes |
post.published | Ett inlägg publicerades på en kanal |
post.failed | Ett inlägg kunde inte publiceras på en kanal |
channel.connected | En kanal anslöts eller återanslöts |
channel.disconnected | En kanal förlorade anslutningen |
media.ready | En uppladdning har bearbetats klart |
media.failed | En uppladdning kunde inte bearbetas |
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=…"
}
}
Verifiera signaturen
X-Amaposta-Signature är t=<unix seconds>,v1=<hex>, där v1 är HMAC_SHA256(secret, t + "." + body) beräknat på den obearbetade begärandekroppen. Beräkna den själv, jämför i konstant tid och avvisa gamla tidsstämplar för att förhindra återuppspelning.
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", ""))
Kanaler med anpassat API
En kanal med anpassat API publicerar till en HTTPS-ändpunkt som du driver: ditt CMS, ett nyhetsbrevsverktyg eller en plattform som Amaposta ännu inte stöder. Den finns i kalendern och får kontroller, godkännanden och nya försök precis som alla andra kanaler. När ett inlägg publiceras skickar Amaposta en POST per leverans:
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- Din API-nyckel. Headernamnet och prefixet (
Bearersom standard) ställs in på kanalen. Idempotency-Key- Leveransens ID. Ett nytt försök med samma leverans skickar samma nyckel, så att du kan hoppa över arbete som redan har gjorts.
X-Amaposta-Delivery- Leveransens ID igen, för dina loggar.
X-Amaposta-Signature- Signeras som webhooks, med kanalens egen signeringshemlighet.
Så svarar du
- 2xxPublicerat. Returnera eventuellt
{"id": "…", "url": "…"}så visas länken på inlägget. - 401, 403Nyckeln avvisades. Kanalen markeras för återanslutning och administratörer meddelas. Använd inte dessa svar vid felaktig signatur.
- 5xx, 408, 429Tillfälligt. Amaposta försöker igen med ökande väntetid.
- Andra 4xxInlägget markeras som misslyckat med ditt meddelande, så att någon kan åtgärda det och trycka på Försök igen.
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 });
});
Din ändpunkt måste gå att nå från internet; omdirigeringar följs inte. När du ansluter kanalen kontrollerar Amaposta den med GET till din kontroll-URL om du har angett en, annars med en OPTIONS-begäran till ändpunkten.
Sandbox-kanaler
En sandbox-kanal fungerar som en riktig kanal, men ingenting lämnar Amaposta. Använd den för att bygga och testa hela din integration: inlägg schemaläggs, sänds, publiceras eller misslyckas och utlöser samma webhooks. Sandbox-kanaler är gratis med alla abonnemang och räknas inte mot kanalgränsen.
Välj hur den ska fungera när du lägger till den:
- Lyckas alltidAlla inlägg publiceras.
- Misslyckas då och dåSe fel och nya försök utan att vänta på ett riktigt avbrott.
- Misslyckas alltidTesta din hantering av
post.failed. - Utgången anslutningSe hur aviseringar och länkar för återanslutning ser ut när åtkomsten löper ut.
Plattformsregler
Vad varje kanaltyp tar emot. Kontrollerna använder samma gränser, så de flesta problem syns innan ett inlägg schemaläggs i stället för vid publiceringen.
| Plattform | Inlägg | Titel | Text | Hashtaggar | Media |
|---|---|---|---|---|---|
| YouTube | Video | TitelObligatoriskt, upp till 100 tecken | BeskrivningUpp till 5 000 tecken | Skickas som taggar, upp till 60 | MP4, MOV, WebM, AVI, MKV; upp till 256 GB; 1 s till 12 h |
| Konton som inte har verifierat ett telefonnummer kan ladda upp upp till 15 minuter och kan inte ange egna miniatyrbilder. Varje uppladdning förbrukar API-kvot; Googles standardkvot medger ungefär sex uppladdningar per dag och app. | |||||
| Bild | Ingen titel | BildtextUpp till 2 200 tecken | Läggs till i texten, upp till 30 | JPEG; upp till 8 MB | |
| Video | Ingen titel | BildtextUpp till 2 200 tecken | Läggs till i texten, upp till 30 | MP4, MOV; upp till 300 MB; 3 s till 15 min | |
| Kräver ett Instagram Business- eller Creator-konto. Instagram tillåter 50 API-publicerade inlägg per konto under en rullande 24-timmarsperiod. Inlägg med enbart text är inte möjliga på Instagram. | |||||
| TikTok | Bild | TitelUpp till 90 tecken | BeskrivningUpp till 4 000 tecken | Läggs till i texten | JPEG, WebP; upp till 20 MB |
| Video | Ingen titel | BildtextUpp till 2 200 tecken | Läggs till i texten | MP4, MOV, WebM; upp till 4 GB; 3 s till 10 min | |
| Inlägg från appar som inte har slutfört TikToks granskning är bara synliga för skaparen. TikTok väljer omslaget från en videobildruta; egna omslagsbilder stöds inte. Inlägg med enbart text är inte möjliga på TikTok. | |||||
| X | Text | Ingen titel | InläggObligatoriskt, upp till 280 (länkar räknas som 23, emoji som 2) | Läggs till i texten | Inga |
| Bild | Ingen titel | InläggUpp till 280 (länkar räknas som 23, emoji som 2) | Läggs till i texten | JPEG, PNG, WebP, GIF; upp till 5 MB | |
| Video | Ingen titel | InläggUpp till 280 (länkar räknas som 23, emoji som 2) | Läggs till i texten | MP4, MOV; upp till 512 MB; 0,5 s till 2:20 min | |
| Med din egen X-utvecklarapp använder inläggen appens API-krediter, som debiteras per användning. Hashtaggar räknas mot teckengränsen. | |||||
| Text | Ingen titel | InläggObligatoriskt, upp till 63 206 tecken | Läggs till i texten | Inga | |
| Bild | Ingen titel | BildtextUpp till 63 206 tecken | Läggs till i texten | JPEG, PNG, GIF, WebP; upp till 10 MB | |
| Video | TitelUpp till 255 tecken | BeskrivningUpp till 63 206 tecken | Läggs till i texten | MP4, MOV; upp till 1 GB; 1 s till 20 min | |
| Publicerar bara till sidor; personliga profiler kan inte publiceras till via API:et. | |||||
| Anpassat API | Text | TitelIngen längdgräns | BeskrivningIngen längdgräns | Skickas som taggar | Inga |
| Bild | TitelIngen längdgräns | BeskrivningIngen längdgräns | Skickas som taggar | JPEG, PNG, WebP, GIF | |
| Video | TitelIngen längdgräns | BeskrivningIngen längdgräns | Skickas som taggar | MP4, MOV, WebM | |
| Varje begäran signeras med en HMAC-SHA256-header så att du kan verifiera att den kommer från Amaposta. Svara med 2xx och eventuellt JSON {"id": "…", "url": "…"}. Svar med 408, 429 och 5xx leder till nya försök med ökande väntetid; 401/403 markerar kanalen för återanslutning; andra 4xx gör att leveransen misslyckas så att du kan åtgärda felet och försöka igen. | |||||
| Sandbox | Text | TitelUpp till 200 tecken | BeskrivningUpp till 5 000 tecken | Läggs till i texten, upp till 30 | Inga |
| Bild | TitelUpp till 200 tecken | BeskrivningUpp till 5 000 tecken | Läggs till i texten, upp till 30 | JPEG, PNG, WebP, GIF | |
| Video | TitelUpp till 200 tecken | BeskrivningUpp till 5 000 tecken | Läggs till i texten, upp till 30 | MP4, MOV, WebM | |
| Publiceringen tar en stund så att du kan se statusen ändras i realtid. | |||||