Skip to main content
A webhook endpoint is an HTTPS URL of yours that Dcycle calls when an event happens in your organization, for example when a bulk ingest job finishes. Your integration reacts at once instead of polling.
Beta. The webhooks API is in beta: the contract may still change before general availability. Ignore unknown fields in the payload so new ones do not break you.

How it works

1

Register an endpoint

POST /v2/webhook-endpoints with your URL and the events you want. The response carries the endpoint’s signing secret (whsec_…). Store it: it is shown only once.
2

Dcycle sends the events

Each event is a POST with a JSON body, signed with your secret in the Dcycle-Signature header.
3

Answer 2xx quickly

Verify the signature, store the event and answer any 2xx within 10 seconds. Do the heavy work afterwards. Any other answer, a timeout or a network error is retried.
Only organization admins can manage endpoints, with an API key or from the app. An endpoint receives the events of the organization that registered it (the x-organization-id it was created with). Webhooks are for integrations: ingest_job.finished is sent for the jobs your organization submits with an API key (their source is api_bulk). A job a person starts while signed in to Dcycle, such as a waste created from the app’s form, notifies that person in the app instead and sends no webhook (its source is app).

Events

Every event has the same envelope:
Two ids, two meanings: the envelope id is the event (the same on every retry: deduplicate on it), and data.id is the job the event is about (the id you got in the 202 of POST /v2/wastes). data.entity_type and data.operation say what the job did, e.g. wastes + create. api_version dates the envelope and payload format. A breaking change to a payload ships under a new version; new fields can appear without one, so ignore the ones you do not use. The payload is a summary. Fetch the details you need with the API, e.g. the failed records with GET /v2/ingest-jobs/{id}/items?status=failed.

Request headers

Verifying the signature

v1 is the HMAC-SHA256, keyed with your secret, of the timestamp t, a dot, and the raw request body. Compute it over the bytes you received, before parsing the JSON, and compare in constant time. Reject requests whose t is more than 5 minutes old to stop replays.

Retries and failures

  • At-least-once. An event can arrive more than once. Deduplicate on id (or Dcycle-Event-Id).
  • Order is not guaranteed. Use the payload’s timestamps and statuses, not the arrival order.
  • Retry schedule. An attempt fails on any non-2xx answer, a timeout (5 s to connect to each address of your host, 10 s to answer) or a network error. Redirects are not followed. Dcycle retries after 1 min, 5 min, 30 min, 2 h, 6 h and 12 h: seven attempts over about 21 hours, then the delivery is failed.
  • Automatic disabling. After 5 deliveries in a row end failed, the endpoint is disabled (disabled_reason: TOO_MANY_FAILURES) and its creator is notified in the app. Fix your server and re-enable it with PATCH {"enabled": true}.
  • Delivery log. List Webhook Deliveries shows every delivery with what was sent (payload), what your server answered (last_status_code and the start of its body in last_response_body), why the last attempt failed (last_error_code) and the next retry. Retry Webhook Delivery sends one again on demand, with the same event id.

Debugging a failed delivery

last_error_code says why the last attempt failed, and last_error gives the detail: last_response_body keeps up to the first 2 KB of your server’s body. Once the status code has arrived, Dcycle waits at most 10 more seconds for that body, and the body never changes the outcome. If it looks garbled, your server compressed it even though Dcycle sends Accept-Encoding: identity. | ENDPOINT_DISABLED | The endpoint was disabled, so the delivery was not attempted again. last_status_code and last_response_body still show the attempt before. | Re-enable it with PATCH. | Once fixed, send a test event or retry the delivery.

URL requirements

The URL must use https and resolve to a public address. Private, loopback and link-local addresses (10.x, 192.168.x, 127.0.0.1, 169.254.169.254, …), localhost and URLs with credentials are rejected when you register the endpoint, and the name is resolved again before every request.

Endpoints

List Webhook Endpoints

Endpoints of your organization

Get Webhook Endpoint

One endpoint by id

Create Webhook Endpoint

Register a URL and get its secret

Update Webhook Endpoint

Change URL, events or re-enable it

Delete Webhook Endpoint

Stop sending to a URL

Rotate Webhook Secret

Replace the signing secret

Send Test Event

Check your server end to end

List Webhook Deliveries

What was sent and how it went

Retry Webhook Delivery

Send a past event again