Gå til indhold

Udviklervejledning

Send opslag til Amaposta fra din egen indholdspipeline: Upload medier, opret et opslag til alle kanaler, planlæg det, og få besked, når det er udgivet.

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:

Kontrollér en nøgle
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:

TilladelseTillader
content:readLæs projekter, kanaler, opslag og medier.
content:writeUpload medier og opret eller rediger opslag.
posts:publishPlanlæ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.

Vis projekter og kanaler
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.

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

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.

Tre anmodninger
# 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.

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

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.

Opret et videoopslag, og føj det til køen
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

FeltHvad det gør
kindtext, image eller video. Påkrævet.
titleBruges af platforme med et titelfelt: YouTube, TikTok-fotoopslag, Facebook-videoer.
descriptionBilledteksten, beskrivelsen eller opslagsteksten. Accepteres også som body, caption eller text.
hashtagsEn liste, med eller uden #.
media_id, media_urlEt uploadet medie-id eller en offentlig URL, som Amaposta downloader for dig. Påkrævet til billed- og videoopslag.
cover_media_id, cover_urlEt forsidebillede til videoer, hvor platformen understøtter det.
channelsKanal-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.
schedulemode 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_refDin egen reference, som returneres på opslaget og i leveringer til eget API.
metadataValgfri 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.

Planlæg til et tidspunkt
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}.

Hvad der kommer, og ét opslag i detaljer
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[]
"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.

422 Unprocessable Entity
{
  "error": {
    "code": "validation",
    "message": "Please fix the highlighted fields.",
    "fields": {
      "kind": "Use text, image or video."
    }
  }
}
StatusKodeBetydning
400bad_requestAnmodningen kan ikke udføres som angivet, f.eks. planlægning af et opslag, der ikke består kontrollerne.
401unauthorizedAPI-nøglen mangler, er forkert eller tilbagekaldt.
402plan_limitArbejdsområdets abonnement tillader ikke dette; limit angiver grænsen.
403forbiddenNøglen mangler en tilladelse eller adgang til projektet.
404not_foundProjektet, opslaget, mediet eller endepunktet findes ikke.
409conflictÆndringen er i konflikt med den aktuelle tilstand, f.eks. redigering af et opslag, der allerede udgives.
422validationEt eller flere felter skal rettes; se fields.
429rate_limitedMere end 120 anmodninger i minuttet på denne nøgle.
502provider_errorEn 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ændelseSendes, når
post.createdEt opslag blev oprettet (kontrolpanel eller API)
post.scheduledEt opslag blev planlagt
post.approvedEt opslag blev godkendt
post.publishedEt opslag blev udgivet på en kanal
post.failedEt opslag kunne ikke udgives på en kanal
channel.connectedEn kanal blev tilsluttet eller fik genoprettet forbindelsen
channel.disconnectedEn kanal mistede forbindelsen
media.readyEn upload blev færdigbehandlet
media.failedEn upload kunne ikke behandles
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=…"
  }
}

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.

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

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:

Hvad dit endepunkt modtager
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" }
}

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.
En modtager i 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 });
});

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.
Instagram 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.
Facebook 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.