Inloggen Start gratis proefperiode

Haal uw artikelen op.
Publiceer ze op uw manier.

Elk artikel dat wij voor u schrijven kan via HTTP worden gelezen: de titel, de metadata, de Markdown, de HTML, de hero-afbeelding en de FAQ. Neem ze op in uw Next.js-, Astro- of aangepaste site wanneer uw build draait, zet ze live en geef ons het adres door waarop elk artikel is uitgekomen.

Eén bearer token. JSON in, JSON uit. Geen SDK om te installeren en niets om te configureren behalve een sleutel.

De webhook pusht. Met de API kunt u pullen.

Ze dragen hetzelfde artikel in dezelfde vorm, dus een parser die voor de ene is geschreven leest de andere ongewijzigd. Het verschil is wie het gesprek begint.

De webhook, wanneer uw site op elk moment een post kan ontvangen

Wij roepen uw endpoint aan zodra een artikel klaar is, en opnieuw wanneer het verandert. Niets om te pollen, niets om in te plannen. WordPress, Shopify, Ghost, een Zapier-trigger, of een route die u zelf heeft geschreven.

De API, wanneer uw site als één geheel wordt gebouwd en uitgerold

Een statische site kan niet om half zeven 's ochtends een bericht aannemen, eerst moet er iets opnieuw worden gebouwd. Daarom vraagt uw build op wat er klaarstaat, neemt het mee en geeft ons daarna het adres door. U kiest wanneer.

Allebei, als u dat wilt

Het zijn aparte koppelingen en de ene sluit de andere niet uit. Een webhook die een nieuwsbrief voedt en een API die de website voedt, is een normale opzet.

Eén sleutel, verzonden als bearer token.

Maak een sleutel in het dashboard onder Settings, daarna Connections. Die wordt één keer getoond, wanneer hij wordt gemaakt, omdat alleen de hash wordt opgeslagen: als u hem kwijtraakt, trek hem dan in en maak een nieuwe. Een sleutel leest elke site in het account en wordt vanuit hetzelfde scherm ingetrokken.

Elke aanvraag

Authorization: Bearer sns_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json

Controleer of het werkt

curl https://seonis.ai/api/v1/me \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "organisation": { "id": 12, "name": "Peppervale", "country": "GB" },
  "key": {
    "name": "Production build",
    "prefix": "sns_live_ab",
    "created_at": "2026-09-06T09:12:44+00:00",
    "last_used_at": "2026-09-06T09:31:02+00:00"
  },
  "sites": 2
}

Rate limit

120 aanvragen per minuut, geteld voor de sleutel in plaats van voor het adres waar die vandaan komt, omdat build runners adressen delen. Daarboven krijgt u 429 met de standaardheaders Retry-After en X-RateLimit. Artikelen ophalen voor een build is een handvol aanvragen, dus dit is geen limiet die u per ongeluk zou moeten bereiken.

Houd de sleutel uit uw repository

Deze leest alles wat wij voor uw account hebben geschreven, ook artikelen die nog niet zijn gepubliceerd. Zet hem in uw buildomgeving, niet in uw broncode. Trek hem hier meteen in zodra hij ergens staat waar hij niet hoort, en alles wat hem gebruikt krijgt direct een 401.

Vijf in totaal, en vier zijn alleen-lezen.

Alles staat onder /api/v1/. De versie zit vanaf dag één in het pad, zodat er ooit een v2 kan bestaan zonder te breken wat u vandaag schrijft.

GET /api/v1/me

Het account waartoe de sleutel behoort, en de eigen naam en prefix van de sleutel. Vooral nuttig voor één ding: u laten weten dat de sleutel in deze omgeving de sleutel is die u denkt dat het is.

Voorbeeld

curl https://seonis.ai/api/v1/me \
  -H "Authorization: Bearer $SEONIS_API_KEY"
GET /api/v1/sites

Elke site in het account. Op de id filtert de artikellijst, en het domein staat erbij zodat een buildscript kan matchen op iets wat het al kent in plaats van een id mee te dragen.

Voorbeeld

curl https://seonis.ai/api/v1/sites \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "sites": [
    {
      "id": 5,
      "name": "Peppervale",
      "domain": "peppervale.co.uk",
      "url": "https://peppervale.co.uk",
      "language": "en",
      "country": "GB",
      "market": "en-GB",
      "status": "active",
      "articles_published": 34,
      "created_at": "2026-06-02T11:04:19+00:00"
    }
  ]
}
GET /api/v1/articles

Een pagina met artikelen, nieuwste wijziging eerst, zonder de tekst. Gesorteerd op wanneer elk artikel voor het laatst is gewijzigd in plaats van wanneer het is geschreven, en dat maakt updated_since nuttig: een artikel dat al live staat kan later nog worden bewerkt, wanneer er een link in wordt gezet of weer uit wordt gehaald.

Queryparameters

Naam Wat het doet
site_id Eén site, uit /sites. Een id die niet in uw account staat geeft 404.
status Een van draft, qa, needs_repair, review, ready, published, failed. Alles anders geeft een 422 in plaats van een lege pagina. "ready" is wat een build wil: geschreven, gecontroleerd en nog nergens live.
updated_since ISO 8601, zoals 2026-09-06T00:00:00Z. Bewaar de tijdstempel van uw laatste run en geef die bij de volgende weer mee.
per_page Tot 100. De standaard is 25.
page Vanaf 1. meta.has_more geeft aan of u nog een keer moet opvragen.

Voorbeeld

curl -G https://seonis.ai/api/v1/articles \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -d site_id=5 \
  -d status=ready \
  -d updated_since=2026-09-01T00:00:00Z \
  -d per_page=50
{
  "articles": [
    {
      "id": 918,
      "site_id": 5,
      "language": "en",
      "status": "ready",
      "title": "How to choose a pepper grinder",
      "slug": "how-to-choose-a-pepper-grinder",
      "meta_title": "How to choose a pepper grinder | Peppervale",
      "meta_description": "Burr or blade, ceramic or steel: what matters in a grinder.",
      "meta_keywords": ["pepper grinder", "burr grinder"],
      "tags": ["Kitchen"],
      "excerpt": "A burr grinder gives an even grind; a blade one does not.",
      "key_takeaways": ["A burr grinder gives an even grind; a blade one does not."],
      "faq": [{ "question": "Ceramic or steel?", "answer": "Steel for pepper, ceramic for salt." }],
      "hero_image": { "url": "https://seonis.ai/storage/images/5/918.jpg", "alt": "A pepper grinder" },
      "infographic_url": null,
      "word_count": 1812,
      "published_url": null,
      "published_at": null,
      "updated_at": "2026-09-06T06:31:12+00:00",
      "created_at": "2026-09-05T02:14:55+00:00",
      "quality": { "seo_score": 88, "language_score": 96, "language_findings": [] }
    }
  ],
  "meta": { "page": 1, "per_page": 50, "total": 1, "last_page": 1, "has_more": false }
}
GET /api/v1/articles/{id}

Eén artikel, met alles wat de lijst weglaat: content_markdown, content_html, de FAQ als schema.org JSON-LD, klaar om in de pagina te zetten, en eventuele exchange-links die het artikel bevat.

De veldnamen zijn bewust dezelfde als die onze webhook verstuurt. Als u al een webhook-ontvanger heeft, leest dezelfde parser dit.

Voorbeeld

curl https://seonis.ai/api/v1/articles/918 \
  -H "Authorization: Bearer $SEONIS_API_KEY"
{
  "article": {
    "id": 918,
    "site_id": 5,
    "language": "en",
    "status": "ready",
    "title": "How to choose a pepper grinder",
    "slug": "how-to-choose-a-pepper-grinder",
    "meta_description": "Burr or blade, ceramic or steel: what matters in a grinder.",
    "content_markdown": "Grinders differ.\n\n## Burr or blade\n\nA **burr** grinder ...",
    "content_html": "<p>Grinders differ.</p>\n<h2>Burr or blade</h2> ...",
    "faq_schema": { "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [] },
    "hero_image": { "url": "https://seonis.ai/storage/images/5/918.jpg", "alt": "A pepper grinder" },
    "word_count": 1812,
    "published_url": null,
    "updated_at": "2026-09-06T06:31:12+00:00",
    "quality": { "seo_score": 88, "language_score": 96, "language_findings": [] },
    "exchange_links": []
  }
}
POST /api/v1/articles/{id}/published

U zet het artikel live; hier geeft u ons het adres door. Dit is het enige endpoint dat iets verandert.

Het doet precies wat een levering die wij zelf hebben gedaan ook doet: het artikel wordt als gepubliceerd gemarkeerd, het telt mee voor uw maandelijkse tegoed, het planitem wordt afgesloten, eventuele exchange-links erin krijgen het adres waarop de verifier heeft gewacht, en uw Facebook Page krijgt bericht als u er een hebt gekoppeld. Zonder deze aanroep blijft het artikel voor altijd klaarstaan en gebeurt niets daarvan.

Voorbeeld

curl -X POST https://seonis.ai/api/v1/articles/918/published \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://peppervale.co.uk/blog/how-to-choose-a-pepper-grinder"}'

Antwoorden

200 Vastgelegd. Het artikel komt terug met de nieuwe status, published_at en published_url.
422 De url ontbreekt of is geen volledig http://- of https://-adres.
409 Het artikel is niet klaar om te worden gepubliceerd, of staat al als gepubliceerd geregistreerd. Het artikel komt met de weigering terug, zodat u kunt zien welke van de twee het is.

Verbind "REST API" als uw publicatie-engine.

Onder Settings, dan Publishing, staat een engine met de naam "REST API: you fetch and publish". Die vraagt om niets, omdat er niets is dat wij moeten versturen. Wat het verandert, is wat er elke ochtend gebeurt: een voltooid artikel blijft klaarstaan zonder adres, en het publicatiescherm zegt dat het wacht tot u het ophaalt in plaats van een mislukte aflevering te tonen.

U kunt de API gebruiken zonder die te koppelen: de endpoints werken voor elk account met een sleutel. Door die te koppelen weet de rest van het product dat het niet langer een eigen adres moet verwachten, en zo voorkomt u dat een artikel dat u zelf publiceert als mislukking wordt geteld.

Elke fout is JSON met een bericht.

Overal dezelfde vorm, of de weigering nu uit de sleutelcontrole komt of van de validator, zodat niets er twee hoeft te parseren.

{ "message": "That API key is not valid, or it has been revoked." }
Status Wat het betekent
401 Geen sleutel, een sleutel die niet van ons is, of een sleutel die is ingetrokken.
404 Geen dergelijk artikel of dergelijke site in dit account. Een artikel van een ander account geeft 404 in plaats van 403: een API die zegt "dat is niet van u" heeft bevestigd dat het bestaat.
409 De aanvraag was in orde, maar het artikel is daar niet in de juiste status voor.
422 Een parameter ontbreekt of is onjuist. Het antwoord bevat een errors-object met de veldnaam en het bericht.
429 Boven de rate limit. Retry-After geeft aan hoe lang u moet wachten.

Wat een buildstap daadwerkelijk doet.

#!/usr/bin/env bash
set -euo pipefail

# 1. What is finished and not yet on the site?
ready=$(curl -sG https://seonis.ai/api/v1/articles \
  -H "Authorization: Bearer $SEONIS_API_KEY" \
  -d site_id=5 -d status=ready -d per_page=100)

for id in $(echo "$ready" | jq -r '.articles[].id'); do
  # 2. Take the article, body and all.
  curl -s https://seonis.ai/api/v1/articles/$id \
    -H "Authorization: Bearer $SEONIS_API_KEY" \
    | jq -r '.article.content_markdown' > "content/posts/$id.md"

  # 3. Your build puts it live, and you know where it landed.
  slug=$(echo "$ready" | jq -r ".articles[] | select(.id==$id) | .slug")

  curl -s -X POST https://seonis.ai/api/v1/articles/$id/published \
    -H "Authorization: Bearer $SEONIS_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"url\": \"https://peppervale.co.uk/blog/$slug\"}"
done

Maak een sleutel en probeer het.

De proefperiode is voldoende om de API te lezen: de artikelen die daarin worden geschreven zijn echte artikelen, en ze komen via deze endpoints terug zoals alle andere.

Start gratis proefperiode