benecaster_register_integration_action()
benecaster_register_integration_action( string $addon_slug, string $action, array $args ): bool
Declares one action an outside system — Zapier, Make, a CRM — may call through POST /wp-json/benecaster/v1/actions to make your add-on do something. Benecaster owns the endpoint, the sign-in, the checks, the idempotency and the call log; your add-on owns only the handler. Call it from the bootstrap you pass to benecaster_register_addon().
The caller signs in with a WordPress Application Password for a user with the Benecaster Integration role, and names the action, the show, an optional idempotency key and the data. Before your handler runs, Benecaster checks the caller may run integration actions, that the action is registered, that your add-on is active on the show, and that every declared field is present and of the right type. A repeat of the same request with the same idempotency key within 24 hours returns the first answer and never calls your handler twice.
$data holds only your declared fields, already coerced. Zapier and Make send most values as strings, so the check is lenient: an integer field accepts "12" and your handler receives 12; a boolean accepts true/false/1/0 in any form. A key you did not declare is dropped, not refused. Field types: string, integer, number, boolean, array, object.
Parameters
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
addon_slug |
string |
— | Yes | The slug your add-on registered with in benecaster_register_addon(); either form works. |
action |
string |
— | Yes | The action name, {addon-slug}.{noun}.{verb} — the same rule as webhook events: your catalog slug, then lowercase letters, digits and _ in the noun and verb, at most 191 characters. Example: podcast-workflow.guest.crm_linked. |
args |
array |
— | Yes | handler (required callable, function ( array $data, int $show_id, int $user_id ): array|\WP_Error), fields (field name → [ 'type' => …, 'required' => bool, 'description' => string ]; default []) and label (string, translated by your add-on; default ''). |
Return Value
Type:
bool
true when the action is registered — registering the same name again from the same add-on replaces it — and false when it is refused. Every refusal is also reported with _doing_it_wrong().
Example
add_action( 'benecaster_boot', function ( \Benecaster\Container $container ) {
benecaster_register_addon( 'my-addon', static function (): void {
benecaster_register_integration_action( 'my-addon', 'my-addon.booking.paid', [
'label' => __( 'A booking was paid elsewhere', 'my-addon' ),
'fields' => [
'booking_id' => [ 'type' => 'integer', 'required' => true ],
'invoice_id' => [ 'type' => 'string', 'required' => true ],
],
'handler' => static function ( array $data, int $show_id, int $user_id ): array|\WP_Error {
update_post_meta( $data['booking_id'], '_invoice_id', $data['invoice_id'] );
return [ 'booking_id' => $data['booking_id'], 'status' => 'paid' ];
},
] );
} );
} );
Hooks Fired
Notes
Refused when your add-on has not called benecaster_register_addon(); the name is not under your add-on's own prefix; the name is malformed; your slug is one of Benecaster's own webhook families; handler is missing or not callable; or a field has an unknown type or a malformed name.
Return ids, not personal data. The first response is stored for 24 hours to answer a repeated idempotency key. Return a WP_Error with [ 'status' => 4xx ] to refuse (default 422); that refusal is remembered and replayed. Throw, or return a 5xx, only for a failure worth retrying — the key is then released so the retry runs.
Check that the record belongs to $show_id. Benecaster checked your add-on is active on the show the caller named, not that the caller's record ID is one of that show's records. Worked example: the recipe Let Zapier, Make or a CRM call your add-on.
Need this built rather than just documented? See our services →