Ga naar inhoud

API-overzicht

Authenticatie

Alle /api/*-verzoeken authenticeren met een HTTP-token in de Authorization- header. Zowel het Token- als het Bearer-schema wordt geaccepteerd:

Authorization: Token {{ CloudPress API Token }}
Authorization: Bearer {{ CloudPress API Token }}

Er zijn drie soorten credentials, die allemaal op dezelfde manier worden aangeboden. De server bepaalt om welk type het gaat (eerst sessie / API-sleutel, daarna OAuth):

Credential Identiteit Admin‑rechten? Gelden OAuth-scopes? Opmerkingen
User API key Een gebruiker (heeft toegang tot de accounts waartoe die gebruiker behoort) Als de sleutel als admin is gemarkeerd Nee (omzeilt scopecontroles) Optionele IP-toegangslijst.
System API key Een account (alleen systeembeheerd) Als als admin gemarkeerd Nee Het account komt van de drager van de sleutel — vereist geen X-Auth-Account; het IP moet op de systeemtoegangslijst staan.
OAuth 2.1 access token Een gebruiker, gebonden aan één (account, brand) Nooit Ja — fail-closed Uitgegeven via de OAuth 2.1 autorisatieserver.

Trial-accounts kunnen de API niet gebruiken

Een OAuth-token wordt altijd geweigerd wanneer het gekoppelde account een trial-account is. Een user API key wordt alleen geweigerd wanneer X-Auth-Account naar een trial-account verwijst — zonder die header is er geen account om te controleren en gaat het verzoek door. Een system API key wordt afgehandeld vóórdat de trial-controle plaatsvindt en wordt op deze grond nooit geweigerd.


IP-beperking

Je kunt de toegang per IP beperken tot een specifieke API-sleutel in de CloudPress API Key Manager. Let op: wanneer je probeert verbinding te maken vanaf een niet-geautoriseerd IP, krijg je dezelfde reactie als wanneer je een ongeldige API-sleutel had opgegeven.

Standaard is er geen IP-beperking ingesteld.


Accountscope instellen

Sommige API-endpoints vereisen een accountscope. Om aan te geven onder welk account je wilt werken, voeg je de header X-Auth-Account toe met je Account-ID:

X-Auth-Account: {{ CloudPress Account ID }}

Gedrag:

  • Voor een user API key scope't X-Auth-Account het verzoek naar één account en stelt het de accountcontext in. Zonder deze header geven list-endpoints resources terug over alle accounts waartoe de gebruiker van de sleutel toegang heeft.
  • Twee lijsten negeren de header volledig. GET /api/domains en GET /api/dns_zones geven altijd elk domein / elke zone terug waar de gebruiker van de sleutel bij kan, of je X-Auth-Account nu meestuurt of niet. Filter aan de clientzijde als je de subset van één account nodig hebt.
  • Sommige endpoints vereisen de header en geven 400 {"errors":["Missing X-Auth-Account"],"code":"missing_account"} terug wanneer hij ontbreekt — Orders, Carts, Subscriptions, Users, SSO, cPanel-accounts, en alle endpoints voor domeinregistratie. Het aanmaken van een DNS-zone hanteert dezelfde regel, maar rendert een eigen body zonder code-sleutel400 {"errors":["Missing X-Auth-Account"]} — vertrouw daar dus niet op missing_account. Mailspace create heeft ook een accountcontext nodig en antwoordt met 400 account_required.
  • OAuth-tokens dragen altijd een account, dus voor die tokens wordt de header genegeerd.

Authenticatiefouten

Een mislukte authenticatie geeft 401 terug met de header WWW-Authenticate: Token realm="Application" en een lege body. Mogelijke oorzaken zijn: geen/ongeldig token, een IP dat niet op de toegangslijst van de sleutel staat, een trial-account, of een X-Auth-Account-waarde die niet overeenkomt met een account waartoe het token toegang heeft.

OAuth audience binding (RFC 8707)

Een OAuth-token dat is aangemaakt met een resource-indicator (bijvoorbeeld een token uitgegeven voor de MCP-server op /mcp) wordt op /api/* geweigerd met HTTP 401 en een JSON-body — niet de bovenstaande vorm met lege body en WWW-Authenticate:

{ "error": "invalid_token", "error_description": "token audience is not valid for /api" }

/api geeft nooit resource-gebonden tokens uit, dus elk token dat een resource draagt is aangemaakt voor een andere audience en kan /api niet bereiken.


Conventies

  • Alle API-routes vallen onder /api/. Alle reacties zijn JSON.
  • Resource-ID's zijn GUID's, behalve numerieke task-ID's, integer volume-ID's, integer DNS-recordtype-codes, en numerieke domain_contact-ID's.
  • Tijdstempels zijn ISO 8601, UTC.
  • Asynchrone bewerkingen geven 202 Accepted terug — poll een task, registrar-proces of cart om de voltooiing te controleren (zie Asynchrone bewerkingen).

Paginering

Paginering is geen conventie die overal geldt. Precies vijf index-endpoints accepteren page en per_page:

  • GET /api/orders
  • GET /api/subscriptions
  • GET /api/domains
  • GET /api/dns_zones
  • GET /api/cpanel_accounts
Param Type Standaard Opmerkingen
page Integer 1 Paginanummer
per_page Integer 50 Records per pagina, begrensd tot een maximum van 100

Elke andere index-actie — sites, tasks, users, accounts, API-sleutels, DNS-records, domeinregistraties, domeincontacten, Mailspace, de domeinen van een cPanel account, en alle sub-resources van een site — negeert beide parameters en geeft de volledige set in één reactie terug.

Rate limiting

Verzoeken zijn beperkt tot 600 per 10 minuten, geteld per client-IP-adres en per controller — niet per credential. Daaruit volgen twee dingen:

  • Eén credential krijgt een apart budget van 600 verzoeken tegen elke groep endpoints (sites, domeinen, DNS-zones, orders, …), dus werk dat over meerdere resources verdeeld is, valt niet onder één gedeeld maximum van 600.
  • Twee credentials die vanaf hetzelfde bron-IP verzoeken sturen — achter één NAT of egress-gateway — delen één bucket en kunnen elkaars budget opmaken.

Bij overschrijding van de limiet wordt 429 met een lege body teruggegeven.


Foutreacties

Status Wanneer dit optreedt
400 Ontbrekende verplichte header (missing_account, of account_required bij Mailspace create); ongeldige/no-op-params; validatiefouten bij order- en site-resize (onbekende variant/locatie/term/product); no_default_payment_method; een app-wachtwoord-update zonder de verplichte allowed_ips-sleutel (allowed_ips_missing); een days-waarde die wel is meegestuurd maar geen heel getal is bij de metrics van transactionele e-mail van een site (invalid_days); OAuth picker-/DCR-fouten
401 Authenticatie mislukt (geen/ongeldig token, IP geblokkeerd, trial-account, accountmismatch); admin-only endpoint met een niet-admin-credential
402 Dienst opgeschort vanwege een onbetaalde factuur (service_suspended); registrar fee-gate (payment_required)
403 Onvoldoende rol ({"errors":["Not Authorized"]}, of forbidden bij writes op DNS-zones / DNS-records); OAuth-scopefout (insufficient_scope); Shield niet in abonnement / premium vereist; site wacht op verwijdering (pending_delete); cPanel niet ingeschakeld voor de workspace (cpanel_not_enabled)
404 Resource niet gevonden of niet toegankelijk voor dit token (bijv. unknown_task voor een task-id dat niet bij de site hoort)
409 Conflict — Bunny-resource niet actief (cdn_not_active, shield_not_active); registrar-proces al onderweg (registration_busy); een pakketwijziging die al wordt doorgevoerd (resize_in_flight)
422 Validatiefout of rechtenbeperking (bijv. overgeërfde rol, alleen voor resellers, resize-beperkingen); billing-settle-bewaking op een net aangemaakte site (billing_settling); cart-betaling kon niet worden gestart (cart_pay_failed)
429 Rate limit overschreden (600 / 10 min)
502 Upstream-fout (Bunny CDN/Shield, of domeinregistrar)
503 Functie uitgeschakeld (feature_disabled, de domain-registration-flag); geen registrar geconfigureerd voor een TLD (registrar_unavailable); mailhosting niet geconfigureerd (stalwart_unavailable); cPanel tijdelijk onbereikbaar (cpanel_unavailable); een Mailspace-read die de mailserver niet kon uitvoeren (archived_items_unavailable, purged_mailboxes_unavailable, group_members_unavailable — zie Mailspace)

Sites die op verwijdering wachten, zijn vergrendeld (403 pending_delete)

Een soft-deleted site is niet weg — hij blijft gedurende zijn bewaartermijn adresseerbaar, maar is vergrendeld. GET /api/sites toont hem nog steeds (met pending_delete: true en delete_scheduled_at), en GET /api/sites/{id} geeft een beperkte payload terug met status "pending_delete" in plaats van de details van een actieve site. Alles wat hem zou wijzigen, wordt geweigerd met 403:

{
  "errors": ["This site is pending deletion and is locked. Restore it to make changes."],
  "code": "pending_delete",
  "delete_scheduled_at": "2026-09-01T14:22:05Z"
}

Dit geldt voor PATCH en DELETE /api/sites/{id} en voor elke geneste sub-resource van de site — domeinen en certificaten, back-ups en exports, restores, cache, CDN, edge rules, Shield, varianten, tasks, metrics, logs en SSO. De geneste endpoints zijn afgeschermd voor zowel reads als writes, dus de sub-resources van een vergrendelde site antwoorden ook op een GET met 403. Herstel de site om de vergrendeling op te heffen.

Functie- en plan-gating

De enige feature flag die API-endpoints gate't is domain-registration (geeft 503 feature_disabled terug wanneer uit). Shield is plan-gated (403 shield_not_in_plan, of shield_premium_required voor premium-only writes). CDN/Shield nog niet voorzien op Bunny geeft 409 terug (cdn_not_active / shield_not_active).


Asynchrone bewerkingen

De meeste provisioning-bewerkingen zijn asynchroon en geven 202 Accepted terug met een referentie om te pollen.

  • Tasks — verschillende bewerkingen openen een Task, maar niet alle geven het id terug. Drie gevallen, en het verschil telt zodra je je polling inricht:

    • 202 met een task_id — PHP-versiewijziging (PATCH /api/sites/{site-id}/variants/php) en cache inschakelen / uitschakelen / legen. Poll het teruggegeven id direct.
    • 202 zonder task-id — herstarten, een back-up maken en verwijderen, een restore, en een site-domein promoveren / verwijderen. Er wordt een Task aangemaakt, maar de responsbody is leeg; zoek hem dus op via GET /api/sites/{site-id}/tasks. Een site-domein toevoegen geeft wel een id terug, maar dat is de guid van het nieuwe domein, geen task-id.
    • Helemaal geen Task — het verwijderen van een accountrol (DELETE /api/accounts/{account-id}/roles/{id}) en accountverwijdering (DELETE /api/accounts/{account-id}) antwoorden met een kale 202. Er wordt niets aangemaakt om te pollen; lees het account of zijn rollen opnieuw uit om het resultaat te bevestigen.

    Poll een task met GET /api/tasks/:id of GET /api/sites/:site_id/tasks/:id. Taskstatussen: PENDING, RUNNING, OK, FAILED, CANCELLED, PAUSED. - Cartssite-aanmaak (POST /api/orders), site-resize / planwijziging (PATCH /api/sites/:id met plan), en domeinorders (POST /api/orders/domain) worden gepolld via de cart, niet via een task: ze geven een cart-envelop terug; poll de cart op gematerialiseerde orders. - Registrar-processen — mutaties voor domeinregistratie kunnen een proces openen; poll het op voltooiing.

Afrondingscallback

Bij het aanmaken van een order kun je optioneel een callback meegeven, zodat je een webhook ontvangt wanneer het asynchrone werk klaar is in plaats van te pollen:

{ "callback": { "url": "https://your-app.com/webhook", "authorization": "Bearer your-secret" } }

Zie Callbacks voor het volledige contract.


About-endpoint

CloudPress biedt een 'about'-endpoint dat informatie geeft over wie je bent ingelogd als, evenals informatie over beschikbare resources. Het accepteert elk geldig token, ongeacht de OAuth-scope.

GET /api/about

Teruggegeven params
  • version: String | Informatie over de API-versie
  • logged_in_as: String | Jouw gebruikers-ID
  • account_scoped: String | Als je met een account hebt geauthenticeerd, is dit jouw ID.
  • locations: Array
    • id: String
    • name: String
  • products: Array
    • id: String
    • name: String
    • description: String
  • php: Array | [] wanneer er geen versies beschikbaar zijn
    • id: Integer
    • label: String
    • is_default: Boolean
Voorbeeld
curl -H "Authorization: Bearer $CLOUDPRESS_TOKEN" \
  https://your-instance/api/about