Autentisering
Opprett en API-nøkkel i kontrollpanelet under Innstillinger, API og webhooks. Nøkler begynner med ss_live_, tilhører ett arbeidsområde og kan begrenses til bestemte prosjekter. Send nøkkelen som et bearer-token i hver forespørsel:
curl https://www.amaposta.com/api/v1/me \
-H "Authorization: Bearer ss_live_…"
Svaret oppgir nøkkelens navn, tilgangsomfang og arbeidsområdet. Hver nøkkel har ett eller flere tilgangsomfang:
| Tilgangsomfang | Tillater |
|---|---|
content:read | Les prosjekter, kanaler, innlegg og medier. |
content:write | Last opp medier og opprett eller rediger innlegg. |
posts:publish | Planlegg og publiser uten gjennomgang. Uten dette sendes innlegg til gjennomgangsinnboksen i prosjekter som bruker godkjenninger, og forblir utkast alle andre steder. |
Hver nøkkel kan gjøre 120 forespørsler i minuttet. Over dette får du 429 med koden rate_limited. Vent litt og prøv igjen.
Prosjekter og kanaler
Innlegg tilhører et prosjekt. List opp prosjektene nøkkelen din kan se, og deretter kanalene i ett av dem. Du trenger kanalens ID for å velge den som mål eller overstyre teksten.
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 innleggstypene den supports.
Last opp medier
Bilder og videoer lastes opp én gang per prosjekt og kan brukes i et ubegrenset antall innlegg. Det finnes tre måter å laste opp på.
Direkte opplasting
Send filen som multipart-skjemadata i et felt med navnet file. Best for filer opptil noen hundre MB.
curl https://www.amaposta.com/api/v1/projects/$PROJECT_ID/media \
-H "Authorization: Bearer $AMAPOSTA_KEY" \
-F "[email protected]"
Forhåndssignert opplasting for store filer
Be om en opplastings-URL, send bytene direkte til lagring med PUT, og gi deretter Amaposta beskjed om at du er ferdig.
# 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"
Importer fra en URL
Gi Amaposta en offentlig URL, så lastes filen ned i bakgrunnen. Du kan også hoppe over dette trinnet og sende media_url når du oppretter innlegget.
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 opplasting returnerer et medieobjekt. Dets status går fra pending til processing til ready (eller failed, med en error). Når det er behandlet, inneholder det width, height, duration_ms og et miniatyrbilde. Spør jevnlig med GET /api/v1/media/{id} eller lytt etter webhooken media.ready. Feltet url som returneres, er signert og gyldig i 12 timer.
Opprett et innlegg
POST /api/v1/projects/{project_id}/posts oppretter ett innlegg med én levering for hver kanal. Amaposta tilpasser det per plattform: titler sendes bare dit det finnes et tittelfelt, og emneknagger blir tagger på YouTube og 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 | Hva det gjør |
|---|---|
kind | text, image eller video. Påkrevd. |
title | Brukes av plattformer med et tittelfelt: YouTube, TikTok-bildeinnlegg og Facebook-videoer. |
description | Bildeteksten, beskrivelsen eller innleggsteksten. Godtas også som body, caption eller text. |
hashtags | En liste, med eller uten #. |
media_id, media_url | En opplastet medie-ID eller en offentlig URL som Amaposta laster ned for deg. Påkrevd for bilde- og videoinnlegg. |
cover_media_id, cover_url | Et forsidebilde for videoer, der plattformen støtter det. |
channels | Kanal-ID-er å publisere til. Utelat feltet for å bruke alle aktive kanaler i prosjektet som støtter denne innleggstypen. |
overrides | Endringer per kanal, med kanal-ID som nøkkel: title, description, hashtags og plattformens options, som YouTubes privacy. |
schedule | mode er at (med et ISO 8601-at), now eller queue for neste ledige publiseringstidspunkt. Utelat feltet for å opprette et utkast. |
external_ref | Din egen referanse, som returneres på innlegget og i leveringer til egne API-er. |
metadata | JSON med valgfri struktur lagret med innlegget. Ta med "pipeline" for å merke generert innhold. Kontrollpanelet viser det, og webhooks rapporterer opprinnelsen som pipeline. |
Svaret er innlegget, med én oppføring i deliveries per kanal.
Trygge nye forsøk
Nettverk kan miste forespørsler. Send en Idempotency-Key-header når du oppretter et innlegg, så vil et nytt forsøk med samme nøkkel returnere innlegget fra første forsøk i stedet for å opprette et nytt. Bruk noe stabilt fra din side, som en jobb- eller episode-ID. Nøkler kuttes til 200 tegn.
Planlegg og publiser
Planlegg et utkast, publiser det nå, legg det i køen eller fjern det 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"}'
atPubliserer til det oppgitte tidspunktet, opptil to år frem i tid.nowPubliserer med en gang.queueTar neste ledige publiseringstidspunkt for innleggets kanaler i løpet av de neste 12 ukene.unscheduleFlytter innlegget tilbake til utkast.
Før noe planlegges, kjøres de samme kontrollene som i innleggsredigeringen. Hvis en mislykkes, returnerer forespørselen 400 med en melding som Rett dette før planlegging: YouTube trenger en tittel.
Planlegging krever tilgangsomfanget posts:publish, eller et prosjekt med godkjenninger slått på. I så fall venter innlegget i gjennomgangsinnboksen.
Les innlegg og leveringer
List opp innleggene i et prosjekt, filtrert etter status (kommaseparerte statuser eller inbox, queue eller history), et from/to-tidsrom, 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 innlegg har en samlet status (draft, in_review, changes_requested, ready, scheduled, publishing, published, partial eller failed) og én levering 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
}
]
Leveringsstatusene er pending, scheduled, publishing, processing, published, failed og cancelled. DELETE /api/v1/posts/{post_id} fjerner et innlegg.
Feil
Alle feil har samme struktur: et error-objekt med en stabil code, en message du kan vise til brukere, og noen ganger fields (meldinger per 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 | Forespørselen kan ikke utføres som angitt, for eksempel planlegging av et innlegg som ikke består kontrollene. |
| 401 | unauthorized | API-nøkkelen mangler, er feil eller er tilbakekalt. |
| 402 | plan_limit | Arbeidsområdets abonnement tillater ikke dette. limit angir hvilken grense. |
| 403 | forbidden | Nøkkelen mangler et tilgangsomfang eller tilgang til prosjektet. |
| 404 | not_found | Prosjektet, innlegget, mediefilen eller endepunktet finnes ikke. |
| 409 | conflict | Endringen er i konflikt med gjeldende tilstand, for eksempel redigering av et innlegg som allerede publiseres. |
| 422 | validation | Ett eller flere felt må rettes. Se fields. |
| 429 | rate_limited | Mer enn 120 forespørsler i minuttet med denne nøkkelen. |
| 502 | provider_error | En plattform avviste forespørselen eller feilet. hint forteller hva du bør gjøre. |
Webhooks
Legg til et endepunkt under Innstillinger, API og webhooks, velg ønskede hendelser og kopier signeringshemmeligheten. Amaposta sender JSON med POST til URL-en din for hver hendelse. Alt annet enn et 2xx-svar, eller manglende svar innen 15 sekunder, prøves på nytt med økende ventetid. Endepunkter som fortsetter å feile, slås av med et varsel til administratorer.
| Hendelse | Sendes når |
|---|---|
post.created | Et innlegg ble opprettet (kontrollpanel eller API) |
post.scheduled | Et innlegg ble planlagt |
post.approved | Et innlegg ble godkjent |
post.published | Et innlegg ble publisert på en kanal |
post.failed | Et innlegg kunne ikke publiseres på en kanal |
channel.connected | En kanal ble koblet til eller koblet til på nytt |
channel.disconnected | En kanal mistet tilkoblingen |
media.ready | En opplasting ble ferdig behandlet |
media.failed | En opplasting 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=…"
}
}
Kontroller signaturen
X-Amaposta-Signature er t=<unix seconds>,v1=<hex>, der v1 er HMAC_SHA256(secret, t + "." + body) over den rå forespørselskroppen. Beregn den selv, sammenlign i konstant tid, og avvis gamle tidsstempler for å hindre gjenavspilling.
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", ""))
Egne API-kanaler
En egen API-kanal publiserer til et HTTPS-endepunkt du drifter: CMS-et ditt, et nyhetsbrevverktøy eller en plattform Amaposta ennå ikke dekker. Den vises i kalenderen og får kontroller, godkjenninger og nye forsøk som alle andre kanaler. Når et innlegg sendes ut, sender Amaposta én POST per 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- API-nøkkelen din. Headernavnet og prefikset (
Bearersom standard) angis på kanalen. Idempotency-Key- Leverings-ID-en. Et nytt forsøk på samme levering sender samme nøkkel, slik at du kan hoppe over arbeid du allerede har gjort.
X-Amaposta-Delivery- Leverings-ID-en igjen, for loggene dine.
X-Amaposta-Signature- Signert som webhooks, med kanalens egen signeringshemmelighet.
Hvordan svare
- 2xxPublisert. Returner eventuelt
{"id": "…", "url": "…"}, så vises lenken på innlegget. - 401, 403Nøkkelen ble avvist. Kanalen merkes for ny tilkobling, og administratorer varsles. Ikke bruk disse ved ugyldig signatur.
- 5xx, 408, 429Midlertidig. Amaposta prøver igjen med økende ventetid.
- Andre 4xxInnlegget merkes som mislykket med meldingen din, og noen kan rette det og trykke Prøv igjen.
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 });
});
Endepunktet ditt må være tilgjengelig fra internett. Omdirigeringer følges ikke. Når du kobler til kanalen, kontrollerer Amaposta den med en GET til helsesjekk-URL-en hvis du angir en, eller en OPTIONS-forespørsel til endepunktet.
Sandbox-kanaler
En Sandbox-kanal oppfører seg som en ekte kanal, men ingenting forlater Amaposta. Bruk den til å bygge og teste integrasjonen fra ende til ende: innlegg planlegges, går på lufta, publiseres eller mislykkes og utløser de samme webhookene. Sandbox-kanaler er gratis i alle abonnementer og teller ikke mot kanalgrenser.
Velg hvordan den skal oppføre seg når du legger den til:
- Alltid vellykketAlle innlegg publiseres.
- Mislykkes av og tilSe feil og nye forsøk uten å vente på et ekte driftsavbrudd.
- Mislykkes alltidTest håndteringen av
post.failed. - Utløpt tilkoblingSe hvordan varsler og lenker for ny tilkobling ser ut når tilgangen utløper.
Plattformregler
Hva hver kanaltype godtar. Kontrollene bruker de samme grensene, så de fleste problemer vises før et innlegg planlegges, i stedet for når det publiseres.
| Plattform | Innlegg | Tittel | Tekst | Emneknagger | Medier |
|---|---|---|---|---|---|
| YouTube | Video | TittelPåkrevd, opptil 100 tegn | BeskrivelseOpptil 5 000 tegn | Sendes som tagger, opptil 60 | MP4, MOV, WebM, AVI, MKV; opptil 256 GB; 1 s til 12 t |
| Kontoer som ikke har bekreftet et telefonnummer, kan laste opp opptil 15 minutter og kan ikke angi egne miniatyrbilder. Hver opplasting bruker API-kvote. Googles standardkvote tillater omtrent seks opplastinger per dag per app. | |||||
| Bilde | Ingen tittel | BildetekstOpptil 2 200 tegn | Legges til i teksten, opptil 30 | JPEG; opptil 8 MB | |
| Video | Ingen tittel | BildetekstOpptil 2 200 tegn | Legges til i teksten, opptil 30 | MP4, MOV; opptil 300 MB; 3 s til 15 min | |
| Krever en Instagram-bedriftskonto eller skaperkonto. Instagram tillater 50 innlegg publisert via API per konto i en løpende periode på 24 timer. Rene tekstinnlegg er ikke mulig på Instagram. | |||||
| TikTok | Bilde | TittelOpptil 90 tegn | BeskrivelseOpptil 4 000 tegn | Legges til i teksten | JPEG, WebP; opptil 20 MB |
| Video | Ingen tittel | BildetekstOpptil 2 200 tegn | Legges til i teksten | MP4, MOV, WebM; opptil 4 GB; 3 s til 10 min | |
| Innlegg fra apper som ikke har fullført TikToks kontroll, er bare synlige for skaperen. TikTok velger forsiden fra et videobilde. Egne forsidebilder støttes ikke. Rene tekstinnlegg er ikke mulig på TikTok. | |||||
| X | Tekst | Ingen tittel | InnleggPåkrevd, opptil 280 (lenker teller som 23, emojier som 2) | Legges til i teksten | Ingen |
| Bilde | Ingen tittel | InnleggOpptil 280 (lenker teller som 23, emojier som 2) | Legges til i teksten | JPEG, PNG, WebP, GIF; opptil 5 MB | |
| Video | Ingen tittel | InnleggOpptil 280 (lenker teller som 23, emojier som 2) | Legges til i teksten | MP4, MOV; opptil 512 MB; 0,5 s til 2:20 min | |
| Med din egen X-utviklerapp bruker innlegg appens API-kreditter som betales per bruk. Emneknagger teller mot tegngrensen. | |||||
| Tekst | Ingen tittel | InnleggPåkrevd, opptil 63 206 tegn | Legges til i teksten | Ingen | |
| Bilde | Ingen tittel | BildetekstOpptil 63 206 tegn | Legges til i teksten | JPEG, PNG, GIF, WebP; opptil 10 MB | |
| Video | TittelOpptil 255 tegn | BeskrivelseOpptil 63 206 tegn | Legges til i teksten | MP4, MOV; opptil 1 GB; 1 s til 20 min | |
| Publiserer bare til sider. Personlige profiler kan ikke publiseres til gjennom API-et. | |||||
| Eget API | Tekst | TittelIngen lengdegrense | BeskrivelseIngen lengdegrense | Sendes som tagger | Ingen |
| Bilde | TittelIngen lengdegrense | BeskrivelseIngen lengdegrense | Sendes som tagger | JPEG, PNG, WebP, GIF | |
| Video | TittelIngen lengdegrense | BeskrivelseIngen lengdegrense | Sendes som tagger | MP4, MOV, WebM | |
| Hver forespørsel signeres med en HMAC-SHA256-header slik at du kan kontrollere at den kom fra Amaposta. Svar med 2xx og valgfri JSON {"id": "…", "url": "…"}. Svar med 408, 429 og 5xx prøves på nytt med økende ventetid. 401/403 merker kanalen for ny tilkobling. Andre 4xx markerer leveringen som mislykket, slik at du kan rette den og prøve igjen. | |||||
| Sandbox | Tekst | TittelOpptil 200 tegn | BeskrivelseOpptil 5 000 tegn | Legges til i teksten, opptil 30 | Ingen |
| Bilde | TittelOpptil 200 tegn | BeskrivelseOpptil 5 000 tegn | Legges til i teksten, opptil 30 | JPEG, PNG, WebP, GIF | |
| Video | TittelOpptil 200 tegn | BeskrivelseOpptil 5 000 tegn | Legges til i teksten, opptil 30 | MP4, MOV, WebM | |
| Publisering tar et øyeblikk slik at du kan se statusen endre seg direkte. | |||||