Skip to content

Integraties

WordPress (acf/save_post)
↓ webhook POST
Make.com Scenario
↓ API calls
Moneybird (boekhouding)
↓ moneybird_id terug
Make.com
↓ REST upsert
WordPress (contact update)
Bestandfunctions/api-contact.php
URLACS_MAKE_WEBHOOK_URL (hardcoded, regel 10)
Hookacf/save_post (priority 20)
TriggerElke save van een contact CPT
  • post_date === post_modified → event = created
  • Anders → event = updated
{
"wp_id": 567,
"post_type": "contact",
"event": "created",
"status": "publish",
"timestamp": "2026-04-05T14:30:00+02:00",
"title": "Jan de Vries",
"edit_url": "https://werkbon.nl/wp-admin/post.php?post=567&action=edit",
"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"
}
ConditieReden
contact-type === 'maasdelta'Woningcorporatie, nooit syncen
_acs_origin === 'website' zonder job/fileVoorkom sync incompleet contact
Debounce actief (3 sec transient)Voorkom dubbele webhooks
wp_get_environment_type() !== 'production'Alleen productie

Gebruikt post meta i.p.v. transients (betrouwbaarder bij concurrent saves):

function acs_make_should_debounce(int $post_id, int $seconds = 3): bool {
$key = '_acs_make_last_fired_ts';
$last = (int) get_post_meta($post_id, $key, true);
$now = time();
if ($last > 0 && ($now - $last) < $seconds) {
return true; // Te snel na vorige webhook
}
update_post_meta($post_id, $key, (string)$now);
return false;
}
  • Contacten via formulier krijgen _acs_origin = 'website'
  • Niet gesynceerd tot job/file gekoppeld: beam_contact_has_related_job_or_file()
Bestandfunctions/api-file.php
URLACS_MAKE_FILE_WEBHOOK_URL (hardcoded, regel 13)
Hookacf/save_post (priority 20)
Skipfile-type === 'maasdelta', niet productie

Alle file ACF velden plus invoice details:

{
"wp_id": 1234,
"event": "created",
"title": "20260405: Hoofdstraat 42a, Rotterdam",
"details_attributes": [
{"description": "Riool ontstopt - Keuken, Badkamer", "amount": "1"},
{"description": "PVC Buis 110mm", "amount": "2"}
]
}

acs_file_build_details_attributes():

  1. file-description-json → factuurregels met beschrijving
  2. file-material-json → factuurregels met qty
  3. Output: Moneybird-compatibel
  1. Contact gewijzigd → webhook → Make.com
  2. Make: create/update Moneybird contact
  3. Moneybird retourneert moneybird_id
  4. Make: POST /wp-json/acs/v1/contacts/upsert
  5. moneybird_id opgeslagen in WP
Werkbon (WP)MoneybirdRichting
contact-companycompany_nameWP → MB
contact-firstnamefirstnameWP → MB
contact-lastnamelastnameWP → MB
contact-emailemailWP → MB
contact-phonephoneWP → MB
contact-streetname + number + additionaddress1WP → MB
contact-zipcodezipcodeWP → MB
contact-citycityWP → MB
moneybird_ididMB → WP
  1. Werkbon aangemaakt (Form 40)
  2. File webhook met details_attributes
  3. Make: create Moneybird sales invoice
  4. Factuurregels uit details_attributes array

Type maasdelta wordt NOOIT gesynceerd — apart gefactureerd.

define('ACS_MAKE_WEBHOOK_URL', 'https://hook.eu2.make.com/...');
define('ACS_MAKE_FILE_WEBHOOK_URL', 'https://hook.eu2.make.com/...');

Hardcoded en in Git. Aanbeveling: verplaats naar wp-config.php.

function acs_make_send_webhook(int $post_id, string $event, string $status): void {
if (wp_get_environment_type() !== 'production') return;
$payload = [
'wp_id' => (int) $post_id,
'post_type' => 'contact',
'event' => $event, // 'created' | 'updated'
'status' => $status, // 'publish' | 'private'
'title' => get_the_title($post_id),
'timestamp' => time(),
'edit_url' => get_edit_post_link($post_id, 'raw'),
];
wp_remote_post(ACS_MAKE_WEBHOOK_URL, [
'timeout' => 10,
'headers' => ['Content-Type' => 'application/json'],
'body' => wp_json_encode($payload),
]);
}
  • wp_remote_post() retourneert WP_Error bij netwerkfouten
  • Huidige implementatie: fout wordt genegeerd (fire-and-forget)
  • Geen retry mechanisme — als Make.com down is, gaat de webhook verloren
  • Make.com heeft eigen retry logica voor gemiste webhooks
function acs_make_is_sync_request(): bool {
return isset($_SERVER['HTTP_X_ACS_SYNC']) && $_SERVER['HTTP_X_ACS_SYNC'] === '1';
}

Wanneer Make.com een contact terugschrijft via de upsert endpoint, wordt de X-ACS-SYNC: 1 header meegestuurd. Dit voorkomt een oneindige webhook loop.

In de nieuwe stack worden webhooks vervangen door Cloudflare Worker cron jobs of Supabase database triggers. Zie Migratie naar Beam Stack.

BestandLocatieFunctie
api-contact.phpfunctions/Contact webhook + REST endpoints
api-file.phpfunctions/File webhook + REST endpoints
api-job.phpfunctions/Job creatie + contact lookup