# REST API-referentie

Alle endpoints, vereiste rechten en invoervelden van de Trelyn API v1.

Deze referentie wordt uit dezelfde endpointdefinities opgebouwd als de API. Gebruik de basis-URL van je eigen installatie met `/api/v1`, bijvoorbeeld `https://app.trelyn.nl/api/v1`.

[Download de OpenAPI 3.1-specificatie](/developers/openapi.json). De actuele specificatie van jouw installatie staat op `GET /api/v1/openapi.json`; daarvoor is geen sleutel nodig. Je kunt het bestand importeren in Postman of een OpenAPI-clientgenerator.

Alle overige endpoints vereisen `Authorization: Bearer <API-sleutel>`. Velden gebruiken camelCase. Record-ID's zijn UUID's. Onbekende velden worden geweigerd. Er zijn geen DELETE-endpoints. Een schrijfvinkje geeft alleen toegang tot de hieronder genoemde schrijfoperaties.

## Antwoorden en paginering

Een lijst geeft `{ data: [...], nextCursor: string | null, total?: number, requestId: string }`. Gebruik `nextCursor` als volgende `cursor` met dezelfde filters. Een lege lijst geeft `data: []` en `nextCursor: null`. De standaardlimiet is doorgaans 50, maximaal 200; endpoints zonder limietveld geven de volledige kleine referentielijst. De volgorde hangt af van de resource; wijzigingen tijdens het bladeren kunnen records verschuiven, dus ontdubbel op ID.

Een detail geeft `{ data: {...}, requestId: string }`, zonder uitgebreide gerelateerde tijdlijnen. Een schrijfoperatie geeft het resultaat in `data`, bijvoorbeeld `{ created: "company", id: "<uuid>" }` of `{ updated: "company", id: "<uuid>", fields: ["name"] }`. Haal het record daarna met GET op voor de actuele gegevens. POST-aanmaak geeft 201; GET, PATCH en taakafronding geven 200.

Bedrijven bevatten onder andere `id`, `name`, `website`, `email`, `phone` en `industry`. Contactpersonen bevatten `id`, `firstName`, `lastName`, contactgegevens en bedrijfsrelaties. Deals bevatten `id`, `name`, `status`, `stage`, `pipelineId`, `company`, `nextStep` en afgeschermde bedragen. Taken en activiteiten bevatten `id`, `type`, `body`, `done` en `dueAt`. Projecten bevatten `id`, `name`, `status`, klantkoppelingen en taakvoortgang. Financiële velden volgen zowel de sleutelvinkjes als de actuele rol.

## Verbinding controleren

`GET /me` geeft `data.workspace` (id, name, slug) en `data.scopes` terug. Dit zijn de ingestelde sleutelrechten; de actuele rol en abonnementsbeperkingen kunnen de effectieve toegang verder begrenzen.

## GET /companies

Vereist: `companies:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /companies/{id}

Vereist: `companies:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /companies

Vereist: `companies:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Ja |  |
| `website` | string | Nee |  |
| `email` | string | Nee |  |
| `phone` | string | Nee |  |
| `industry` | string | Nee |  |

## PATCH /companies/{id}

Vereist: `companies:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Nee |  |
| `website` | string | Nee |  |
| `email` | string | Nee |  |
| `phone` | string | Nee |  |
| `industry` | string | Nee |  |

## GET /contacts

Vereist: `contacts:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /contacts/{id}

Vereist: `contacts:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /contacts

Vereist: `contacts:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `firstName` | string | Ja |  |
| `lastName` | string | Ja |  |
| `email` | string | Nee |  |
| `phone` | string | Nee |  |
| `jobTitle` | string | Nee |  |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## PATCH /contacts/{id}

Vereist: `contacts:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `firstName` | string | Nee |  |
| `lastName` | string | Nee |  |
| `email` | string | Nee |  |
| `phone` | string | Nee |  |
| `otherEmails` | array | Nee | Further addresses/numbers, besides the main one. The complete list: anything left out is removed. |
| `otherPhones` | array | Nee | Further addresses/numbers, besides the main one. The complete list: anything left out is removed. |
| `jobTitle` | string | Nee |  |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## GET /deals

Vereist: `deals:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `status` | string | Nee | Waarden: active, on_hold, won, lost. |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /deals/{id}

Vereist: `deals:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /deals

Vereist: `deals:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Ja |  |
| `pipelineId` | string | Ja | The record's id, as returned by a list or search tool. |
| `stageId` | string | Ja | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactIds` | array | Nee |  |
| `priority` | string | Nee | Waarden: low, medium, high. |
| `nextStep` | string | Nee | What has to happen next on this deal. |
| `nextActionDate` | string | Nee | YYYY-MM-DD, when that next step is due. |
| `source` | string | Nee |  |
| `acquisitionType` | string | Nee | Waarden: inbound, outbound, referral, existing_client, partner, other. |
| `revenueModel` | string | Nee | Pricing model, separate from contractType (agreement type). Waarden: one_time, recurring, hybrid. |
| `estimatedBudget` | number | Nee |  |
| `oneTimeRevenue` | number | Nee | Money billed once. |
| `mrr` | number | Nee | Money billed every month. |
| `contractType` | string | Nee | Waarden: fixed, indefinite. |
| `contractTermMonths` | integer | Nee | Only on a fixed-term contract. |

## PATCH /deals/{id}

Vereist: `deals:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Nee |  |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactIds` | array | Nee | Replaces the whole list of people on the deal. |
| `priority` | string | Nee | Waarden: low, medium, high. |
| `nextStep` | string | Nee |  |
| `nextActionDate` | string | Nee | YYYY-MM-DD. |
| `source` | string | Nee |  |
| `acquisitionType` | string | Nee | Waarden: inbound, outbound, referral, existing_client, partner, other. |
| `revenueModel` | string | Nee | Pricing model, separate from contractType (agreement type). Waarden: one_time, recurring, hybrid. |
| `estimatedBudget` | number | Nee |  |
| `oneTimeRevenue` | number | Nee |  |
| `mrr` | number | Nee |  |
| `contractType` | string | Nee | Waarden: fixed, indefinite. |
| `contractTermMonths` | integer | Nee |  |

## GET /tasks

Vereist: `tasks:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `done` | boolean | Nee | Defaults to false: only tasks still to do. |
| `dueBefore` | string | Nee | YYYY-MM-DD or ISO timestamp. |
| `mine` | boolean | Nee | Only tasks assigned to the person this connection acts as. |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /tasks/{id}

Vereist: `tasks:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /tasks

Vereist: `tasks:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `body` | string | Ja | What has to be done. |
| `dueAt` | string | Nee | When it is due: YYYY-MM-DD, or a full ISO 8601 timestamp for a time of day. |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## PATCH /tasks/{id}

Vereist: `tasks:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `body` | string | Nee |  |
| `dueAt` | string | Nee | YYYY-MM-DD or an ISO 8601 timestamp. |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## GET /activities

Vereist: `activities:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /activities/{id}

Vereist: `activities:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /activities

Vereist: `activities:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `type` | string | Ja | Waarden: call, email, meeting. |
| `body` | string | Ja |  |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## GET /projects

Vereist: `projects:read`. De onderstaande velden zijn queryparameters.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `limit` | integer | Nee | How many to return. Defaults to a sensible page; capped by the server. Minimaal 1. Maximaal 200. |
| `cursor` | string | Nee | The `nextCursor` from a previous call to this same tool, to get the following page. Omit for the first page. Treat it as opaque. |

## GET /projects/{id}

Vereist: `projects:read`. Vervang `{id}` door de UUID van het record. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /projects

Vereist: `projects:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Ja |  |
| `description` | string | Nee |  |
| `status` | string | Nee | Default planning. Waarden: planning, active, on_hold, completed, cancelled. |
| `priority` | string | Nee | Waarden: none, low, medium, high, urgent. |
| `projectType` | string | Nee | Free text, like "Website" or "Branding". |
| `startDate` | string | Nee | A date, YYYY-MM-DD. |
| `endDate` | string | Nee | A date, YYYY-MM-DD. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `dealId` | string | Nee | Needs deal access. |
| `ownerUserId` | string | Nee | A member's id, from list_members. |
| `engagementId` | string | Nee | The record's id, as returned by a list or search tool. |
| `budget` | number | Nee | Needs the project financials permission. |

## PATCH /projects/{id}

Vereist: `projects:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `name` | string | Nee |  |
| `description` | string | Nee |  |
| `status` | string | Nee | Waarden: planning, active, on_hold, completed, cancelled. |
| `priority` | string | Nee | Waarden: none, low, medium, high, urgent. |
| `projectType` | string | Nee |  |
| `startDate` | string | Nee | A date, YYYY-MM-DD. Send null to clear it. |
| `endDate` | string | Nee | A date, YYYY-MM-DD. Send null to clear it. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `dealId` | string | Nee | Needs deal access. |
| `ownerUserId` | string | Nee | The record's id, as returned by a list or search tool. |
| `engagementId` | string | Nee | The record's id, as returned by a list or search tool. |
| `budget` | number | Nee | Needs the project financials permission. |

## GET /pipelines

Vereist: `pipelines:read`. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## GET /members

Vereist: `members:read`. De onderstaande velden zijn queryparameters.

Geen extra invoervelden.

## POST /tasks/{id}/complete

Vereist: `tasks:write`. Vervang `{id}` door de UUID van het record. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `done` | boolean | Nee | Defaults to true. |

## POST /activities/notes

Vereist: `activities:write`. Stuur de onderstaande velden als JSON-body.

| Veld | Type | Verplicht | Toelichting |
| --- | --- | --- | --- |
| `body` | string | Ja | What to record, in the words it should be read in. |
| `dealId` | string | Nee | The record's id, as returned by a list or search tool. |
| `contactId` | string | Nee | The record's id, as returned by a list or search tool. |
| `companyId` | string | Nee | The record's id, as returned by a list or search tool. |

## Functionele grenzen

`tasks` zijn CRM-taken, geen projecttaken. `activities` maakt gelogde gesprekken, e-mails en meetings aan; `POST /activities/notes` maakt notities. Een gelogde activiteit plant geen afspraak en verstuurt geen e-mail. `POST /tasks/{id}/complete` rondt een CRM-taak af. Projectdetails geven alleen het project terug, geen projecttaken.

De API biedt hier geen generieke verwijdering, projecttaken, bestanden, facturen, portaalgebruikers of webhookbeheer-endpoints. API-sleutels en webhooks beheer je in het portaal. Een deal aanmaken vereist een bestaand pipeline- en stage-ID; die haal je op via `GET /pipelines`. Alleen de gedocumenteerde dealvelden kunnen met PATCH worden gewijzigd; dealstatusovergangen lopen via het CRM.

Relatievelden kunnen verwijzingen (ID en naam) naar andere CRM-records bevatten. Een sleutel heeft voor het apart ophalen van die records het bijbehorende leestoegangsvinkje nodig. Financiële velden vereisen `deals:values` of `projects:financials`. Voor bedragen wijzigen is bovendien het schrijfrecht op de resource vereist.

Schrijfverzoeken ondersteunen geen idempotency-key. Herhaal een POST na een verbroken verbinding daarom pas nadat je gecontroleerd hebt of het record al is aangemaakt. Gebruik PATCH voor bekende ID's. Zie [fouten en limieten](/developers/fouten-en-limieten/) voor foutantwoorden en [voorbeelden](/developers/voorbeelden/) voor werkende verzoeken.
