Authenticatie met API-sleutels
Elke call naar de API gebruikt een credential in de Authorization-header. Een credential bestaat uit een publiek prefix en een geheim, samen in de vorm kp_<prefix>_<secret>.
Stap 1
Maak een credential
Ga naar Instellingen, Integraties en maak een API-sleutel met een label en een set scopes. De volledige sleutel wordt precies één keer getoond, bewaar hem meteen veilig.
Stap 2
Werk met minimale scopes
Geef een sleutel enkel de scopes die je integratie nodig heeft. Een call zonder de vereiste scope krijgt een 403 met code insufficient_scope.
Stap 3
Roep de API aan
Stuur de sleutel mee als Bearer token in de Authorization-header. Behandel de sleutel als een wachtwoord: wie hem heeft, kan binnen de scopes namens je account handelen.
curl https://www.keypilot.eu/api/v1/properties?limit=25 \ -H "Authorization: Bearer kp_<prefix>_<secret>"
Scopes
Scopes begrenzen wat een credential mag. Je combineert lees- en schrijfrechten per resource en kan een sleutel op elk moment roteren of intrekken.
properties:read
Panden oplijsten en ophalen.
properties:write
Panden aanmaken en bijwerken.
contacts:read
Contacten (huurders en aannemers) oplijsten en ophalen.
contacts:write
Contacten aanmaken en bijwerken.
contracts:read
Contracten oplijsten en ophalen.
contracts:write
Contracten aanmaken en bijwerken.
tasks:read
Taken oplijsten en ophalen.
tasks:write
Taken aanmaken en bijwerken.
maintenance:read
Onderhoudsaanvragen oplijsten en ophalen.
maintenance:write
Onderhoudsaanvragen aanmaken en bijwerken.
webhooks:manage
Webhook-abonnementen beheren (vandaag via Instellingen, Integraties).
Paginatie
Lijstendpoints gebruiken cursorpaginatie en geven resultaten oplopend op id terug.
Stuur limit mee (1 tot 100, standaard 25) voor de paginagrootte. Zolang nextCursor niet null is, haal je de volgende pagina op met cursor=<nextCursor>. Zo loop je de volledige collectie door zonder dubbels of gaten.
{ "data": [ { "id": 42, "address": "Grote Markt 1", "...": "…" } ], "pagination": { "limit": 25, "nextCursor": 42 } }
Fouten en limieten
Elke fout volgt dezelfde envelop: een machineleesbare code, een leesbare message en een requestId voor support.
{ "error": { "code": "insufficient_scope", "message": "This endpoint requires contacts:write.", "requestId": "9f1c…" } }
unauthorized
Geen geldige credential, of de sleutel is ingetrokken (401).
insufficient_scope
De credential mist de vereiste scope voor dit endpoint (403).
invalid_request
De payload of parameters voldoen niet aan de validatie (400).
not_found
De resource bestaat niet of hoort niet bij je account (404).
idempotency_conflict
Deze Idempotency-Key werd al gebruikt voor een andere request (409).
idempotency_in_progress
Een request met deze Idempotency-Key loopt nog (409).
rate_limited
Te veel requests binnen het tijdvenster (429).
Limiet: 900 requests per 15 minuten per credential. De RateLimit-headers op elke response tonen hoeveel er nog over is.
POST- en PATCH-calls aanvaarden een Idempotency-Key-header. Stuur je dezelfde key opnieuw, dan krijg je het opgeslagen antwoord zonder dat de mutatie een tweede keer uitgevoerd wordt. Zo kunnen retries nooit dubbele records aanmaken.
Webhooks
Abonneer een HTTPS-endpoint op wijzigingen in je account. Je beheert abonnementen in Instellingen, Integraties. Elke levering is een POST met een JSON-event, ondertekend met het secret dat je bij het aanmaken eenmalig ziet.
Events
property.created
property.updated
contact.created
contact.updated
contract.created
contract.updated
task.created
task.updated
maintenance.created
maintenance.updated
Antwoordt je endpoint met een 2xx, dan is de levering gelukt. Bij elke andere uitkomst proberen we tot 5 keer opnieuw met exponentiële backoff (max 60 seconden tussen pogingen). Daarna markeren we de levering als failed.
{ "id": "evt_9f1c…", "type": "property.updated", "createdAt": "2026-08-16T09:30:00.000Z", "data": { "id": 42, "address": "Grote Markt 1", "...": "…" } }
Handtekening verifiëren
Elke levering stuurt de headers x-keypilot-event, x-keypilot-event-id, x-keypilot-timestamp en x-keypilot-signature mee. De handtekening is v1= gevolgd door de hex HMAC-SHA256 van "<timestamp>.<raw body>" met je webhook-secret. Vergelijk timing-safe en verwerk elk event id maximaal één keer.
import crypto from "node:crypto"; // rawBody: the exact request body string, before JSON.parse function verifyKeypilotWebhook(rawBody, secret, timestamp, signature) { const expected = "v1=" + crypto.createHmac("sha256", secret) .update(timestamp + "." + rawBody) .digest("hex"); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); }
Endpointreferentie
Deze referentie wordt rechtstreeks uit de OpenAPI-specificatie gerenderd en kan dus nooit achterlopen. Basis-URL voor alle v1-endpoints: https://www.keypilot.eu/api/v1.
Properties
Buildings and units for rent or sale.
GET
/api/v1/properties
properties:read
List properties
Returns your properties ordered by id, with cursor pagination.
Parameters:
limit (query), cursor (query)
POST
/api/v1/properties
properties:write
Create a property
Creates a property and emits a `property.created` webhook event.
Parameters:
Idempotency-Key (header)
GET
/api/v1/properties/{id}
properties:read
Retrieve a property
Parameters:
id (path)
PATCH
/api/v1/properties/{id}
properties:write
Update a property
Partial update: only the supplied fields change. Emits a `property.updated` webhook event.
Parameters:
id (path), Idempotency-Key (header)
Contacts
Tenants and contractors. Reads of this resource are audit-logged.
GET
/api/v1/contacts
contacts:read
List contacts
Returns your contacts ordered by id, with cursor pagination.
Parameters:
limit (query), cursor (query)
POST
/api/v1/contacts
contacts:write
Create a contact
Creates a contact and emits a `contact.created` webhook event. When `propertyId` is supplied it must reference one of your properties.
Parameters:
Idempotency-Key (header)
GET
/api/v1/contacts/{id}
contacts:read
Retrieve a contact
Parameters:
id (path)
PATCH
/api/v1/contacts/{id}
contacts:write
Update a contact
Partial update: only the supplied fields change. Emits a `contact.updated` webhook event.
Parameters:
id (path), Idempotency-Key (header)
Contracts
Rental contracts linked to properties and tenants.
GET
/api/v1/contracts
contracts:read
List contracts
Returns your contracts ordered by id, with cursor pagination.
Parameters:
limit (query), cursor (query)
POST
/api/v1/contracts
contracts:write
Create a contract
Creates a contract and emits a `contract.created` webhook event. `contractNumber` must be unique per account; new contracts are created as drafts.
Parameters:
Idempotency-Key (header)
GET
/api/v1/contracts/{id}
contracts:read
Retrieve a contract
Parameters:
id (path)
PATCH
/api/v1/contracts/{id}
contracts:write
Update a contract
Partial update: only the supplied fields change. Emits a `contract.updated` webhook event. `contractNumber` cannot be changed.
Parameters:
id (path), Idempotency-Key (header)
Tasks
To-dos, optionally linked to a property or contractor.
GET
/api/v1/tasks
tasks:read
List tasks
Returns your tasks ordered by id, with cursor pagination.
Parameters:
limit (query), cursor (query)
POST
/api/v1/tasks
tasks:write
Create a task
Creates a task and emits a `task.created` webhook event.
Parameters:
Idempotency-Key (header)
GET
/api/v1/tasks/{id}
tasks:read
Retrieve a task
Parameters:
id (path)
PATCH
/api/v1/tasks/{id}
tasks:write
Update a task
Partial update: only the supplied fields change. Emits a `task.updated` webhook event.
Parameters:
id (path), Idempotency-Key (header)
Maintenance requests
Tenant-reported or API-created maintenance tickets.
GET
/api/v1/maintenance-requests
maintenance:read
List maintenance requests
Returns your maintenance requests ordered by id, with cursor pagination. The resource path is `/api/v1/maintenance-requests`.
Parameters:
limit (query), cursor (query)
POST
/api/v1/maintenance-requests
maintenance:write
Create a maintenance
Creates a maintenance and emits a `maintenance.created` webhook event. `tenantId` is required and must reference one of your tenants.
Parameters:
Idempotency-Key (header)
GET
/api/v1/maintenance-requests/{id}
maintenance:read
Retrieve a maintenance
Parameters:
id (path)
PATCH
/api/v1/maintenance-requests/{id}
maintenance:write
Update a maintenance
Partial update: only the supplied fields change. Emits a `maintenance.updated` webhook event. `tenantId`, `propertyId` and `contractId` cannot be changed.
Parameters:
id (path), Idempotency-Key (header)
Credentials
API credential management. These endpoints use the web app session (cookie) authentication, not an API key.
GET
/api/integrations/api-credentials
sessie (webapp)
List API credentials
Returns all credentials of the signed-in account, most recent first. Secrets are never returned after creation.
POST
/api/integrations/api-credentials
sessie (webapp)
Create an API credential
The full secret (`kp_<prefix>_<secret>`) is returned exactly once, in this response.
POST
/api/integrations/api-credentials/{id}/rotate
sessie (webapp)
Rotate an API credential
Revokes the credential and issues a new one with the same label and scopes. The new secret is returned once.
Parameters:
id (path)
DELETE
/api/integrations/api-credentials/{id}
sessie (webapp)
Revoke an API credential
Parameters:
id (path)
Webhooks
Subscription management (session-authenticated) and the event envelope delivered to your endpoint. Deliveries are signed: `x-keypilot-signature: v1=<hex HMAC-SHA256 of "<timestamp>.<raw body>"` with the subscription secret; verify with `x-keypilot-timestamp`. Failed deliveries retry up to 5 times with exponential backoff (max 60 s).
GET
/api/integrations/webhooks
sessie (webapp)
List webhook subscriptions
POST
/api/integrations/webhooks
sessie (webapp)
Create a webhook subscription
The URL must be HTTPS and resolve to a public address (validated again at every delivery). The signing secret is returned exactly once.
PATCH
/api/integrations/webhooks/{id}
sessie (webapp)
Update a webhook subscription
Enable/disable a subscription, rename it or change the subscribed events.
Parameters:
id (path)
GET
/api/integrations/webhooks/{id}/deliveries
sessie (webapp)
List recent deliveries
Returns the 100 most recent delivery attempts for a subscription, newest first.
Parameters:
id (path)
Machinaal leesbaar
Voor tooling, AI-assistenten en API-catalogi publiceert Keypilot de specificatie op vaste URLs.