De Keeo API gebruiken
Je kan gratis gebruik maken van de Keeo API als je zelf wat kennis hebt van API's. We kunnen hiervoor géén ondersteuning via email voor geven, dus gebruik het op je eigen risico.
Toegang krijgen
Je kan een API-key opvragen via de Keeo instellingen van jouw eenheid (Instellingen > Experimenten > API-keys). Met deze API-key kan je de API raadplegen.
We raden aan om altijd een nieuwe key aan te maken per toepassing die je wilt gebruiken. Daardoor kan je netjes de toegang van de API afschermen door de toegangsrechten van de gekoppelde keys aan te passen, bv. tot enkel het gedeelte van betalingen.
Basisprincipes
Structuur voor algemene endpoints: https://api.keeo.fos.be/v398/organizations/search?query=test
Structuur voor endpoints specifiek voor één vereniging:https://634d549b-862e-4a5e-852d-3d4a9814e22d.api.keeo.fos.be/v398/webshop/d6b9ed68-3a1f-4dd5-8259-62d0d808f597
Hier zie je dat elke vereniging een andere API aanspreekt op het subdomein van api.keeo.fos.be, met als subdomein het ID van de vereniging.
Versiebeheer
De versie van de API die je aanspreekt zit in de endpoints. Bij elke wijziging aan de API gaat dit nummer omhoog. Oude versies blijven nog even ondersteund, maar we bieden momenteel geen garantie dat we oude versies voor een bepaalde tijd blijven ondersteunen. Soms is het noodzakelijk in verband met interne wijzigingen dat we een update moeten doorvoeren die niet meer compatibel is, waardoor alle oude versies niet langer ondersteund worden.
Gebruik de webinspector
Je kan alle API endpoints gebruiken, hoewel we ze nog niet allemaal gaan documenteren. Je kan altijd de webinspector gebruiken in je browser en via keeo.fos.be het netwerkverkeer bekijken om te weten hoe je bepaalde zaken kan doen. De API die de app aanspreekt is namelijk dezelfde API die je ook kan gebruiken.

Authenticatie
Hiervoor kan je de Authorization header toevoegen met als waarde Authorization: Bearer <jouw API-key>. Authenticatie is bij de meeste endpoints noodzakelijk.
Rate limits: Wees zuinig met je requests
Spreek de API niet aan als dat niet nodig is. Beperk het aantal requests tot een absoluut minimum. Er staan limieten op het aantal aanvragen die je kan versturen:
- 5 req/s, maximaal aangehouden gedurende 5 seconden
- 1 req/s, maximaal aangehouden gedurende 2 minuten
- 1000 req/uur
- 2000 req/dag
Zorg er dus best voor dat je niet alle aanvragen tegelijk verstuurd, meestal is dat ook niet nodig. Heeft jouw toepassing toch hogere limieten nodig? Leg dan goed uit waarom het niet met de huidige limieten lukt, en stuur ons een e-mail.
Voorbeeld 1: openstaande overschrijvingen opvragen
Stap 1: totaal aantal opvragen
De endpoints hebben paginatie, dus kan het handig zijn om eerst te weten over hoeveel overschrijvingen het in totaal gaat.
curl \
--get 'https://<ORG-ID>.api.keeo.fos.be/v398/payments/count' \
--data-urlencode 'filter={
"$and":[
{"status":{"$in":["Pending","Created"]}},
{"method":{"$in":["Transfer"]}}
]
}' \
--data-urlencode 'search=' \
-H 'authorization: Bearer <YOUR-TOKEN>'Antwoord:
{
"count": 18
}Nu we weten over hoeveel transacties het gaat kan je gemakkelijk de transacties ophalen, eventueel moet je meerdere requests doen.
Stap 2: Eerste transacties ophalen
curl \
--get 'https://<ORG-ID>.api.keeo.fos.be/v398/payments' \
--data-urlencode 'filter={
"$and":[
{"status":{"$in":["Pending","Created"]}},
{"method":{"$in":["Transfer"]}}
]
}' \
--data-urlencode 'sort=createdAt DESC,id DESC' \
--data-urlencode 'limit=17' \
--data-urlencode 'search=' \
-H 'authorization: Bearer <YOUR-TOKEN>'Antwoord:
{
"results": [
...
],
"next": {
"filter": "{\"$and\":[{\"status\":{\"$in\":[\"Pending\",\"Created\"]}},{\"method\":{\"$in\":[\"Transfer\"]}}]}",
"pageFilter": "{\"$or\":[{\"createdAt\":{\"$lt\":\"2025-12-01 07:52:42\"}},{\"$and\":[{\"createdAt\":\"2025-12-01 07:52:42\"},{\"id\":{\"$lt\":\"c6bc0bc2-cc09-4568-8647-784250fac8ec\"}}]}]}",
"sort": "createdAt DESC,id DESC",
"limit": 17,
"search": ""
}
}We laten de results even weg, om het leesbaar te houden. Hieronder kan je een voorbeeld van een result zien.
Stap 3, 4...: volgende transacties ophalen
Merk op dat je aan de hand van next, uit het antwoord van de vorige request, de volgende requests moet opbouwen.
curl \
--get 'https://<ORG-ID>.api.keeo.fos.be/v398/payments' \
--data-urlencode 'filter={
"$and":[
{"status":{"$in":["Pending","Created"]}},
{"method":{"$in":["Transfer"]}}
]
}' \
--data-urlencode 'pageFilter={
"$or":[
{"createdAt":{"$lt":"2025-12-01 07:52:42"}},
{"$and":[
{"createdAt":"2025-12-01 07:52:42"},
{"id":{"$lt":"201a9efc-bb84-4302-aa03-a182779b994b"}}
]}
]
}' \
--data-urlencode 'sort=createdAt DESC,id DESC' \
--data-urlencode 'limit=10' \
--data-urlencode 'search=' \
-H 'authorization: Bearer <YOUR-TOKEN>'Antwoord:
Aangezien alle resultaten nu binnen de limit vallen, is er géén next.
{
"results": [
{
"id": "35027f6c-0156-475c-9117-23374650d9c1",
"balanceItemPayments": [
{
"id": "6463d262-4bac-4f41-b55c-c2b0d7ad80b6",
"balanceItem": {
"id": "d23dc67d-0145-4fb6-adff-61344be5aa5d",
"description": "Bestelling #1 - Wafelslag",
"amount": 1,
"createdAt": 1764261041000,
"dueAt": null,
"memberId": null,
"order": null,
"orderId": "2070076c-2f12-4740-a247-8c50a4a6ccb1",
"organizationId": "634d549b-862e-4a5e-852d-3d4a9814e22d",
"paidAt": null,
"payingOrganizationId": null,
"priceInvoiced": 0,
"pricePaid": 0,
"pricePending": 1000000,
"registration": null,
"registrationId": null,
"relations": {
"Webshop": {
"id": "313f686b-fd14-4cf4-99d4-81f0a3071f5f",
"name": "Wafelslag"
}
},
"status": "Due",
"type": "Order",
"unitPrice": 1000000,
"userId": null,
"VATExcempt": null,
"VATIncluded": true,
"VATPercentage": null
},
"price": 1000000
}
],
"createdAt": 1764261041000,
"customer": {
"company": null,
"email": "jolien@telenet.be",
"firstName": "Jolien",
"lastName": "De wanbetaler",
"phone": null
},
"freeContribution": null,
"iban": null,
"ibanName": null,
"invoiceId": null,
"method": "Transfer",
"organizationId": "634d549b-862e-4a5e-852d-3d4a9814e22d",
"paidAt": null,
"payingOrganization": null,
"payingOrganizationId": null,
"payingUserId": null,
"price": 1000000,
"provider": null,
"serviceFeeManual": 0,
"serviceFeeManualCharged": 0,
"serviceFeePayout": 0,
"settlement": null,
"status": "Pending",
"stripeAccountId": null,
"transferDescription": "Wafelslag #1",
"transferFee": 0,
"transferSettings": {
"creditor": "De Ruimtevaarders",
"iban": "BE68 5390 0754 7034",
"infoDescription": "",
"prefix": "Wafelslag {{nr}}",
"type": "Fixed"
},
"type": "Payment",
"updatedAt": 1765236927000
}
]
}Voorbeeld 2: overschrijven als (niet)betaald markeren
curl -X PATCH \
'https://<ORG-ID>.api.keeo.fos.be/v398/organization/payments' \
-H 'authorization: Bearer <YOUR-TOKEN>' \
-H 'content-type: application/json' \
--data-raw '{
"_isPatch":true,
"changes":[
{"patch":{
"_isPatch":true,
"id":"35027f6c-0156-475c-9117-23374650d9c1",
"status":"Succeeded"
}}
]
}'Een PATCH request gebruikt een body zodat de betaling met id 35027f6c-0156-475c-9117-23374650d9c1 als betaald (ofwel 'Succeeded') wordt gemarkeerd.
Als je meerdere betalingen tegelijk wilt wijzigen:
curl -X PATCH \
'https://<ORG-ID>.api.keeo.fos.be/v398/organization/payments' \
-H 'authorization: Bearer <YOUR-TOKEN>' \
-H 'content-type: application/json' \
--data-raw '{
"_isPatch":true,
"changes":[
{"patch":{
"_isPatch":true,
"id":"abad022a-8281-412f-9668-4dd0ef0d41ef",
"status":"Failed"
}},
{"patch":{
"_isPatch":true,
"id":"9935176a-34c4-4bbb-8d33-01caf93ad8b5",
"status":"Failed"
}}
]
}'Je kan deze body gebruiken om meerdere betalingen als 'Geannuleerd' te markeren. Maar je kan verschillende statussen met elkaar combineren in dezelfde request.
Als antwoord op deze request krijg je een lijst van de betalingen die je hebt gewijzigd en hun nieuwe eigenschappen.