Signed webhooks.
Let another system start a job without an Access Key. Stripe, Shopify, or your own service signs each request with a secret, and Olbrain checks the signature instead of a key.
When to use this
- A third party sends the events (a Stripe payment, a Shopify order) and can't hold your Access Key.
- You want each event to start a job at most once, even when the sender retries.
Signed webhooks start jobs only. The job must have a signed sender connected: Stripe, Shopify, or a shared secret. Set it up when you build the job with Alchemist; its hand-over shows the exact URL and steps.
Stripe and Shopify
Add the URL above as a webhook endpoint in Stripe or Shopify, with the signing secret connected
to the job. Olbrain checks Stripe-Signature (Stripe's t= and
v1= scheme, 5-minute tolerance) or X-Shopify-Hmac-SHA256. Use
Send test webhook in Stripe, or Send test notification in Shopify,
to try it — it starts a real, billed run.
Your own service
Sign {timestamp}.{raw body} with HMAC-SHA256 and the shared secret, and send the hex digest:
| Header | Value |
|---|---|
X-Olbrain-Timestamp | Unix time in seconds. Must be within 5 minutes of Olbrain's clock. |
X-Olbrain-Signature | Hex HMAC-SHA256 of the timestamp, a dot, and the exact body bytes. |
Content-Type | application/json |
BODY='{"order_id":"4421"}'
TS=$(date +%s)
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$OLBRAIN_WEBHOOK_SECRET" | sed 's/^.*= //')
curl -X POST https://webhook.olbrain.com/api/agents/webhook/agt_01HAKZ.../signed \
-H "Content-Type: application/json" \
-H "X-Olbrain-Timestamp: $TS" \
-H "X-Olbrain-Signature: $SIG" \
-d "$BODY"
Sign the bytes you send, not a re-serialised copy. The body must be a JSON object up to 1 MiB, shaped like a job trigger. Keep the secret on your server.
Each delivery runs once
Olbrain remembers each signed delivery for 24 hours. Sending the same signed request again
returns {"status": "duplicate"} and starts nothing. A delivery that fails is
forgotten, so the sender's retry runs it. Expect a rare duplicate if a run started but its
response never reached the sender.
Errors
| Status | When |
|---|---|
401 invalid_signature | Missing or wrong signature, a timestamp outside 5 minutes, or the agent has no signed sender. All look the same on purpose. |
400 invalid_body | The body isn't a JSON object. |
409 delivery_in_progress | The same delivery is still running. Retry shortly. |
413 body_too_large | The body is over 1 MiB. |
| 503 | secret_unavailable, delivery_store_unavailable, or signed_senders_disabled. Retry with backoff. |
After admission, the same checks as any trigger apply — billing, the job's daily run limit, and publishing. See Errors.