Contacten
Contactaccounts
Hoe storefront-contactaccounts, sessietokens en de gastlevenscyclus werken.
Bekijk als MarkdownContacts geven je storefront contactaccounts: registratie, inloggen, wachtwoordherstel, een profiel en opgeslagen adressen. Alle routes leven onder /v1/api/contacts, met een identieke alias op /v1/api/customers voor integraties die vóór de hernoeming zijn gebouwd. Contacts horen bij elke winkel, dus je hoeft vooraf geen module in te schakelen.
Alias: /v1/api/customers
Elke route hieronder wordt ook, ongewijzigd, aangeboden op het equivalente /v1/api/customers/... pad (bijvoorbeeld POST /v1/api/customers/register naast POST /v1/api/contacts/register). Request- en response-vorm zijn op beide identiek. Deze alias is permanent, geen deprecatievenster: bestaande integraties hoeven nooit te migreren, al zouden nieuwe integraties /v1/api/contacts moeten gebruiken.
Twee tokens, twee headers
Contact-endpoints gebruiken een gelaagd authenticatiemodel:
- Tenant-API-key (altijd verplicht). Elk request draagt de API-key van je winkel als
Authorization: Bearer {api_key}, precies zoals de rest van de storefront API. De key heeft decontacts:writescope nodig voor alle POST-, PATCH- en DELETE-endpoints en decontacts:readscope voor de GET-endpoints. Een key die vóór de hernoeming is aangemaakt draagt in plaats daarvancustomers:write/customers:read, en wordt nog steeds geaccepteerd. Een ontbrekende scope retourneert403 {"message":"Invalid ability provided."}. - Contactsessietoken (verplicht op contact-geauthenticeerde endpoints).
POST /v1/api/contacts/registerenPOST /v1/api/contacts/loginretourneren eentoken-string. Stuur deze op volgende requests mee in deX-Customer-Tokenheader. Een ontbrekend of ongeldig contacttoken retourneert401 {"message":"Invalid customer token."}.
De twee headers zijn onafhankelijk en beide verplicht op contact-geauthenticeerde routes:
Authorization: Bearer {api_key}
X-Customer-Token: {token}Welke endpoints wat nodig hebben:
| Endpoint | API-key scope | X-Customer-Token |
|---|---|---|
POST /register | contacts:write (customers:write geaccepteerd) | Nee |
POST /login | contacts:write (customers:write geaccepteerd) | Nee |
POST /forgot-password | contacts:write (customers:write geaccepteerd) | Nee |
POST /reset-password | contacts:write (customers:write geaccepteerd) | Nee |
POST /logout | contacts:write (customers:write geaccepteerd) | Ja |
GET /me | contacts:read (customers:read geaccepteerd) | Ja |
PATCH /me | contacts:write (customers:write geaccepteerd) | Ja |
GET /me/addresses | contacts:read (customers:read geaccepteerd) | Ja |
POST /me/addresses | contacts:write (customers:write geaccepteerd) | Ja |
PATCH /me/addresses/{id} | contacts:write (customers:write geaccepteerd) | Ja |
DELETE /me/addresses/{id} | contacts:write (customers:write geaccepteerd) | Ja |
Contactsessietokens verlopen niet op een timer. Ze worden ingetrokken door POST /logout (één token) en door een succesvol wachtwoordherstel (alle tokens van het contact).
Het publieke contactobject
Contactgerichte endpoints retourneren deze vorm (interne velden zoals is_guest, type en customer_group_id worden nooit blootgesteld op de storefront API):
| Veld | Type | Beschrijving |
|---|---|---|
id | string (uuid) | Contact-id. Stabiel over de gast-naar-account-upgrade heen. |
name | string | Volledige naam. |
email | string of null | E-mailadres, altijd lowercase indien aanwezig. Uniek per winkel. Registreren via de storefront vereist altijd een e-mailadres; een contact kan alleen een null e-mailadres hebben wanneer het door de handelaar is aangemaakt (bijvoorbeeld een zakelijk contact toegevoegd via het klantdashboard of CSV-import) zonder e-mailadres. |
phone | string of null | Telefoonnummer. |
kind | string | person of company. Alleen-lezen via deze API: wordt door de handelaar ingesteld, niet door de storefront. |
company_name | string of null | Bedrijfsnaam. Alleen ingesteld wanneer kind company is. Alleen-lezen via deze API. |
registration_number | string of null | KvK-nummer of vergelijkbaar registratienummer. Alleen-lezen via deze API. |
vat_id | string of null | Btw-nummer. Alleen-lezen via deze API. |
external_id | string of null | Door de handelaar toegekende identifier, bijvoorbeeld een ERP- of boekhoud-id. Alleen-lezen via deze API. |
display_name | string | De bedrijfsnaam wanneer die er is, anders de naam van het contact. Afgeleid, niet opgeslagen. |
created_at | string (ISO 8601) | Aanmaaktijdstempel, bijvoorbeeld 2026-08-14T10:32:11+00:00. |
kind, company_name, registration_number, vat_id en external_id zijn leesbaar op elk contact maar niet schrijfbaar via register of PATCH /me: een storefrontaccount kan zichzelf niet omzetten in een zakelijk contact. De handelaar stelt deze velden in vanuit de Contacten-pagina's van het klantdashboard.
Gastlevenscyclus
E-mailcapture in de winkelwagen (Commerce-module) kan een contactrij aanmaken met alleen een e-mailadres en geen wachtwoord (een gast). Dit is op drie plekken van belang:
- Registratie upgradet gasten. Registreren met een e-mailadres dat bij een gastrij hoort, upgradet die rij ter plekke: zelfde
id, bestelgeschiedenis behouden. Alleen een e-mailadres dat bij een echt (niet-gast) account hoort, faalt met422 "Email already registered.". - Gasten kunnen niet inloggen. Ze hebben geen wachtwoord, dus inloggen faalt met de generieke
422 "Invalid credentials.". - Wachtwoordherstel upgradet ook. Het voltooien van een reset zet een wachtwoord, markeert het account als niet-gast, en zet
email_verified_atals dat nog niet gezet was. Dit is een tweede pad van gast-checkout naar een volwaardig account.
Rate limits
Alle contact-endpoints delen de storefront-limiet van 120 requests per minuut per winkel (429 met een Retry-After header bij overschrijding). De vier credential-endpoints (register, login, forgot-password, reset-password) dragen een extra limiet van 10 requests per minuut per client-IP om brute-force-pogingen af te remmen.
Fouten
Alle fout-envelopes zijn de standaard storefront-vormen:
| Status | Body | Oorzaak |
|---|---|---|
| 401 | {"message":"Unauthenticated."} | Ontbrekende of ongeldige tenant-API-key. |
| 401 | {"message":"Invalid customer token."} | Ontbrekende of ongeldige X-Customer-Token op een contact-geauthenticeerde route. |
| 403 | {"message":"Invalid ability provided."} | API-key mist de vereiste scope. |
| 403 | {"message":"Tenant suspended.","code":"tenant_suspended"} | Winkel geschorst. |
| 404 | {"message":"..."} | Resource niet gevonden (of niet van het geauthenticeerde contact). |
| 422 | {"message":"...","errors":{"field":["..."]}} | Validatiefout. |
| 429 | {"message":"Too Many Attempts."} | Rate limit overschreden. |