Ga naar hoofdinhoud

REST API v1

Integreer het Korporaal Media Platform in uw eigen applicatie. Toegang tot tickets, bestellingen, hosting, domeinen en meer.

Base URL: https://korporaalmedia.nl/api/v1

Aan de slag

1

Token aanvragen

Login via /auth/token (wachtwoord) of /auth/sso-token (Authentik SSO).

2

Token meesturen

Voeg het token toe als Authorization: Bearer <token> header bij elke request.

3

API aanroepen

Alle responses zijn in JSON. Prijzen zijn altijd in centen (integers).

Token aanvragen POST
curl -X POST https://korporaalmedia.nl/api/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{
    "email": "uw@email.nl",
    "password": "uw_wachtwoord",
    "device_name": "Mijn App"
  }'
Response 201
{
  "token": "1|abc123def456...",
  "user": {
    "id": 1,
    "name": "Jan Jansen",
    "email": "jan@bedrijf.nl",
    "role": "customer",
    "customer_id": 5
  }
}

Endpoints

Alle endpoints starten met /api/v1. Endpoints met een slotje vereisen authenticatie.

Authenticatie

POST /auth/login

Inloggen (e-mail + wachtwoord)

Parameters

Naam Type Vereist Beschrijving
email string verplicht E-mailadres
password string verplicht Wachtwoord
device_name string verplicht Naam van het apparaat (bijv. "iPhone", "Mijn App")

Response

{ "token": "1|abc...", "user": { "id", "name", "email", "role", "customer_id" } }
POST /auth/token

Token aanmaken (alias voor /auth/login)

Parameters

Naam Type Vereist Beschrijving
email string verplicht E-mailadres
password string verplicht Wachtwoord
device_name string verplicht Naam van het apparaat

Response

{ "token": "1|abc...", "user": { "id", "name", "email", "role", "customer_id" } }
POST /auth/sso-token

Token aanmaken via Authentik SSO (OIDC code exchange)

Parameters

Naam Type Vereist Beschrijving
code string verplicht OIDC authorization code van Authentik
redirect_uri string verplicht Redirect URI die bij de authorization request is gebruikt
device_name string verplicht Naam van het apparaat (bijv. "iPhone 15")
code_verifier string optioneel PKCE code verifier (aanbevolen voor mobiele apps)

Response

{ "token": "1|abc...", "user": { "id", "name", "email", "role", "customer_id" }, "is_new_user": false, "needs_customer_profile": false }
GET /auth/sso-config

OIDC configuratie ophalen voor SSO login flow

Response

{ "authorization_endpoint", "token_endpoint", "userinfo_endpoint", "client_id", "scopes" }
GET /auth/user

Huidige gebruiker ophalen

Response

{ "id", "name", "email", "role", "customer_id", "customer": { "id", "name" } }
POST /auth/logout

Token verwijderen (uitloggen)

Response

{ "message": "Token verwijderd." }

Profiel & klantgegevens

GET /profile

Profiel met klantgegevens ophalen

Response

{ "data": { "id", "name", "email", "role", "customer": { "id", "name", "email", "phone", "address", "kvk_number", "vat_number" } } }
GET /profile/hosting-packages

Hosting pakketten van de klant

Parameters

Naam Type Vereist Beschrijving
per_page integer optioneel Resultaten per pagina (standaard 15)

Response

{ "data": [{ "id", "domain", "status", "product", "amount", "next_due_date", "auto_renew" }] }
GET /profile/domains

Domeinen van de klant

Parameters

Naam Type Vereist Beschrijving
per_page integer optioneel Resultaten per pagina (standaard 15)

Response

{ "data": [{ "id", "domain", "tld", "status", "expires_at", "days_until_expiry", "auto_renew" }] }
GET /profile/orders

Bestellingen van de klant

Parameters

Naam Type Vereist Beschrijving
per_page integer optioneel Resultaten per pagina (standaard 15)

Response

{ "data": [{ "id", "order_number", "status", "total", "items", "paid_at" }] }
GET /profile/invoices

Facturen ophalen via Moneybird

Response

{ "data": [{ "id", "invoice_number", "date", "total", "status", "pdf_url" }] }

Integraties & service tokens

Wat is een service token?

Een service token is een Sanctum personal access token dat hoort bij een applicatie (geen mens). Externe systemen zoals KM Desk gebruiken zo'n token om, namens bekende eindgebruikers, tickets aan te maken in het Korporaal Media platform, zonder dat die eindgebruikers handmatig hoeven in te loggen.

Tokens hebben abilities (scopes). Een KM Desk token heeft bijvoorbeeld tickets:create-on-behalf , daarmee mag het ticket-endpoint aangeroepen worden, maar bijvoorbeeld geen orders aanmaken of klanten verwijderen.

Tokens worden via een artisan command op de server aangemaakt en moeten direct na aanmaak bewaard worden, ze zijn daarna niet meer op te vragen. Wel kunnen ze worden ingetrokken.

KM Desk integratie, stap voor stap

  1. Token aanvragen. Vraag de beheerder om een token via:
    php artisan api:issue-token --name="KM Desk"
    Bewaar de output (formaat 1|abc...) als KM_PLATFORM_TOKEN in de KM Desk config.
  2. Ticket aanmaken namens een gebruiker. Roep POST /api/v1/tickets/on-behalf aan met het emailadres van de KM Desk gebruiker. Het platform zoekt die op in zijn eigen userlijst (matching op email).
  3. Foutafhandeling. Krijgt KM Desk een 404 user_not_found? Dan bestaat de gebruiker niet in het portaal (of heeft hij geen email). Toon dan in KM Desk de melding: "Vraag de hoofdgebruiker van uw organisatie om dit ticket aan te maken." Eindgebruikers zonder email kunnen geen tickets aanmaken, die loopt via hun primaire contactpersoon.
  4. Status terug naar KM Desk. Registreer een webhook (via POST /api/v1/webhooks) voor de events ticket.replied, ticket.status_changed, ticket.resolved en ticket.closed. KM Desk kan dan in real-time tonen wat de status van het ticket is.

Voorbeeld request

curl -X POST https://korporaalmedia.nl/api/v1/tickets/on-behalf \
  -H "Authorization: Bearer $KM_PLATFORM_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "subject": "Printer doet het niet",
    "description": "De HP LaserJet op de eerste verdieping start niet meer op.",
    "priority": "high",
    "user_email": "jan@bedrijf.nl",
    "user_name": "Jan Jansen",
    "external_reference": "kmdesk-ticket-4821"
  }'

Voorbeeld response (201)

{
  "data": {
    "id": 1234,
    "subject": "Printer doet het niet",
    "status": "open",
    "status_label": "Open",
    "priority": "high",
    "priority_label": "Hoog",
    "source": "kmdesk",
    "customer": { "id": 17, "name": "Bedrijf B.V." },
    "assignee": { "id": 1, "name": "Sanne Jansen" },
    "created_at": "2026-04-08T14:23:11+02:00"
  }
}

Foutscenario: gebruiker onbekend

HTTP/1.1 404 Not Found

{
  "message": "Gebruiker niet bekend in het Korporaal Media portaal. Vraag de hoofdgebruiker van uw organisatie om dit ticket aan te maken.",
  "code": "user_not_found"
}
POST /tickets/on-behalf

Ticket aanmaken namens een KM Platform gebruiker (service token vereist)

Parameters

Naam Type Vereist Beschrijving
subject string verplicht Onderwerp (max 255 tekens)
description string verplicht Beschrijving (max 10.000 tekens)
user_email string verplicht Email van de eindgebruiker, moet bestaan in KM Platform
user_name string optioneel Weergavenaam (voor audit/notifications)
priority string optioneel low, normal (standaard), high of urgent
category_id integer optioneel Ticket categorie ID
source string optioneel Bron tag (standaard: kmdesk)
external_reference string optioneel Eigen referentie van het externe systeem (audit only)

Response

{ "data": { "id", "subject", "status", "priority", "source", "customer", "assignee", "created_at" } }

Tickets

GET /tickets

Tickets ophalen

Parameters

Naam Type Vereist Beschrijving
status string optioneel Filter op status (open, pending, closed, etc.)
open boolean optioneel Alleen openstaande tickets tonen
per_page integer optioneel Resultaten per pagina (standaard 15)

Response

{ "data": [{ "id", "subject", "status", "priority", "category", "replies_count", "created_at" }] }
GET /tickets/{id}

Ticket details met reacties

Response

{ "id", "subject", "description", "status", "priority", "replies": [{ "id", "message", "is_from_customer", "sender_name", "attachments" }] }
POST /tickets

Nieuw ticket aanmaken

Parameters

Naam Type Vereist Beschrijving
subject string verplicht Onderwerp (max 255 tekens)
description string verplicht Beschrijving (max 10.000 tekens)
priority string optioneel low, normal (standaard), high of urgent
category_id integer optioneel Categorie ID

Response

Ticket object (zie GET /tickets/{id})
POST /tickets/{id}/replies

Reactie op ticket plaatsen

Parameters

Naam Type Vereist Beschrijving
message string verplicht Bericht (max 10.000 tekens)

Response

{ "id", "message", "is_from_customer", "sender_name", "attachments", "created_at" }

Notificaties

GET /notifications

Alle notificaties (gepagineerd)

Parameters

Naam Type Vereist Beschrijving
per_page integer optioneel Resultaten per pagina (standaard 20)

Response

{ "data": [{ "id", "type", "title", "body", "read_at", "created_at" }], "meta": { "unread_count" } }
GET /notifications/unread

Alleen ongelezen notificaties

Response

Zelfde als GET /notifications
POST /notifications/{id}/read

Notificatie als gelezen markeren

Response

{ "message": "Gelezen." }
POST /notifications/read-all

Alle notificaties als gelezen markeren

Response

{ "message": "Alle notificaties gelezen." }

Winkelwagen

GET /cart

Winkelwagen ophalen

Response

{ "data": { "items": [{ "id", "type", "name", "price", "quantity", "total" }], "subtotal", "tax", "total", "item_count" } }
POST /cart/items

Item toevoegen

Parameters

Naam Type Vereist Beschrijving
type string verplicht hosting, domain, product of print
product_id integer verplicht Product ID
name string verplicht Productnaam
price integer verplicht Prijs in centen
quantity integer optioneel Aantal (standaard 1, max 100)
options object optioneel Extra opties (bijv. billing cycle, domein)

Response

{ "message": "Item toegevoegd.", "cart_item_id": "...", "cart": { ... } }
PUT /cart/items/{id}

Aantal wijzigen

Parameters

Naam Type Vereist Beschrijving
quantity integer verplicht Nieuw aantal (0 = verwijderen, max 100)

Response

{ "message": "Winkelwagen bijgewerkt.", "cart": { ... } }
DELETE /cart/items/{id}

Item verwijderen

Response

{ "message": "Item verwijderd.", "cart": { ... } }
DELETE /cart

Winkelwagen legen

Response

{ "message": "Winkelwagen geleegd.", "cart": { ... } }

Bestellingen

GET /orders

Bestellingen ophalen

Parameters

Naam Type Vereist Beschrijving
per_page integer optioneel Resultaten per pagina (standaard 15)

Response

{ "data": [{ "id", "order_number", "status", "total", "items", "paid_at", "created_at" }] }
GET /orders/{id}

Bestelling details

Response

{ "data": { "id", "order_number", "status", "payment_status", "subtotal", "tax_amount", "total", "items": [{ "name", "type", "quantity", "price", "total" }] } }

Producten

Deze endpoints zijn openbaar en vereisen geen authenticatie.

GET /hosting-products

Hosting pakketten catalogus

Response

{ "data": [{ "id", "name", "slug", "price_monthly", "price_yearly", "disk_space_gb", "features", "is_featured" }] }
GET /hosting-products/{id}

Hosting pakket details

Response

{ "data": { "id", "name", "slug", "description", "price_monthly", "price_yearly", "disk_space_gb", "bandwidth_gb", "max_domains", "features" } }

Domeinen

Dit endpoint is openbaar en vereist geen authenticatie.

POST /domains/check

Domein beschikbaarheid controleren

Parameters

Naam Type Vereist Beschrijving
domain string verplicht Domeinnaam zonder extensie (2-63 tekens)
tlds array optioneel Extensies om te controleren (standaard: nl, com, eu, be, de, net)

Response

{ "data": [{ "domain": "voorbeeld.nl", "tld": "nl", "available": true, "price": 995 }] }

Push notificaties (apparaten)

POST /devices

Apparaat registreren voor push notificaties

Parameters

Naam Type Vereist Beschrijving
player_id string verplicht OneSignal player/subscription ID
platform string verplicht ios, android of web
device_model string optioneel Apparaat model (bijv. "iPhone 15")

Response

{ "message": "Apparaat geregistreerd.", "user_id": 1, "external_id": "1" }

Webhooks

Beschikbare events

order.created Bestelling aangemaakt
order.paid Bestelling betaald
order.completed Bestelling afgerond
order.cancelled Bestelling geannuleerd
hosting.provisioned Hosting actief
hosting.suspended Hosting opgeschort
domain.registered Domein geregistreerd
ticket.created Ticket aangemaakt
ticket.replied Reactie op ticket
ticket.status_changed Status gewijzigd
ticket.resolved Ticket opgelost
ticket.closed Ticket gesloten

Payload-formaat

Elke webhook is een POST naar de geregistreerde URL met JSON body en de headers X-Webhook-Event en X-Webhook-Signature (HMAC-SHA256 van de body met het webhook-secret).

{
  "event": "ticket.replied",
  "timestamp": "2026-04-08T14:23:11+02:00",
  "data": {
    "ticket": {
      "id": 1234,
      "subject": "Printer doet het niet",
      "status": "in_progress",
      "priority": "high",
      "source": "kmdesk",
      "requester_email": "jan@bedrijf.nl",
      "requester_name": "Jan Jansen",
      "customer_id": 17,
      "customer_name": "Bedrijf B.V.",
      "assignee_name": "Sanne Jansen",
      "url": "https://korporaalmedia.nl/admin/tickets/1234"
    },
    "reply": {
      "id": 9876,
      "message": "Ik heb het ticket opgepakt en ga ermee aan de slag.",
      "is_from_customer": false,
      "is_internal": false,
      "sender_name": "Sanne Jansen",
      "created_at": "2026-04-08T14:23:11+02:00"
    }
  }
}

Signature verifiëren

Bereken aan de ontvangerskant hash_hmac('sha256', $rawBody, $webhookSecret) en vergelijk met de header X-Webhook-Signature. Verwerp het verzoek bij mismatch. Failed deliveries worden tot 10 keer geprobeerd, daarna wordt de webhook automatisch gedeactiveerd.

GET /webhooks

Webhooks ophalen

Response

{ "data": [{ "id", "url", "events", "is_active", "last_triggered_at", "failure_count" }], "available_events": [...] }
POST /webhooks

Webhook aanmaken

Parameters

Naam Type Vereist Beschrijving
url string verplicht URL om events naartoe te sturen (HTTPS aanbevolen)
events array verplicht Lijst van events (zie hierboven)

Response

{ "message": "Webhook aangemaakt.", "data": { "id", "url", "events", "secret" } }
DELETE /webhooks/{id}

Webhook verwijderen

Response

{ "message": "Webhook verwijderd." }

HTTP statuscodes

200 OK, Request succesvol verwerkt
201 Created, Resource succesvol aangemaakt
401 Unauthorized, Geen of ongeldig token
403 Forbidden, Geen toegang tot deze resource
404 Not Found, Resource niet gevonden
422 Validation Error, Ongeldige parameters
429 Too Many Requests, Rate limit bereikt
500 Server Error, Interne fout

Belangrijke informatie

Prijzen in centen

Alle bedragen worden geretourneerd als integers in centen. Deel door 100 voor euros. Voorbeeld: 1995 = €19,95.

Paginering

Gepagineerde responses bevatten meta en links objecten met paginatie-informatie.

Multi-tenancy

Klanten zien alleen hun eigen data. Tickets, bestellingen, domeinen en hosting worden automatisch gefilterd op basis van uw account.

Admin endpoints

Endpoints onder /admin vereisen een account met role: admin. Niet-admins ontvangen een 403.

Machine-leesbare docs

Een automatisch gegenereerd overzicht van alle endpoints is beschikbaar op GET /api.

Rate limiting

De API is gelimiteerd tot 60 requests per minuut per token. Bij overschrijding ontvangt u een 429 status.

Hulp nodig bij de integratie?

Neem contact op voor ondersteuning bij het koppelen van uw applicatie aan onze API.

Cookies

Wij gebruiken cookies om de website te verbeteren. Noodzakelijke cookies zijn altijd actief. Privacybeleid

Cookie-voorkeuren