# API-referentie

Alle endpoints van de Agreli API, met het benodigde recht, de parameters en voorbeelden. Deze pagina wordt gegenereerd uit de OpenAPI-specificatie; de omschrijvingen komen daar letterlijk uit.

Agreli API 1.0.0. Basis-URL: `https://app.agreli.nl/api/public`. OpenAPI 3.1: `https://app.agreli.nl/api/public/v1/openapi.json`.

## Overzicht

| Methode | Pad | Recht | Wat |
| --- | --- | --- | --- |
| `GET` | [`/v1/organizations`](#get-v1-organizations) | `organization:read` | Organisaties die deze sleutel mag gebruiken |
| `GET` | [`/v1/organization`](#get-v1-organization) | `organization:read` | Organisatie, vestigingen, templates en toegestane domeinen |
| `GET` | [`/v1/onboardings`](#get-v1-onboardings) | `onboardings:read` | Onboardings |
| `POST` | [`/v1/onboardings`](#post-v1-onboardings) | `onboardings:write` | Hosted onboarding aanmaken |
| `GET` | [`/v1/onboardings/{id}`](#get-v1-onboardings-id) | `onboardings:read` | Eén onboarding met stappen en documenten |
| `PATCH` | [`/v1/onboardings/{id}`](#patch-v1-onboardings-id) | `onboardings:write` | Referentie en metadata bijwerken |
| `POST` | [`/v1/onboardings/{id}/hosted-link`](#post-v1-onboardings-id-hosted-link) | `onboardings:write` | Nieuwe hosted link (de vorige vervalt) |
| `POST` | [`/v1/onboardings/{id}/review-sessions`](#post-v1-onboardings-id-review-sessions) | `reviews:embed` | Controlelink voor de ingebedde controle |
| `POST` | [`/v1/onboardings/{id}/cancel`](#post-v1-onboardings-id-cancel) | `onboardings:write` | Annuleren |
| `POST` | [`/v1/onboardings/{id}/identity-verification`](#post-v1-onboardings-id-identity-verification) | `approvals:write` | ID-controle bevestigen (als manager) |
| `POST` | [`/v1/onboardings/{id}/approvals`](#post-v1-onboardings-id-approvals) | `approvals:write` | Goedkeuren als de eigenaar van de sleutel |
| `POST` | [`/v1/onboardings/{id}/contract`](#post-v1-onboardings-id-contract) | `contracts:write` | Contract maken en ter ondertekening versturen |
| `GET` | [`/v1/onboardings/{id}/documents`](#get-v1-onboardings-id-documents) | `documents:read` | Documenten |
| `GET` | [`/v1/onboardings/{id}/documents/{documentId}`](#get-v1-onboardings-id-documents-documentid) | `documents:read` | Document downloaden |
| `GET` | [`/v1/employees`](#get-v1-employees) | `employees:read` | Medewerkers |
| `GET` | [`/v1/approvals`](#get-v1-approvals) | `approvals:read` | Wat jij nu kunt goedkeuren |
| `GET` | [`/v1/integrations`](#get-v1-integrations) | `integrations:read` | Koppelingen en synchronisatiestatus |
| `GET` | [`/v1/webhooks`](#get-v1-webhooks) | `webhooks:manage` | Webhookadressen |
| `POST` | [`/v1/webhooks`](#post-v1-webhooks) | `webhooks:manage` | Webhookadres toevoegen |
| `GET` | [`/v1/webhooks/{id}`](#get-v1-webhooks-id) | `webhooks:manage` | Eén webhookadres met recente afleveringen |
| `DELETE` | [`/v1/webhooks/{id}`](#delete-v1-webhooks-id) | `webhooks:manage` | Verwijderen |
| `POST` | [`/v1/webhooks/{id}/test`](#post-v1-webhooks-id-test) | `webhooks:manage` | Testbericht (ping) sturen |
| `POST` | [`/v1/webhooks/{id}/rotate-secret`](#post-v1-webhooks-id-rotate-secret) | `webhooks:manage` | Geheim vernieuwen |
| `GET` | [`/v1/webhooks/{id}/deliveries`](#get-v1-webhooks-id-deliveries) | `webhooks:manage` | Afleverlog van één adres |
| `POST` | [`/v1/webhooks/{id}/deliveries/{deliveryId}/retry`](#post-v1-webhooks-id-deliveries-deliveryid-retry) | `webhooks:manage` | Aflevering opnieuw versturen |
| `GET` | [`/v1/events`](#get-v1-events) | `onboardings:read` | Gebeurtenissen (om gemiste webhooks na te lopen) |
| `POST` | [`/v1/sandbox/onboardings/{id}/advance`](#post-v1-sandbox-onboardings-id-advance) | `onboardings:write` | Sandbox: volgende stap naspelen |

## Het onboarding-object

`GET /v1/onboardings/{id}` en de schrijfacties op een onboarding geven dit object terug. In lijsten ontbreken `steps`, `documents`, `email`, `phone` en de arbeidsvoorwaarden. Bij één onboarding staan `email`, `phone` en de arbeidsvoorwaarden er alleen in als de sleutel het dossier mag openen.

```json
{
  "id": "onb_…",
  "object": "onboarding",
  "status": "in_review",
  "waiting_on": ["payroll_reviewer"],
  "returned": false,
  "employee": { "id": "emp_…", "first_name": "Sam", "last_name": "Jansen", "email": "sam@example.com", "phone": null },
  "employment": { "position": "Bediening", "location_id": "loc_…", "start_date": "2026-12-01", "contract_type": "on_call", "hours_per_week": 16, "hourly_wage_cents": 1450 },
  "workflow": { "template_id": "t1", "version": 1 },
  "data_version": 2,
  "approvals": {
    "required": ["manager", "payroll_reviewer"],
    "given": [{ "role": "manager", "valid": true, "data_version": 2, "at": "2026-11-20T10:15:00.000Z" }]
  },
  "contract": { "status": "none" },
  "payroll": null,
  "hosted_link": { "status": "activated", "expires_at": "2026-10-26T12:00:00.000Z", "activated": true },
  "reference": "sollicitant-4711",
  "metadata": { "vacature_id": "vac-311" },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-11-20T10:15:00.000Z",
  "steps": [{ "id": "…", "phase": "gegevens", "kind": "document", "title": "…", "applies": true, "done": true }],
  "documents": [{ "id": "doc_…", "kind": "passport", "title": null, "uploaded_at": "2026-11-20T09:58:00.000Z", "downloadable": false }]
}
```

- `contract.status`: `none`, `sent`, `signed_by_employee` of `signed`.
- `hosted_link.status`: `open`, `activated` of `revoked`.
- `payroll`: `null` tot de verwerking begint; daarna `status`, `external_id` en `error_code`.
- `data_version` gaat omhoog als gegevens of voorwaarden veranderen. Een goedkeuring geldt voor één versie.

Dit object is breder dan het schema `Onboarding` in de OpenAPI-spec; de velden hierboven komen uit de API zelf.

## Statussen

| Status | Betekenis | Aan zet (`waiting_on`) |
| --- | --- | --- |
| `pending_employee` | Uitgenodigd of bezig met invullen. | `employee` |
| `in_review` | Gegevens verstuurd; de controle (vierogen) loopt. | de rollen die nog moeten goedkeuren, of `manager` na terugsturen |
| `contract_ready` | Goedgekeurd; het contract kan worden gemaakt en verstuurd. | `manager` |
| `awaiting_employee_signature` | Contract verstuurd; wacht op de handtekening van de medewerker. | `employee` |
| `awaiting_employer_signature` | De medewerker heeft getekend; wacht op de werkgever. | `manager` |
| `processing` | Getekend; de verwerking in de salarisadministratie loopt. | `system` |
| `action_required` | De verwerking in de salarisadministratie vraagt om een handeling. | `manager`, `payroll_reviewer` |
| `completed` | Afgerond. | niemand |
| `cancelled` | Geannuleerd. | niemand |

## Endpoints

### GET /v1/organizations

Organisaties die deze sleutel mag gebruiken.

Een werkgeverssleutel: de eigen organisatie. Een sleutel van een API-partner: alle werkgevers die de partner hebben toegelaten, met de rechten die ze gaven. Gebruik het id in de kop Agreli-Organization.

Recht: `organization:read`

```bash
curl https://app.agreli.nl/api/public/v1/organizations \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "org_…",
      "object": "organization",
      "name": "…",
      "permissions": [
        "…"
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/organization

Organisatie, vestigingen, templates en toegestane domeinen.

Recht: `organization:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `Agreli-Organization` | header | string | nee | Alleen voor sleutels van een API-partner: de werkgever namens wie je werkt. Verplicht als de partner meer dan één werkgever heeft. |

```bash
curl https://app.agreli.nl/api/public/v1/organization \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "id": "org_…",
  "name": "Brasserie De Haven",
  "locations": [
    {
      "id": "loc_…",
      "name": "De Haven Centrum",
      "city": "Amsterdam"
    }
  ],
  "templates": [
    {
      "id": "t1",
      "name": "Oproepkracht bediening",
      "contract_type": "on_call",
      "cao": "Cao Horeca"
    }
  ],
  "branding": {
    "color": "#0f5132",
    "logo_url": null
  },
  "allowed_origins": [
    "https://jouwapp.nl"
  ]
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/onboardings

Onboardings.

Nieuwste eerst, ook geannuleerde (filter met status). Een API-partner ziet alleen de onboardings die via zijn eigen sleutels liepen.

Recht: `onboardings:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `status` | query | `pending_employee`, `in_review`, `contract_ready`, `awaiting_employee_signature`, `awaiting_employer_signature`, `processing`, `action_required`, `completed`, `cancelled` | nee | — |
| `reference` | query | string | nee | — |
| `updated_since` | query | string (date-time) | nee | — |
| `limit` | query | integer | nee | 1 tot 100. Standaard `25`. |
| `starting_after` | query | string | nee | — |

```bash
curl https://app.agreli.nl/api/public/v1/onboardings \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "onb_…",
      "status": "pending_employee",
      "waiting_on": [
        "employee"
      ],
      "employee": {},
      "employment": {},
      "data_version": 1,
      "approvals": {},
      "contract": {},
      "payroll": null,
      "hosted_link": null,
      "reference": "sollicitant-4711",
      "metadata": {
        "vacature_id": "vac-311"
      },
      "return_url": "https://jouwapp.nl/onboarding/klaar",
      "source": "api",
      "created_at": "2026-10-12T12:00:00.000Z",
      "updated_at": "2026-10-12T12:00:00.000Z",
      "steps": [],
      "documents": [
        {
          "id": "doc_…",
          "kind": "contract_signed",
          "title": "Arbeidsovereenkomst",
          "uploaded_at": "2026-10-12T12:00:00.000Z",
          "downloadable": true
        }
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings

Hosted onboarding aanmaken.

Alleen met een lopende proef of een abonnement van wie betaalt (anders 403 subscription_required).

Recht: `onboardings:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `reference` | string | nee | Je eigen kenmerk; komt terug in de API en in webhooks. Hooguit 200 tekens. |
| `metadata` | object (sleutel → string \| number \| boolean) | nee | Je eigen kenmerken, bijvoorbeeld een vacature-id (sleutels: letters, cijfers, _ . -, hooguit 40 tekens; tekst hooguit 500). Komt terug in de API en in webhooks. Geen persoonsgegevens: e-mail, IBAN, BSN en telefoonnummers worden geweigerd (metadata_personal_data). Hooguit 20 sleutels. |
| `employee` | object | ja | — |
| `employee.first_name` | string | ja | — |
| `employee.last_name` | string | ja | — |
| `employee.email` | string (email) | ja | — |
| `employee.phone` | string | nee | — |
| `employment` | object | ja | — |
| `employment.position` | string | ja | — |
| `employment.start_date` | string (date) | ja | — |
| `employment.location_id` | string | ja | — |
| `employment.template_id` | string | ja | — |
| `employment.contract_type` | `on_call`, `fixed_term`, `permanent` | nee | Standaard die van de template. |
| `employment.hours_per_week` | number | ja | 0 tot 60. |
| `employment.hourly_wage_cents` | integer | ja | Minimaal 1. |
| `options` | object | nee | — |
| `options.send_invitation` | boolean | nee | true: wij mailen de medewerker de link. false: jij stuurt de medewerker naar hosted_url. Standaard `false`. |
| `options.expires_in_hours` | integer | nee | 1 tot 336. Standaard `336`. |
| `options.return_url` | string (uri) | nee | Na afronden kan de medewerker hierheen terug. Alleen https, op een domein uit allowed_origins (van de werkgever, of van de API-partner); anders 422 return_url_not_allowed. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "sollicitant-4711",
    "metadata": {
      "vacature_id": "vac-311"
    },
    "employee": {
      "first_name": "Sam",
      "last_name": "Jansen",
      "email": "sam@example.com",
      "phone": "+31 6 12345678"
    },
    "employment": {
      "position": "Bediening",
      "start_date": "2026-12-01",
      "location_id": "loc_…",
      "template_id": "t1",
      "contract_type": "on_call",
      "hours_per_week": 16,
      "hourly_wage_cents": 1450
    },
    "options": {
      "send_invitation": false,
      "expires_in_hours": 336,
      "return_url": "https://jouwapp.nl/onboarding/klaar"
    }
  }'
```

Antwoord `201` (Aangemaakt):

```json
{
  "id": "onb_…",
  "object": "onboarding",
  "status": "pending_employee",
  "hosted_url": "https://app.agreli.nl/m/…",
  "expires_at": "2026-10-26T12:00:00.000Z",
  "invitation_sent": false,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  }
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/onboardings/{id}

Eén onboarding met stappen en documenten.

Recht: `onboardings:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |

```bash
curl https://app.agreli.nl/api/public/v1/onboardings/onb_… \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### PATCH /v1/onboardings/{id}

Referentie en metadata bijwerken.

Voegt metadata samen; null verwijdert een sleutel. Gegevens van de medewerker wijzig je niet via de API (field_not_updatable). De data_version blijft gelijk, dus goedkeuringen blijven geldig.

Recht: `onboardings:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `reference` | string \| null | nee | Hooguit 200 tekens. |
| `metadata` | object (sleutel → string \| number \| boolean \| null) | nee | Je eigen kenmerken, bijvoorbeeld een vacature-id (sleutels: letters, cijfers, _ . -, hooguit 40 tekens; tekst hooguit 500). Komt terug in de API en in webhooks. Geen persoonsgegevens: e-mail, IBAN, BSN en telefoonnummers worden geweigerd (metadata_personal_data). Hooguit 20 sleutels. |

```bash
curl -X PATCH https://app.agreli.nl/api/public/v1/onboardings/onb_… \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "sollicitant-4711",
    "metadata": {
      "vacature_id": "vac-311"
    }
  }'
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/hosted-link

Nieuwe hosted link (de vorige vervalt).

Recht: `onboardings:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON, optioneel):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `expires_in_hours` | integer | nee | 1 tot 336. |
| `send_invitation` | boolean | nee | Standaard `false`. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/hosted-link \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "expires_in_hours": 336,
    "send_invitation": false
  }'
```

Antwoord `201` (OK):

```json
{
  "onboarding_id": "onb_…",
  "hosted_url": "https://app.agreli.nl/m/…",
  "expires_at": "2026-10-26T12:00:00.000Z",
  "invitation_sent": false
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/review-sessions

Controlelink voor de ingebedde controle.

Een manager van de werkgever controleert en keurt goed in jouw product, in een iframe (embed.js met review_url). Het BSN en het identiteitsbewijs blijven bij Agreli. De eerste keer logt de controleur in de iframe in met een eigen Agreli-account; daarna is jouw gebruiker (external_id) 30 dagen gekoppeld en opent de controle direct. De link is 15 minuten geldig en opent één keer: vraag hem aan op het moment dat je de controle toont. Een partner heeft hiervoor het recht reviews:embed van de werkgever nodig.

Recht: `reviews:embed`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `reviewer` | object | ja | — |
| `reviewer.email` | string (email) | ja | E-mailadres van het Agreli-account van de controleur. |
| `reviewer.external_id` | string | ja | Vast id van deze gebruiker in jouw product. Hooguit 200 tekens. |
| `reviewer.name` | string | nee | Hooguit 120 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/review-sessions \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "reviewer": {
      "email": "sam@example.com",
      "external_id": "…",
      "name": "…"
    }
  }'
```

Antwoord `201` (OK):

```json
{
  "id": "…",
  "onboarding_id": "onb_…",
  "review_url": "…",
  "expires_at": "2026-10-26T12:00:00.000Z",
  "reviewer": {
    "email": "sam@example.com",
    "external_id": "…",
    "name": "…",
    "linked": false
  }
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/cancel

Annuleren.

Recht: `onboardings:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/cancel \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/identity-verification

ID-controle bevestigen (als manager).

Staat standaard uit: een eigenaar zet goedkeuren via de API aan bij Instellingen, API en webhooks (anders 403 api_approvals_disabled).

Recht: `approvals:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/identity-verification \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/approvals

Goedkeuren als de eigenaar van de sleutel.

Vierogen: één persoon kan niet twee rollen vervullen. data_version moet gelijk zijn aan de gecontroleerde versie. Staat standaard uit: een eigenaar zet goedkeuren via de API aan bij Instellingen, API en webhooks (anders 403 api_approvals_disabled).

Recht: `approvals:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `role` | `manager`, `payroll_reviewer`, `owner` | ja | — |
| `data_version` | integer | ja | — |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/approvals \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "role": "manager",
    "data_version": 1
  }'
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/onboardings/{id}/contract

Contract maken en ter ondertekening versturen.

Recht: `contracts:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/onboardings/onb_…/contract \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK):

```json
{
  "id": "onb_…",
  "status": "pending_employee",
  "waiting_on": [
    "employee"
  ],
  "employee": {},
  "employment": {},
  "data_version": 1,
  "approvals": {},
  "contract": {},
  "payroll": null,
  "hosted_link": null,
  "reference": "sollicitant-4711",
  "metadata": {
    "vacature_id": "vac-311"
  },
  "return_url": "https://jouwapp.nl/onboarding/klaar",
  "source": "api",
  "created_at": "2026-10-12T12:00:00.000Z",
  "updated_at": "2026-10-12T12:00:00.000Z",
  "steps": [],
  "documents": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ]
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/onboardings/{id}/documents

Documenten.

Recht: `documents:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |

```bash
curl https://app.agreli.nl/api/public/v1/onboardings/onb_…/documents \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "doc_…",
      "kind": "contract_signed",
      "title": "Arbeidsovereenkomst",
      "uploaded_at": "2026-10-12T12:00:00.000Z",
      "downloadable": true
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/onboardings/{id}/documents/{documentId}

Document downloaden.

Kopieën van identiteitsbewijzen alleen voor de salarisadministratie. Elke download staat in de audit.

Recht: `documents:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `documentId` | path | string | ja | — |

```bash
curl https://app.agreli.nl/api/public/v1/onboardings/onb_…/documents/doc_… \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200`: Het bestand (`application/pdf`, `image/png`, `image/jpeg`).

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/employees

Medewerkers.

Recht: `employees:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `limit` | query | integer | nee | 1 tot 100. |
| `starting_after` | query | string | nee | — |

```bash
curl https://app.agreli.nl/api/public/v1/employees \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "emp_…",
      "first_name": "Sam",
      "last_name": "Jansen",
      "position": "Bediening",
      "location_id": "loc_…",
      "start_date": "2026-12-01",
      "onboarding": {}
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/approvals

Wat jij nu kunt goedkeuren.

Recht: `approvals:read`

```bash
curl https://app.agreli.nl/api/public/v1/approvals \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "onboarding_id": "onb_…",
      "data_version": 1,
      "can_approve_as": [
        "payroll_reviewer"
      ],
      "blocked_by": []
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/integrations

Koppelingen en synchronisatiestatus.

Recht: `integrations:read`

```bash
curl https://app.agreli.nl/api/public/v1/integrations \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK): een JSON-object; de velden staan niet in de spec.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/webhooks

Webhookadressen.

Recht: `webhooks:manage`

```bash
curl https://app.agreli.nl/api/public/v1/webhooks \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "wh_…",
      "url": "https://jouwapp.nl/webhooks/agreli",
      "events": [
        "onboarding.approval_required",
        "onboarding.completed"
      ],
      "status": "enabled",
      "api_version": "…",
      "previous_secret_expires_at": "2026-10-12T12:00:00.000Z",
      "secret": "whsec_…",
      "recent_deliveries": [
        {
          "id": "whd_…",
          "object": "webhook_delivery",
          "event_id": "evt_…",
          "event_type": "…",
          "status": "pending",
          "attempts": 1,
          "last_status_code": 1,
          "last_error": "…",
          "created_at": "2026-10-12T12:00:00.000Z",
          "delivered_at": "2026-10-12T12:00:00.000Z",
          "next_attempt_at": "2026-10-12T12:00:00.000Z"
        }
      ]
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/webhooks

Webhookadres toevoegen.

Het geheim (whsec_…) staat alleen in dit antwoord.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `url` | string (uri) | ja | — |
| `description` | string | nee | — |
| `events` | array van `contract.sent`, `contract.signed`, `contract.signed_by_employee`, `integration.sync_failed`, `integration.sync_succeeded`, `onboarding.approval_given`, `onboarding.approval_required`, `onboarding.approved`, `onboarding.cancelled`, `onboarding.completed`, `onboarding.contract_signed`, `onboarding.created`, `onboarding.employee_submitted`, `onboarding.failed`, `onboarding.invitation_sent`, `onboarding.returned`, `onboarding.started`, `onboarding.submitted`, `onboarding.terms_changed`, `payroll.completed` | nee | Leeg = alle gebeurtenissen. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/webhooks \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://jouwapp.nl/webhooks/agreli",
    "description": "Productie",
    "events": [
      "onboarding.approval_required",
      "onboarding.completed"
    ]
  }'
```

Antwoord `201` (OK):

```json
{
  "id": "wh_…",
  "url": "https://jouwapp.nl/webhooks/agreli",
  "events": [
    "onboarding.approval_required",
    "onboarding.completed"
  ],
  "status": "enabled",
  "api_version": "…",
  "previous_secret_expires_at": "2026-10-12T12:00:00.000Z",
  "secret": "whsec_…",
  "recent_deliveries": [
    {
      "id": "whd_…",
      "object": "webhook_delivery",
      "event_id": "evt_…",
      "event_type": "…",
      "status": "pending",
      "attempts": 1,
      "last_status_code": 1,
      "last_error": "…",
      "created_at": "2026-10-12T12:00:00.000Z",
      "delivered_at": "2026-10-12T12:00:00.000Z",
      "next_attempt_at": "2026-10-12T12:00:00.000Z"
    }
  ]
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/webhooks/{id}

Eén webhookadres met recente afleveringen.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |

```bash
curl https://app.agreli.nl/api/public/v1/webhooks/wh_… \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "id": "wh_…",
  "url": "https://jouwapp.nl/webhooks/agreli",
  "events": [
    "onboarding.approval_required",
    "onboarding.completed"
  ],
  "status": "enabled",
  "api_version": "…",
  "previous_secret_expires_at": "2026-10-12T12:00:00.000Z",
  "secret": "whsec_…",
  "recent_deliveries": [
    {
      "id": "whd_…",
      "object": "webhook_delivery",
      "event_id": "evt_…",
      "event_type": "…",
      "status": "pending",
      "attempts": 1,
      "last_status_code": 1,
      "last_error": "…",
      "created_at": "2026-10-12T12:00:00.000Z",
      "delivered_at": "2026-10-12T12:00:00.000Z",
      "next_attempt_at": "2026-10-12T12:00:00.000Z"
    }
  ]
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### DELETE /v1/webhooks/{id}

Verwijderen.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X DELETE https://app.agreli.nl/api/public/v1/webhooks/wh_… \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK): een JSON-object; de velden staan niet in de spec.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/webhooks/{id}/test

Testbericht (ping) sturen.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/webhooks/wh_…/test \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK): een JSON-object; de velden staan niet in de spec.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/webhooks/{id}/rotate-secret

Geheim vernieuwen.

Het nieuwe geheim (alleen in dit antwoord) ondertekent direct. Het vorige ondertekent nog overlap_hours mee als tweede v1 in Agreli-Signature, zodat je zonder gemiste webhooks overstapt. 0 = het vorige is direct ongeldig.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

Request body (JSON, optioneel):

| Veld | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- |
| `overlap_hours` | integer | nee | 0 tot 168. Standaard `24`. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/webhooks/wh_…/rotate-secret \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "overlap_hours": 24
  }'
```

Antwoord `200` (OK):

```json
{
  "id": "wh_…",
  "url": "https://jouwapp.nl/webhooks/agreli",
  "events": [
    "onboarding.approval_required",
    "onboarding.completed"
  ],
  "status": "enabled",
  "api_version": "…",
  "previous_secret_expires_at": "2026-10-12T12:00:00.000Z",
  "secret": "whsec_…",
  "recent_deliveries": [
    {
      "id": "whd_…",
      "object": "webhook_delivery",
      "event_id": "evt_…",
      "event_type": "…",
      "status": "pending",
      "attempts": 1,
      "last_status_code": 1,
      "last_error": "…",
      "created_at": "2026-10-12T12:00:00.000Z",
      "delivered_at": "2026-10-12T12:00:00.000Z",
      "next_attempt_at": "2026-10-12T12:00:00.000Z"
    }
  ]
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/webhooks/{id}/deliveries

Afleverlog van één adres.

Nieuwste eerst. Afleveringen blijven 30 dagen zichtbaar.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `status` | query | `pending`, `in_progress`, `succeeded`, `failed`, `dead` | nee | — |
| `limit` | query | integer | nee | 1 tot 100. Standaard `25`. |
| `starting_after` | query | string | nee | next_cursor van de vorige pagina. |

```bash
curl https://app.agreli.nl/api/public/v1/webhooks/wh_…/deliveries \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "whd_…",
      "object": "webhook_delivery",
      "event_id": "evt_…",
      "event_type": "…",
      "status": "pending",
      "attempts": 1,
      "last_status_code": 1,
      "last_error": "…",
      "created_at": "2026-10-12T12:00:00.000Z",
      "delivered_at": "2026-10-12T12:00:00.000Z",
      "next_attempt_at": "2026-10-12T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/webhooks/{id}/deliveries/{deliveryId}/retry

Aflevering opnieuw versturen.

Met hetzelfde event-id en dezelfde inhoud, dus je kunt ontdubbelen. Kan bij geslaagde, mislukte en definitief mislukte afleveringen.

Recht: `webhooks:manage`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `deliveryId` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/webhooks/wh_…/deliveries/{deliveryId}/retry \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK):

```json
{
  "id": "whd_…",
  "object": "webhook_delivery",
  "event_id": "evt_…",
  "event_type": "…",
  "status": "pending",
  "attempts": 1,
  "last_status_code": 1,
  "last_error": "…",
  "created_at": "2026-10-12T12:00:00.000Z",
  "delivered_at": "2026-10-12T12:00:00.000Z",
  "next_attempt_at": "2026-10-12T12:00:00.000Z"
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### GET /v1/events

Gebeurtenissen (om gemiste webhooks na te lopen).

Dezelfde gebeurtenissen als de webhooks, met hetzelfde id en dezelfde inhoud, ook als je geen webhookadres hebt. Oudste eerst; bewaard 30 dagen. Bewaar het laatste id en vraag daarna op met starting_after.

Recht: `onboardings:read`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `Agreli-Organization` | header | string | nee | Alleen voor sleutels van een API-partner: de werkgever namens wie je werkt. Verplicht als de partner meer dan één werkgever heeft. |
| `since` | query | string (date-time) | nee | — |
| `type` | query | `contract.sent`, `contract.signed`, `contract.signed_by_employee`, `integration.sync_failed`, `integration.sync_succeeded`, `onboarding.approval_given`, `onboarding.approval_required`, `onboarding.approved`, `onboarding.cancelled`, `onboarding.completed`, `onboarding.contract_signed`, `onboarding.created`, `onboarding.employee_submitted`, `onboarding.failed`, `onboarding.invitation_sent`, `onboarding.returned`, `onboarding.started`, `onboarding.submitted`, `onboarding.terms_changed`, `payroll.completed` | nee | — |
| `limit` | query | integer | nee | 1 tot 100. Standaard `50`. |
| `starting_after` | query | string | nee | next_cursor van de vorige pagina. |

```bash
curl https://app.agreli.nl/api/public/v1/events \
  -H "Authorization: Bearer $AGRELI_API_KEY"
```

Antwoord `200` (OK):

```json
{
  "object": "list",
  "data": [
    {
      "id": "evt_…",
      "object": "event",
      "type": "contract.sent",
      "api_version": "…",
      "created_at": "2026-10-12T12:00:00.000Z",
      "organization_id": "org_…",
      "data": {
        "onboarding_id": "onb_…",
        "reference": "sollicitant-4711",
        "metadata": {
          "vacature_id": "vac-311"
        },
        "data_version": 1,
        "role": "…",
        "returned_to": "…",
        "kind": "invitation",
        "connector": "…",
        "error_code": "…"
      }
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

### POST /v1/sandbox/onboardings/{id}/advance

Sandbox: volgende stap naspelen.

Alleen met een testsleutel. Vult de gegevens in, keurt goed met testgebruikers, tekent en rondt de gesimuleerde salarisverwerking af.

Recht: `onboardings:write`

| Parameter | In | Type | Verplicht | Omschrijving |
| --- | --- | --- | --- | --- |
| `id` | path | string | ja | — |
| `Idempotency-Key` | header | string | nee | Zelfde sleutel en inhoud binnen 24 uur geeft hetzelfde antwoord. Loopt het eerste verzoek nog, dan 409 idempotency_in_progress: probeer het zo opnieuw. Hooguit 200 tekens. |

```bash
curl -X POST https://app.agreli.nl/api/public/v1/sandbox/onboardings/onb_…/advance \
  -H "Authorization: Bearer $AGRELI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

Antwoord `200` (OK):

```json
{
  "step": "employee_submitted",
  "onboarding": {
    "id": "onb_…",
    "status": "pending_employee",
    "waiting_on": [
      "employee"
    ],
    "employee": {},
    "employment": {},
    "data_version": 1,
    "approvals": {},
    "contract": {},
    "payroll": null,
    "hosted_link": null,
    "reference": "sollicitant-4711",
    "metadata": {
      "vacature_id": "vac-311"
    },
    "return_url": "https://jouwapp.nl/onboarding/klaar",
    "source": "api",
    "created_at": "2026-10-12T12:00:00.000Z",
    "updated_at": "2026-10-12T12:00:00.000Z",
    "steps": [],
    "documents": [
      {
        "id": "doc_…",
        "kind": "contract_signed",
        "title": "Arbeidsovereenkomst",
        "uploaded_at": "2026-10-12T12:00:00.000Z",
        "downloadable": true
      }
    ]
  }
}
```

Een `{}` in dit voorbeeld is een object waarvan de spec de velden niet vastlegt.

Fouten: `401`, `403`, `404`, `409`, `422`, `429`, in de vaste foutvorm.

## Rechten

| Recht | Wat het toestaat | Endpoints |
| --- | --- | --- |
| `approvals:read` | Openstaande controles lezen | `GET /v1/approvals` |
| `approvals:write` | Goedkeuren en de ID-controle bevestigen, als jijzelf | `POST /v1/onboardings/{id}/identity-verification`, `POST /v1/onboardings/{id}/approvals` |
| `contracts:write` | Contract maken en ter ondertekening versturen | `POST /v1/onboardings/{id}/contract` |
| `documents:read` | Documenten en toegestane downloads | `GET /v1/onboardings/{id}/documents`, `GET /v1/onboardings/{id}/documents/{documentId}` |
| `employees:read` | Medewerkers en dienstverbanden lezen | `GET /v1/employees` |
| `integrations:read` | Koppelingen en synchronisatiestatus lezen | `GET /v1/integrations` |
| `onboardings:read` | Onboardings en hun status lezen | `GET /v1/onboardings`, `GET /v1/onboardings/{id}`, `GET /v1/events` |
| `onboardings:write` | Onboardings starten, links maken en annuleren | `POST /v1/onboardings`, `PATCH /v1/onboardings/{id}`, `POST /v1/onboardings/{id}/hosted-link`, `POST /v1/onboardings/{id}/cancel`, `POST /v1/sandbox/onboardings/{id}/advance` |
| `organization:read` | Organisatie en vestigingen lezen | `GET /v1/organizations`, `GET /v1/organization` |
| `reviews:embed` | Controle inbedden: een manager van de werkgever keurt goed in jouw product | `POST /v1/onboardings/{id}/review-sessions` |
| `webhooks:manage` | Webhooks beheren | `GET /v1/webhooks`, `POST /v1/webhooks`, `GET /v1/webhooks/{id}`, `DELETE /v1/webhooks/{id}`, `POST /v1/webhooks/{id}/test`, `POST /v1/webhooks/{id}/rotate-secret`, `GET /v1/webhooks/{id}/deliveries`, `POST /v1/webhooks/{id}/deliveries/{deliveryId}/retry` |
