Godkendelse
Opret en API-nøgle i kontrolpanelet under Indstillinger, API og webhooks. Nøgler begynder med ss_live_, tilhører ét arbejdsområde og kan begrænses til bestemte projekter. Send nøglen som et bearer-token med hver anmodning:
curl https://www.amaposta.com/api/v1/me \
-H "Authorization: Bearer ss_live_…"
Svaret angiver nøglen, dens tilladelser og arbejdsområdet. Hver nøgle har en eller flere tilladelser:
| Tilladelse | Tillader |
|---|---|
content:read | Læs projekter, kanaler, opslag og medier. |
content:write | Upload medier og opret eller rediger opslag. |
posts:publish | Planlæg og udgiv uden gennemgang. Uden denne tilladelse sendes opslag til indbakken til gennemgang i projekter, der bruger godkendelser, og forbliver kladder alle andre steder. |
Hver nøgle kan sende 120 anmodninger i minuttet. Derefter får du 429 med koden rate_limited; vent et øjeblik, og prøv igen.
Projekter og kanaler
Opslag hører til i et projekt. Hent de projekter, din nøgle kan se, og derefter kanalerne i et af dem. Du skal bruge en kanals id for at udgive på den eller tilpasse dens tekst.
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) og de opslagstyper, den supports.
Upload medier
Billeder og videoer uploades én gang pr. projekt og kan bruges i et vilkårligt antal opslag. Der er tre veje ind.
Direkte upload
Send filen som multipart-formulardata i et felt med navnet file. Bedst til filer på op til nogle få hundrede MB.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-F "[email protected]"
Forhåndssigneret upload til store filer
Anmod om en upload-URL, send dataene direkte til lageret med PUT, og giv derefter Amaposta besked om, at du er færdig.
# 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"
Importér fra en URL
Giv Amaposta en offentlig URL, så downloades filen i baggrunden. Du kan også springe dette trin over og angive media_url, når du opretter opslaget.
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"}'
Hver upload returnerer et medieobjekt. Dets status går fra pending til processing til ready (eller failed med en error). Efter behandling indeholder det width, height, duration_ms og et miniaturebillede. Forespørg løbende på GET /api/v1/media/{id}, eller lyt efter webhooken media.ready. Den returnerede url er signeret og gyldig i 12 timer.
Opret et opslag
POST /api/v1/projects/{project_id}/posts opretter ét opslag med en levering til hver kanal. Amaposta tilpasser det til hver platform: Titler sendes kun, hvor der er et titelfelt, hashtags bliver til tags på YouTube og til tekst andre steder.
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
Felter
| Felt | Hvad det gør |
|---|---|
kind | text, image eller video. Påkrævet. |
title | Bruges af platforme med et titelfelt: YouTube, TikTok-fotoopslag, Facebook-videoer. |
description | Billedteksten, beskrivelsen eller opslagsteksten. Accepteres også som body, caption eller text. |
hashtags | En liste, med eller uden #. |
media_id, media_url | Et uploadet medie-id eller en offentlig URL, som Amaposta downloader for dig. Påkrævet til billed- og videoopslag. |
cover_media_id, cover_url | Et forsidebillede til videoer, hvor platformen understøtter det. |
channels | Kanal-id'er at udgive på. Udelad feltet for at bruge alle aktive kanaler i projektet, der understøtter denne opslagstype. |
overrides | Ændringer pr. kanal med kanal-id som nøgle: title, description, hashtags og platformens options, såsom YouTubes privacy. |
schedule | mode er at (med at i ISO 8601-format), now eller queue for den næste ledige udgivelsestid. Udelad feltet for at oprette en kladde. |
external_ref | Din egen reference, som returneres på opslaget og i leveringer til eget API. |
metadata | Valgfri JSON-struktur, der gemmes med opslaget. Medtag "pipeline" for at markere genereret indhold; kontrolpanelet viser det, og webhooks rapporterer oprindelsen som pipeline. |
Svaret er opslaget med én post i deliveries pr. kanal.
Sikre gentagne forsøg
Netværk kan miste anmodninger. Send en Idempotency-Key-header, når du opretter et opslag, så returnerer et nyt forsøg med samme nøgle opslaget fra første forsøg i stedet for at oprette endnu et. Brug noget stabilt fra dit system, f.eks. et opgave- eller episode-id. Nøgler afkortes til 200 tegn.
Planlæg og udgiv
Planlæg en kladde, udgiv den nu, føj den til køen, eller fjern den fra kalenderen 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"}'
atUdgiver på det angivne tidspunkt, op til to år frem.nowUdgiver med det samme.queueTager den næste ledige udgivelsestid for opslagets kanaler i de næste 12 uger.unscheduleFlytter opslaget tilbage til kladder.
Før noget planlægges, køres de samme kontroller som i redigeringsværktøjet. Hvis en kontrol fejler, returnerer anmodningen 400 med en besked såsom Ret dette før planlægning: YouTube kræver en titel.
Planlægning kræver tilladelsen posts:publish eller et projekt med godkendelser slået til, hvor opslaget venter i indbakken til gennemgang.
Læs opslag og leveringer
Vis et projekts opslag filtreret efter status (kommaseparerede statusser eller inbox, queue eller history), en periode med from/to, limit og offset. Svaret er {"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"
Et opslag har en samlet status (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial eller failed) og én levering pr. 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
}
]
Leveringsstatusser er pending, scheduled, publishing, processing, published, failed og cancelled. DELETE /api/v1/posts/{post_id} fjerner et opslag.
Fejl
Alle fejl har samme struktur: et error-objekt med en stabil code, en message, du kan vise til brugere, og nogle gange fields (beskeder pr. felt) og et hint.
{
"error": {
"code": "validation",
"message": "Please fix the highlighted fields.",
"fields": {
"kind": "Use text, image or video."
}
}
}
| Status | Kode | Betydning |
|---|---|---|
| 400 | bad_request | Anmodningen kan ikke udføres som angivet, f.eks. planlægning af et opslag, der ikke består kontrollerne. |
| 401 | unauthorized | API-nøglen mangler, er forkert eller tilbagekaldt. |
| 402 | plan_limit | Arbejdsområdets abonnement tillader ikke dette; limit angiver grænsen. |
| 403 | forbidden | Nøglen mangler en tilladelse eller adgang til projektet. |
| 404 | not_found | Projektet, opslaget, mediet eller endepunktet findes ikke. |
| 409 | conflict | Ændringen er i konflikt med den aktuelle tilstand, f.eks. redigering af et opslag, der allerede udgives. |
| 422 | validation | Et eller flere felter skal rettes; se fields. |
| 429 | rate_limited | Mere end 120 anmodninger i minuttet på denne nøgle. |
| 502 | provider_error | En platform afviste eller fejlede; hint angiver, hvad du skal gøre. |
Webhooks
Tilføj et endepunkt under Indstillinger, API og webhooks, vælg de ønskede hændelser, og kopiér signeringshemmeligheden. Amaposta sender JSON med POST til din URL for hver hændelse. Alle svar, der ikke er 2xx, eller manglende svar inden for 15 sekunder forsøges igen med stigende intervaller, og endepunkter, der bliver ved med at fejle, slås fra med besked til administratorer.
| Hændelse | Sendes, når |
|---|---|
post.created | Et opslag blev oprettet (kontrolpanel eller API) |
post.scheduled | Et opslag blev planlagt |
post.approved | Et opslag blev godkendt |
post.published | Et opslag blev udgivet på en kanal |
post.failed | Et opslag kunne ikke udgives på en kanal |
channel.connected | En kanal blev tilsluttet eller fik genoprettet forbindelsen |
channel.disconnected | En kanal mistede forbindelsen |
media.ready | En upload blev færdigbehandlet |
media.failed | En upload kunne ikke behandles |
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=…"
}
}
Kontrollér signaturen
X-Amaposta-Signature er t=<unix seconds>,v1=<hex>, hvor v1 er HMAC_SHA256(secret, t + "." + body) over anmodningens rå indhold. Beregn den selv, sammenlign i konstant tid, og afvis gamle tidsstempler for at forhindre genafspilning.
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 eget API
En kanal med eget API udgiver til et HTTPS-endepunkt, du driver: dit CMS, et nyhedsbrevsværktøj eller en platform, Amaposta endnu ikke dækker. Den findes i kalenderen og får kontroller, godkendelser og gentagne forsøg som alle andre kanaler. Når et opslag udgives, sender Amaposta én POST pr. levering:
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-nøgle. Headernavnet og præfikset (
Bearersom standard) angives på kanalen. Idempotency-Key- Leverings-id'et. Et nyt forsøg på samme levering sender samme nøgle, så du kan springe allerede udført arbejde over.
X-Amaposta-Delivery- Leverings-id'et igen, til dine logs.
X-Amaposta-Signature- Signeret som webhooks med kanalens egen signeringshemmelighed.
Sådan svarer du
- 2xxUdgivet. Returnér eventuelt
{"id": "…", "url": "…"}, så vises linket på opslaget. - 401, 403Nøglen blev afvist. Kanalen markeres til genoprettelse af forbindelse, og administratorer får besked. Brug ikke disse til en forkert signatur.
- 5xx, 408, 429Midlertidigt. Amaposta prøver igen med stigende intervaller.
- Andre 4xxOpslaget markeres som mislykket med din besked, og en person kan rette det og trykke på Prøv 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 });
});
Dit endepunkt skal kunne nås fra internettet; omdirigeringer følges ikke. Når du tilslutter kanalen, kontrollerer Amaposta den med GET til din kontrol-URL, hvis du har angivet en, eller med en OPTIONS-anmodning til endepunktet.
Sandbox-kanaler
En Sandbox-kanal opfører sig som en rigtig kanal, men intet forlader Amaposta. Brug den til at bygge og teste din integration fra ende til ende: Opslag planlægges, går i luften, udgives eller mislykkes og udløser de samme webhooks. Sandbox-kanaler er gratis på alle abonnementer og tæller ikke med i kanalgrænser.
Vælg, hvordan den skal opføre sig, når du tilføjer den:
- Lykkes altidAlle opslag udgives.
- Fejl af og tilSe fejl og gentagne forsøg uden at vente på et rigtigt nedbrud.
- Fejler altidTest din håndtering af
post.failed. - Udløbet forbindelseSe, hvordan advarsler og links til genoprettelse af forbindelse ser ud, når adgang udløber.
Platformregler
Hvad hver kanaltype accepterer. Kontrollerne bruger de samme grænser, så de fleste problemer viser sig, før et opslag planlægges, frem for når det udgives.
| Platform | Opslag | Titel | Tekst | Hashtags | Medier |
|---|---|---|---|---|---|
| YouTube | Video | TitelPåkrævet, op til 100 tegn | BeskrivelseOp til 5.000 tegn | Sendes som tags, op til 60 | MP4, MOV, WebM, AVI, MKV; op til 256 GB; 1 s til 12 t |
| Konti uden bekræftet telefonnummer kan uploade op til 15 minutter og kan ikke angive brugerdefinerede miniaturebilleder. Hver upload bruger API-kvote; Googles standardkvote tillader cirka seks uploads pr. dag pr. app. | |||||
| Billede | Ingen titel | BilledtekstOp til 2.200 tegn | Føjes til teksten, op til 30 | JPEG; op til 8 MB | |
| Video | Ingen titel | BilledtekstOp til 2.200 tegn | Føjes til teksten, op til 30 | MP4, MOV; op til 300 MB; 3 s til 15 min | |
| Kræver en Instagram Business- eller Creator-konto. Instagram tillader 50 API-udgivne opslag pr. konto i en løbende periode på 24 timer. Opslag med kun tekst er ikke mulige på Instagram. | |||||
| TikTok | Billede | TitelOp til 90 tegn | BeskrivelseOp til 4.000 tegn | Føjes til teksten | JPEG, WebP; op til 20 MB |
| Video | Ingen titel | BilledtekstOp til 2.200 tegn | Føjes til teksten | MP4, MOV, WebM; op til 4 GB; 3 s til 10 min | |
| Opslag fra apps, der ikke har gennemført TikToks kontrol, er kun synlige for indholdsskaberen. TikTok vælger forsiden fra et videobillede; brugerdefinerede forsidebilleder understøttes ikke. Opslag med kun tekst er ikke mulige på TikTok. | |||||
| X | Tekst | Ingen titel | OpslagPåkrævet, op til 280 (links tæller som 23, emojis som 2) | Føjes til teksten | Ingen |
| Billede | Ingen titel | OpslagOp til 280 (links tæller som 23, emojis som 2) | Føjes til teksten | JPEG, PNG, WebP, GIF; op til 5 MB | |
| Video | Ingen titel | OpslagOp til 280 (links tæller som 23, emojis som 2) | Føjes til teksten | MP4, MOV; op til 512 MB; 0,5 s til 2:20 min | |
| Med din egen X-udviklerapp bruger opslag dens API-kreditter, som afregnes efter forbrug. Hashtags tæller med i tegngrænsen. | |||||
| Tekst | Ingen titel | OpslagPåkrævet, op til 63.206 tegn | Føjes til teksten | Ingen | |
| Billede | Ingen titel | BilledtekstOp til 63.206 tegn | Føjes til teksten | JPEG, PNG, GIF, WebP; op til 10 MB | |
| Video | TitelOp til 255 tegn | BeskrivelseOp til 63.206 tegn | Føjes til teksten | MP4, MOV; op til 1 GB; 1 s til 20 min | |
| Udgiver kun på sider; der kan ikke udgives på personlige profiler via API'et. | |||||
| Eget API | Tekst | TitelIngen længdegrænse | BeskrivelseIngen længdegrænse | Sendes som tags | Ingen |
| Billede | TitelIngen længdegrænse | BeskrivelseIngen længdegrænse | Sendes som tags | JPEG, PNG, WebP, GIF | |
| Video | TitelIngen længdegrænse | BeskrivelseIngen længdegrænse | Sendes som tags | MP4, MOV, WebM | |
| Hver anmodning signeres med en HMAC-SHA256-header, så du kan kontrollere, at den kom fra Amaposta. Svar med 2xx og eventuelt JSON {"id": "…", "url": "…"}. Svar med 408, 429 og 5xx forsøges igen med stigende intervaller; 401/403 markerer kanalen til genoprettelse af forbindelse; andre 4xx får leveringen til at mislykkes, så du kan rette fejlen og prøve igen. | |||||
| Sandbox | Tekst | TitelOp til 200 tegn | BeskrivelseOp til 5.000 tegn | Føjes til teksten, op til 30 | Ingen |
| Billede | TitelOp til 200 tegn | BeskrivelseOp til 5.000 tegn | Føjes til teksten, op til 30 | JPEG, PNG, WebP, GIF | |
| Video | TitelOp til 200 tegn | BeskrivelseOp til 5.000 tegn | Føjes til teksten, op til 30 | MP4, MOV, WebM | |
| Udgivelse tager et øjeblik, så du kan se status ændre sig live. | |||||