# Registratie en sessies

Deze drie endpoints beheren contactaccounts en sessietokens. `register` en `login` retourneren een `token` naast het contact; stuur dit als `X-Customer-Token` mee op contact-geauthenticeerde endpoints. Alle drie vereisen ze de `contacts:write` scope op je API-key (`customers:write` geaccepteerd).

## POST /v1/api/contacts/register

Ook aangeboden op `/v1/api/customers/register` voor bestaande integraties; identiek request en response.

Registreer een storefront-contactaccount. Retourneert het aangemaakte contact plus een sessietoken. Als het e-mailadres al bij een gastrij hoort (aangemaakt door e-mailcapture in de winkelwagen in de Commerce-module), wordt de gast ter plekke geüpgraded: zelfde `id`, bestelgeschiedenis behouden, naam en wachtwoord gezet vanuit dit request. Alleen een e-mailadres dat bij een echt (niet-gast) account hoort, wordt geweigerd. Extra rate limit: 10 requests per minuut per IP.

### Body-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `name` | string | Ja | Volledige naam. Maximaal 150 tekens. |
| `email` | string | Ja | Geldig e-mailadres, maximaal 255 tekens. Server-side naar lowercase omgezet. Mag niet bij een bestaand niet-gast account horen. |
| `password` | string | Ja | Minimaal 8 tekens. |

```bash title="Request"
curl -X POST https://api.borkol.com/v1/api/contacts/register \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{"name":"Jane Doe","email":"jane@example.com","password":"s3cret-pass"}'
```

```javascript title="Request (JS)"
const res = await fetch("https://api.borkol.com/v1/api/contacts/register", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${apiKey}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Jane Doe",
    email: "jane@example.com",
    password: "s3cret-pass",
  }),
});
const { data: contact, token } = await res.json();
```

Status: `201 Created`.

```json title="Response"
{
  "data": {
    "id": "9d4e2f1a-6b3c-4f8e-9a1d-2c5b7e8f0a3d",
    "name": "Jane Doe",
    "email": "jane@example.com",
    "phone": null,
    "kind": "person",
    "company_name": null,
    "registration_number": null,
    "vat_id": null,
    "external_id": null,
    "display_name": "Jane Doe",
    "created_at": "2026-08-14T10:32:11+00:00"
  },
  "token": "12|Fq8sT3vY6wZx9aBcDeFgHiJkLmNoPqRsTuVwXyZ0"
}
```

### Fouten

- `422` met `errors.email` `["Email already registered."]` wanneer een niet-gast account het e-mailadres al gebruikt.
- `422` bij veldvalidatiefouten (ontbrekende naam, ongeldig e-mailadres, wachtwoord korter dan 8 tekens).
- `429` wanneer de limiet van 10 requests per minuut per IP is overschreden.

## POST /v1/api/contacts/login

Ook aangeboden op `/v1/api/customers/login` voor bestaande integraties; identiek request en response.

Authenticeer een contact met e-mailadres en wachtwoord. Retourneert het contact en een vers sessietoken, en werkt `last_login_at` van het account bij. De controle is timing-safe en onthult nooit of het e-mailadres bestaat: een verkeerd wachtwoord, een onbekend e-mailadres en een gastaccount (dat geen wachtwoord heeft) falen allemaal met dezelfde 422. Extra rate limit: 10 requests per minuut per IP.

### Body-parameters

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `email` | string | Ja | Geldig e-mailadres. Server-side naar lowercase omgezet vóór de lookup. |
| `password` | string | Ja | Het accountwachtwoord. |

```bash title="Request"
curl -X POST https://api.borkol.com/v1/api/contacts/login \
  -H "Authorization: Bearer {api_key}" \
  -H "Content-Type: application/json" \
  -d '{"email":"jane@example.com","password":"s3cret-pass"}'
```

Status: `200 OK`.

```json title="Response"
{
  "data": {
    "id": "9d4e2f1a-6b3c-4f8e-9a1d-2c5b7e8f0a3d",
    "name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+31612345678",
    "kind": "person",
    "company_name": null,
    "registration_number": null,
    "vat_id": null,
    "external_id": null,
    "display_name": "Jane Doe",
    "created_at": "2026-08-14T10:32:11+00:00"
  },
  "token": "13|Gh7rS2uX5vWy8zAbCdEfGhIjKlMnOpQrStUvWxYz"
}
```

### Fouten

- `422` met `errors.email` `["Invalid credentials."]` voor een verkeerd e-mailadres of een verkeerd wachtwoord. De fout staat altijd op de `email`-key.
- `429` wanneer de limiet van 10 requests per minuut per IP is overschreden.

## POST /v1/api/contacts/logout

Ook aangeboden op `/v1/api/customers/logout` voor bestaande integraties; identiek request en response.

Trek het contactsessietoken in dat in `X-Customer-Token` is meegegeven. De header moet aanwezig en geldig zijn om de contactauthenticatie te passeren: een momenteel geldig token wordt ingetrokken en het request retourneert 204, terwijl een al ingetrokken of onbekend token de authenticatie laat falen met 401 `{"message": "Invalid customer token."}`.

### Headers

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `X-Customer-Token` | string | Ja | Het in te trekken sessietoken. |

Geen body.

```bash title="Request"
curl -X POST https://api.borkol.com/v1/api/contacts/logout \
  -H "Authorization: Bearer {api_key}" \
  -H "X-Customer-Token: 13|Gh7rS2uX5vWy8zAbCdEfGhIjKlMnOpQrStUvWxYz"
```

Status: `204 No Content`. De respons heeft geen body.

### Fouten

- `401` `{"message":"Invalid customer token."}` wanneer `X-Customer-Token` ontbreekt of ongeldig is.
