REST API'et er til pipelines, scripts og alt, der ikke er en agent. Hvis du i stedet kobler en model til, skal du bruge MCP-serveren — den eksponerer de samme operationer som værktøjer over den samme tilladelsesmodel.

Basis-URL

fastsite er selv-hostet, så basis-URL'en er din egen engine-host. Alt bor under ét origin: dashboardet, API'et, MCP-endpointet og indgående webhooks.

https://your-host/api/v1

Autentificering

Hver anmodning medbringer en API-nøgle i et header. Der er ingen bearer-token og ingen session på denne overflade — bearer-auth tilhører MCP.

X-API-Key: fs_<key_id>_<secret>

En nøgle er en streng på 44 tegn: det bogstavelige præfiks fs_, et offentligt id på 8 tegn, en underscore og en hemmelighed på 32 tegn. Hemmeligheden er hashet med argon2id i hvile og vises præcis én gang, når nøglen oprettes.

php bin/fastsite key:create you@example.com \
  --name="Deploy pipeline" \
  --scopes=content:write,media:write,publish \
  --sites=blog

Brug --sites=* for at tillade alle sites. Nøgler administreres også fra dashboardet og kan roteres eller tilbagekaldes til enhver tid — en tilbagekaldt nøgle holder op med at virke øjeblikkeligt frem for ved slutningen af et cache-vindue.

Alle fejl ser ens ud

Et manglende header, en misdannet nøgle, en ukendt nøgle, en forkert hemmelighed, en tilbagekaldt nøgle og en deaktiveret bruger returnerer alle den samme 401 med den samme besked. Det er bevidst — det betyder, at en nøgle ikke kan sondes for eksistens.

Svar-envelopen

Hvert JSON-svar har den samme form, så en klient kan forgrene sig på ét felt.

{ "success": true, "data": { … } }

{ "success": false, "error": { "message": "…" } }

Liste-endpoints tilføjer en pagination-blok ved siden af data, og data er et almindeligt array frem for et objekt:

{
  "success": true,
  "data": [ … ],
  "pagination": { "total": 42, "page": 1, "per_page": 20, "total_pages": 3 }
}

To endpoints bryder bevidst envelopen, fordi det ville være meningsløst at indpakke dem: læsning af en shell-fil returnerer de rå bytes som text/plain, og sletning af en returnerer 204 uden krop.

Opret et indlæg, og publicér det derefter

curl -X POST https://your-host/api/v1/sites/blog/content \
  -H "X-API-Key: $FASTSITE_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 2f1c9a7e-…" \
  -d '{
    "type": "post",
    "title": "Hello, world",
    "body_html": "<p>Shipped in a single call.</p>",
    "status": "published"
  }'

At skrive indhold publicerer det ikke. De to er separate operationer med vilje — en pipeline kan oprette, revidere og rette så meget som nødvendigt uden at noget af det når besøgende. Når indholdet er klar, publiceres sitet:

curl -X POST https://your-host/api/v1/sites/blog/publish \
  -H "X-API-Key: $FASTSITE_KEY"
# → { "success": true, "data": { "job": "0f3c…" } }

Det returnerer 202 med et job-id; bygningen kører i køen. Forespørg GET /api/v1/jobs/0f3c… for resultatet.

title er det eneste påkrævede felt ved oprettelse. type er som standard post, status er som standard draft, og slugget afleses fra titlen, når du ikke sender et. Hvis det slug er taget, tilføjer enginen en tæller og returnerer det slug, den faktisk brugte — læs det altid tilbage frem for at antage.

Endpoints

Indhold

MetodeStiScope
GET/sites/{site}/contentcontent:read
POST/sites/{site}/contentcontent:write
GET/sites/{site}/content/{id}content:read
PATCH/sites/{site}/content/{id}content:write
DELETE/sites/{site}/content/{id}content:write
GET/sites/{site}/content/trashcontent:read
POST/sites/{site}/content/{id}/restorecontent:write
DELETE/sites/{site}/content/{id}/purgecontent:write
POST/sites/{site}/content/{id}/fact-checkcontent:read

Sletning er en blød sletning — elementet flyttes til papirkurven og kan gendannes. purge er den uigenkaldelige.

Medier

MetodeStiScope
GET/sites/{site}/mediamedia:read
POST/sites/{site}/mediamedia:write
DELETE/sites/{site}/media/{id}media:write
POST/sites/{site}/media/{id}/restoremedia:write
DELETE/sites/{site}/media/{id}/purgemedia:write

Upload accepterer enten en multipart-formular med et felt ved navn file eller JSON med en url der hentes. Ikke begge — hvis en fil er til stede, ignoreres URL'en.

curl -X POST https://your-host/api/v1/sites/blog/media \
  -H "X-API-Key: $FASTSITE_KEY" \
  -F file=@hero.jpg \
  -F alt="Sunrise over the harbour"

Alt-tekst er påkrævet for billeder, medmindre du eksplicit sender decorative=true. Det er ikke en stilpræference — en manglende alt-tekst fejler byggerevisionen, så API'et afviser det ved døren frem for at lade det ødelægge en publicering senere. URL-imports er SSRF-beskyttet: private adresseintervaller afvises, omdirigeringer genvalideres og downloaden er byte-begrænset.

Filtrer biblioteket med ?kind=image,video,file. Billeder og video køres gennem variant-pipelinen; alt andet gemmes som en fil til download.

Shell

MetodeStiScope
GET/sites/{site}/shell/filesshell:read
GET/sites/{site}/shell/file/{path}shell:read
PUT/sites/{site}/shell/file/{path}shell:write
DELETE/sites/{site}/shell/file/{path}shell:write
POST/sites/{site}/shell/snapshotshell:write
POST/sites/{site}/shell/restore/{rev}shell:write

Kroppen er filen, ikke JSON. Der er intet wrapper-objekt og intet feltnavn — du sender bytes og får bytes tilbage.

curl -X PUT https://your-host/api/v1/sites/blog/shell/file/templates/base.html.twig \
  -H "X-API-Key: $FASTSITE_KEY" \
  --data-binary @base.html.twig

Stien må indeholde skråstreger. Skrivninger er begrænset til shell-mappen, begrænset til 5 MB og begrænset til en tilladt liste over filendelser (twig, css, js, json, woff2, svg og de sædvanlige billedtyper). I modsætning til indhold sætter en shell-skrivning en genopbygning i gang — designet ændrede sig, så outputtet skal følge med. En strøm af redigeringer sammenflettes til én bygning frem for én per fil.

Tag et snapshot inden en risikabel ændring. Gendannelse tager et snapshot først, så en gendannelse i sig selv kan fortrydes.

Komponenter, omdirigeringer, scripts

MetodeStiScope
PUT/sites/{site}/components/{handle}components:write
GET · POST/sites/{site}/redirectssites:read · sites:write
DELETE/sites/{site}/redirects/{id}sites:write
GET · POST/sites/{site}/scriptssites:read · sites:write
DELETE/sites/{site}/scripts/{id}sites:write

En komponent er {type: "html"|"react", source_code, css?, variables_schema?}. React kompileres ved upload, så en ødelagt komponent giver en 422 på din anmodning frem for en ødelagt side senere.

Sprog, publicering, sites

MetodeStiScope
POST/sites/{site}/languagestranslations:manage
DELETE/sites/{site}/languages/{locale}translations:manage
POST/sites/{site}/publishpublish
GET/jobs/{uuid}jobs:read
GET/sitessites:read
POST/sitesadmin
PATCH/sites/{site}sites:write
GET · POST/sites/{site}/webhookssites:read · sites:write
GET/sites/{site}/webhooks/{id}/deliveriessites:read
DELETE/sites/{site}/webhooks/{id}sites:write
GET/authoring-guidesites:read
GET/sites/{site}/authoring-guidesites:read

Hent forfattervejledningen først

GET /api/v1/authoring-guide returnerer de maskinlæsbare regler for brødtekst-HTML, billedindlejring og shell-kontrakten. Send et site for at få dets lokaliteter og indlejringssyntaks foldet ind. Det er forskellen på indhold der bygger, og indhold som revisionen afviser.

Scopes

Nøgler og OAuth-tilladelser deler ét scope-ordforråd, så et endpoint og et værktøj håndhæver adgang identisk.

ScopeGiver adgang til
sites:readSe sites og deres indstillinger
sites:writeÆndre site-indstillinger, omdirigeringer, scripts, webhooks
content:readLæse indlæg og sider
content:writeOprette og redigere indlæg og sider
media:readSe mediebiblioteket
media:writeUploade billeder, video og filer
components:writeOprette og opdatere komponenter
shell:readLæse skabeloner og tema
shell:writeRedigere skabeloner og tema
translations:manageAdministrere lokaliteter og oversættelser
publishBygge og publicere
jobs:readLæse bygge- og jobstatus
backup:read · backup:run · backup:restoreSikkerhedskopieringsoperationer
adminAlt

Kun admin indebærer noget andet. Der er ingen læse/skrive-hierarki — content:write giver ikke content:read, så bed om begge hvis du har brug for begge. Nøgler er også fastgjort til en site-liste, og en anmodning for et site uden for den afvises, inden den når en handler.

Idempotens

Send et Idempotency-Key-header på enhver POST, og enginen registrerer resultatet mod det.

  • Den samme nøgle med samme metode, sti og krop afspiller det gemte svar med Idempotency-Replayed: true på det.
  • Den samme nøgle med en anden krop er en 422 — det er sådan du finder ud af, at din genprøvningslogik ændrede indholdet.
  • En genprøvning der ankommer, mens den første stadig kører, får 409 og en Retry-After.
  • Hvis handleren kaster, eller svaret er en 5xx eller en 429, frigives nøglen, så en ægte genprøvning kan lykkes.

Andre metoder ignorerer headeren fuldstændigt.

Hastighedsbegrænsninger

To faste vindueslimitter, begge per minut: 60 anmodninger per IP og 120 per API-nøgle. Overskridelse af en af dem returnerer 429 med en Retry-After. Per-IP-spanden er den du oftest vil møde, da en enkelt klient er én adresse.

JSON-anmodningskroppe er begrænset til 4 MiB. Uploads er undtaget fra denne kontrol og begrænset af de per-type mediegrænser i stedet.

Statuskoder

KodeBetydning
200 · 201 · 202 · 204Succes. 202 betyder sat i kø — forespørg jobbet.
401Manglende, misdannet, ukendt eller tilbagekaldt nøgle.
403Gyldig nøgle, men scope eller site er ikke tilladt.
404Ingen sådan rute, site eller post.
409Duplikat, eller en idempotent anmodning stadig i gang.
413Krop over grænsen.
422Validering mislykkedes — læs error.message.
429Hastighedsbegrænset.

Detaljer der er værd at kende, inden du bygger mod det

  • Tidsstempler er strenge. scheduled_at og published_at skal være YYYY-MM-DDTHH:MM:SSZ — UTC, stort T, afsluttende Z. Forskydninger som +02:00 afvises frem for at blive konverteret.
  • Statusværdier er draft, scheduled, published og archived. Planlægning kræver scheduled_at, og planlæggeren publicerer det for dig, når tiden kommer.
  • Sideinddeling sker med ?page= og ?per_page=, standard er 20 og max er 100.
  • Brødtekst-HTML saneres på alle veje. Inline-styles fjernes, scripts og iframes fjernes, og resultatet returneres med et warnings-array. Indholdsproblemer fejler aldrig din anmodning — de rapporteres, normaliseres og publiceres.
  • Nogle ting er ikke på REST. Sikkerhedskopier, teams og API-nøgleadministration er CLI- og dashboardoperationer; sikkerhedskopier og gendannelser er også tilgængelige via MCP.

Næste: MCP-serveren til agent-drevet publicering, eller webhooks til at skubbe indhold ind fra et upstream-system.