REST API
Overzicht
Section titled “Overzicht”| Route | Method | Auth | Handler | Bestand |
|---|---|---|---|---|
| /wp-json/acs/v1/jobs/create | POST | Geen | acs_job_api_create | api-job.php |
| /wp-json/acs/v1/contacts | GET | Geen | acs_contacts_list | api-contact.php |
| /wp-json/acs/v1/contacts/{id} | GET | Geen | acs_contacts_get | api-contact.php |
| /wp-json/acs/v1/contacts/upsert | POST | Geen | acs_contacts_upsert | api-contact.php |
| /wp-json/acs/v1/files | GET | Geen | acs_files_list | api-file.php |
| /wp-json/acs/v1/files/{id} | GET | Geen | acs_files_get | api-file.php |
Alle endpoints hebben permission_callback => return true. Er is GEEN authenticatie. Zie Security Audit.
Route Registratie
Section titled “Route Registratie”register_rest_route('acs/v1', '/jobs/create', [ 'methods' => 'POST', 'callback' => 'acs_job_api_create', 'permission_callback' => 'acs_job_api_permission', // return true]);
// api-contact.phpregister_rest_route('acs/v1', '/contacts', [ 'methods' => 'GET', 'callback' => 'acs_contacts_list', 'permission_callback' => 'acs_permission_contacts', // return true]);register_rest_route('acs/v1', '/contacts/(?P<id>\d+)', [ 'methods' => 'GET', 'callback' => 'acs_contacts_single', 'permission_callback' => 'acs_permission_contacts',]);register_rest_route('acs/v1', '/contacts/upsert', [ 'methods' => 'POST', 'callback' => 'acs_contacts_upsert', 'permission_callback' => 'acs_permission_contacts',]);ACF Field Map (api-contact.php)
Section titled “ACF Field Map (api-contact.php)”Alle contact endpoints gebruiken deze mapping:
function acs_acf_field_map(): array { return [ 'type' => 'contact-type', 'firstname' => 'contact-firstname', 'lastname' => 'contact-lastname', 'company' => 'contact-company', 'email' => 'contact-email', 'phone' => 'contact-phone', 'zipcode' => 'contact-zipcode', 'streetname' => 'contact-streetname', 'number' => 'contact-number', 'addition' => 'contact-addition', 'city' => 'contact-city', 'note' => 'contact-note', 'moneybird_id' => 'moneybird_id', ];}Normalisatie Functies (api-job.php)
Section titled “Normalisatie Functies (api-job.php)”function acs_job_api_normalize_zipcode(string $zipcode): string { $z = strtoupper(str_replace(' ', '', trim($zipcode))); if (preg_match('/^(\d{4})([A-Z]{2})$/', $z, $m)) { return $m[1] . ' ' . $m[2]; // "3029 AK" (met spatie) } return strtoupper($zipcode);}
function acs_job_api_zip_compact(string $zipcode): string { return strtoupper(str_replace(' ', '', trim($zipcode))); // "3029AK" (zonder)}POST /wp-json/acs/v1/jobs/create
Section titled “POST /wp-json/acs/v1/jobs/create”Request
Section titled “Request”| Parameter | Type | Verplicht | Beschrijving |
|---|---|---|---|
| moneybird_id | string | Nee | Moneybird contact ID |
| zipcode | string | Nee | Postcode |
| number | string | Nee | Huisnummer |
| addition | string | Nee | Toevoeging |
| string | Nee | ||
| company | string | Nee | Bedrijfsnaam |
| firstname | string | Nee | Voornaam |
| lastname | string | Nee | Achternaam |
| phone | string | Nee | Telefoon |
| type | string | Nee | maasdelta, particulier, zakelijk |
| status | string | Nee | 0, 1, 2 (default: 0) |
| date | string | Nee | Planningsdatum (Ymd) |
| streetname | string | Nee | Straatnaam |
| city | string | Nee | Stad |
| description | string | Nee | Beschrijving |
| note | string | Nee | Notitie |
| employer | string/array | Nee | Monteur user ID(s) |
Contact Lookup
Section titled “Contact Lookup”Prioriteit 4: moneybird_id match → found_by: "moneybird_id"Prioriteit 3: postcode + huisnr + toevoeging + email → found_by: "address_email"Prioriteit 2: postcode + huisnr + toevoeging → found_by: "address"Prioriteit 1: email → found_by: "email"Geen match ��� acs_job_api_create_contact() → found_by: "created"Adres Normalisatie
Section titled “Adres Normalisatie”acs_job_api_lookup_address() zoekt in wp_werkbon_addresses:
- Gevonden → overschrijft streetname + city met database waarden
is_maasdelta→ forceert contact-type naar ‘maasdelta’
Response
Section titled “Response”{ "success": true, "job_id": 1234, "contact_id": 567, "contact_created": false, "found_by": "address_email", "address_normalized": true, "is_maasdelta": false}GET /wp-json/acs/v1/contacts
Section titled “GET /wp-json/acs/v1/contacts”Parameters
Section titled “Parameters”| Parameter | Type | Default | Beschrijving |
|---|---|---|---|
| page | int | 1 | Pagina |
| per_page | int | 50 | Items per pagina |
| search | string | "" | Zoekterm (post title) |
Response
Section titled “Response”{ "items": [ { "id": 567, "title": "Jan de Vries", "company": "Loodgieter BV", "firstname": "Jan", "lastname": "de Vries", "email": "jan@example.nl", "phone": "+31612345678", "streetname": "Hoofdstraat", "number": "42", "addition": "a", "zipcode": "1234AB", "city": "Rotterdam", "type": "zakelijk", "moneybird_id": "123456789" } ], "totalPages": 5, "total": 243}GET /wp-json/acs/v1/contacts/{id}
Section titled “GET /wp-json/acs/v1/contacts/{id}”Enkel contact met alle velden. Zelfde structuur als items hierboven.
POST /wp-json/acs/v1/contacts/upsert
Section titled “POST /wp-json/acs/v1/contacts/upsert”Request
Section titled “Request”| Parameter | Type | Verplicht |
|---|---|---|
| moneybird_id | string | Ja (match key) |
| company, firstname, lastname, email, phone | string | Nee |
| zipcode, streetname, number, addition, city | string | Nee |
Logica
Section titled “Logica”- Zoek contact met
moneybird_id - Gevonden �� update ingevulde velden
- Niet gevonden → nieuw contact
- Trigger
acf/save_post→ webhook
GET /wp-json/acs/v1/files
Section titled “GET /wp-json/acs/v1/files”Zelfde paginatie als contacts. Response bevat alle file ACF velden.
GET /wp-json/acs/v1/files/{id}
Section titled “GET /wp-json/acs/v1/files/{id}”Enkel werkbon inclusief invoice details.
Invoice Details Building
Section titled “Invoice Details Building”acs_file_build_details_attributes($file_id):
{ "details_attributes": [ {"description": "Riool ontstopt - Keuken, Badkamer (05-04-2026)", "amount": "1"}, {"description": "PVC Buis 110mm", "amount": "2"} ]}Moneybird-compatibel. Zie Integraties.
curl Voorbeelden
Section titled “curl Voorbeelden”Contacten ophalen
Section titled “Contacten ophalen”curl -s 'https://werkbon.nl/wp-json/acs/v1/contacts?per_page=10&search=jan' | jqMelding aanmaken
Section titled “Melding aanmaken”curl -X POST 'https://werkbon.nl/wp-json/acs/v1/jobs/create' \ -H 'Content-Type: application/json' \ -d '{ "moneybird_id": "123456789", "zipcode": "3029AK", "number": "42", "firstname": "Jan", "lastname": "de Vries", "email": "jan@example.nl", "description": "Lekkage in badkamer", "status": "0" }'Contact upsert (vanuit Make.com)
Section titled “Contact upsert (vanuit Make.com)”curl -X POST 'https://werkbon.nl/wp-json/acs/v1/contacts/upsert' \ -H 'Content-Type: application/json' \ -d '{ "moneybird_id": "123456789", "company": "Loodgieter BV", "email": "info@loodgieter.nl" }'Error Responses
Section titled “Error Responses”| Status | Wanneer | Response |
|---|---|---|
| 200 | Succes | {"success": true, ...} |
| 400 | Ongeldige parameters | {"code": "rest_invalid_param", ...} |
| 404 | Contact/file niet gevonden | {"code": "rest_no_route", ...} |
| 500 | Interne fout | {"success": false, "error": "..."} |
Let op: door de open permission_callback is er geen 401/403 response mogelijk.
Migratie
Section titled “Migratie”In de nieuwe Beam stack worden deze endpoints vervangen door een Hono API op Cloudflare Workers met Supabase als database. Alle endpoints krijgen authenticatie via Bearer token. Zie Migratie naar Beam Stack.
Bestandsoverzicht
Section titled “Bestandsoverzicht”| Bestand | Locatie | Functie |
|---|---|---|
| api-job.php | functions/ | POST /jobs/create + contact lookup |
| api-contact.php | functions/ | GET/POST contacts + webhook |
| api-file.php | functions/ | GET files + webhook |
| db-addresses.php | functions/ | Address lookup voor normalisatie |