The webhook channel is the generic entry point for connecting any system capable of making an HTTP POST. It is the option to choose when no dedicated channel exists for your source.
When to use it
- Connect an in-house tool (ERP, business application, payment gateway).
- Receive events from a third-party platform that offers generic webhooks.
- Trigger a pipeline from an external cron job or a CI pipeline.
Configuration
- In the model editor, configure the Start node with an Inbound webhook receiver.
- betool generates a public URL (
https://platform.betool.ai/entries/webhook/<token>). - (Recommended) Set an HMAC secret in the receiver configuration.
When a secret is configured, your system must sign the raw body of each request — HMAC-SHA256(secret, body), in hexadecimal — and pass the signature in the X-Webhook-Signature header, as sha256=<hex> or <hex> alone. The header name and the algorithm (sha256, sha384, sha512) are configurable, for example to follow GitHub's X-Hub-Signature-256 convention. Any request without a valid signature is then rejected (401).
Only this format is verified: a hexadecimal HMAC of the raw body. A timestamped signature (t=…,v1=…) or a base64-encoded one will not be recognized.
Payload format
You send any JSON you like. betool does not constrain the structure. The payload is exposed to the pipeline under webhook.payload (with its sub-keys); the headers, the method and the query string are also available under webhook.headers, webhook.method and webhook.query.
The body is read according to its Content-Type: JSON parsed, form (application/x-www-form-urlencoded) as a dictionary, XML and text/* as raw text, multipart/form-data as fields + attached files (webhook.payload._files), any other type (PDF, image, archive…) stored as a file. A gzip-compressed body is decompressed. Maximum size: 50 MB (413 beyond).
Example:
curl -X POST https://platform.betool.ai/entries/webhook/abc123 \
-H "Content-Type: application/json" \
-H "X-Webhook-Signature: sha256=$SIGNATURE" \
-d '{
"type": "order.created",
"order_id": "ord_42",
"amount_cents": 9900,
"customer_email": "client@exemple.com"
}'
The pipeline can then wire an agent that reads webhook.payload.customer_email and webhook.payload.amount_cents directly.
Response
Two response modes (response_mode): sync (default) blocks until the pipeline result and returns it in the response; ack immediately returns 202 Accepted after placing the event in a durable queue (the pipeline then runs, with retries) — choose it for providers with short timeouts.
GET calls (option)
By default only POST is accepted: a GET gets 405. For a partner that requires a GET ?action=… lookup, tick Also accept GET (allow_get). The query string then becomes webhook.payload, in the same shape as a form POST: the pipeline does not need to know which method was used. A GET carries no body (refused with 400) and is incompatible with HMAC signing (refused with 405 while a secret is set). A credential passed in the query appears in access logs: prefer POST when the partner allows it.
Security
- Sign your requests (HMAC) as soon as the endpoint handles anything beyond tests.
- The secret can be changed at any time in the receiver configuration (rotation). Once saved, it is never displayed again: the field shows "•••••• saved — type to replace", and Remove clears it (the signature is then no longer verified).
- Payloads are stored in plain text in the execution history — do not send data that should be encrypted in transit only.