Skip to main content

Overview

Webhooks let your application react to events in real time without polling. When something happens in Arcus — an order is confirmed, a payment is received, a shipment is created, an inventory adjustment is posted — Arcus sends an HTTP POST to your endpoint with a signed JSON payload. All webhook requests are signed with HMAC-SHA256. You verify the signature using the signing secret returned at endpoint creation.

Event structure

Every webhook payload uses this envelope:

Registering an endpoint

The key needs the webhooks:manage scope. These are the fields of the request body: The response includes a secret in whsec_<hex> format. Store it securely. It is shown once and cannot be retrieved again through the API. Use it to verify every incoming request. If it is lost, rotate it.
status is active on creation. Later reads show secret_last4 only, never the secret itself.

If the create call is refused

Queue a test event while creating

Send "send_test_event_on_create": true and the response also carries a test_event object with the event_id and the queued_delivery_id of a webhook.test delivery. The delivery starts as pending and is sent by Arcus’s delivery worker, so it arrives after the response, not inside it. If the test event could not be queued, test_event holds error: "queue_failed" instead; the endpoint is still created, and you can send a test event later with the call in Sending a test event.
Field name: use enabled_events (Stripe convention) in all requests and responses. The legacy alias events is accepted for backward compatibility but is deprecated and will be removed in API v2.

Wildcard subscriptions

Subscribe to an entire event family with order.*, or all events with *:
Valid wildcard patterns are <family>.* (14 families) or * (all 118 events).

Duplicate endpoint guard

Registering the same URL and mode combination twice returns HTTP 409 with error: "duplicate_url" and the existing_id of the endpoint that already holds it. The same URL can be registered once in live mode and once in test mode. A disabled endpoint does not block a new one.

Verifying signatures

Every webhook request includes an Arcus-Signature header. Always verify it before processing the payload. The signature is an HMAC-SHA256 of <timestamp>.<raw_body> using your signing secret, with a 5-minute replay window. Header format: Arcus-Signature: t=<unix_epoch>,v1=<hex_hmac_sha256>

Webhook request headers

Every delivery includes these headers:

Responding to webhooks

Return a 2xx response within 15 seconds; a slower response counts as a failure. Aim for much less: respond immediately and process the event asynchronously. Arcus retries on any non-2xx response or connection failure, with exponential backoff: After 6 failed attempts, no more retries are made for that delivery. An endpoint that accumulates 10 consecutive permanent failures is automatically disabled.

Deduplication

Events may be delivered more than once (network timeouts, retries). Always deduplicate on event.id before processing:

Rotating signing secrets

Rotate when a secret is lost, was exposed, or is due for routine replacement. The key needs the webhooks:manage scope, and the call takes no body.
The new secret is in secret, and it is returned this one time only. Store it, then update your receiver’s environment variable. There is no grace period. The old secret stops signing the moment the call returns: every delivery sent after that, including retries of deliveries queued earlier, is signed with the new secret. A delivery your receiver rejects during the switch is not lost, because Arcus retries it on the normal schedule above. A delivery that was already on the wire when you rotated was signed with the old secret, so if you want zero rejected attempts, have your receiver accept both the old and the new secret until the new one is deployed, then drop the old one. An unknown endpoint ID returns 404 not_found.

Sending a test event

Send a webhook.test event to verify your endpoint is reachable and that your receiver verifies signatures correctly. The key needs the webhooks:manage scope, and the call takes no body.
What the call does:
  • It records a webhook.test event and queues a delivery of it to this one endpoint, whatever the endpoint’s enabled_events list says. The delivery starts as pending and is sent by Arcus’s delivery worker, so the receiver sees it shortly after the response, with the usual signature and headers.
  • It sets the endpoint’s last_delivery_at. It does not change success_count or failure_count, so test traffic never skews the endpoint’s delivery statistics.
  • A delivery is sent only when the endpoint’s mode matches the event’s mode, and a test event created in the live environment is a live-mode event, so a test-mode endpoint there never receives it.
  • An unknown endpoint ID returns 404 not_found.

Event catalog

Arcus emits 118 event types across 14 families. Subscribe to individual events, a whole family (order.*), or everything (*).

account (12 events)

product (21 events)

order (16 events)

invoice (9 events)

payment (8 events)

inventory (7 events)

purchase_order (8 events)

vendor_bill (8 events)

journal_entry and period (5 events)

fulfillment (7 events)

return (5 events)

connector (7 events)

migration (10 events)

The batch events and migration.snapshot_taken, migration.cutover_initiated, migration.cutover_verified, migration.cutover_completed and migration.cutover_rolled_back are delivered. migration.freeze_engaged and migration.unfreeze_engaged are registered but not sent yet.

webhook (1 event)