The contract, on one page.
Every delivery is a signed webhook that names its action. The same records are available through a documented REST API. This page is the whole contract; the OpenAPI reference in your workspace has every field.
The envelope
Every webhook carries one entity and one action. The record itself is under data and has the same shape as the API response.
- event
- What happened: entity.published, entity.unpublished or entity.test.
- deliveryId
- Stable per delivery. A retry carries the same id and the same body, so receivers can deduplicate.
- tenantId
- Your workspace. Every key and every webhook is scoped to it.
- entityType
- event, eventVenue or organization.
- entityId
- Stable across publishes, updates and withdrawals of the same record.
- timestamp
- When the delivery was signed, ISO 8601.
- data
- The record as it was at the time of the delivery. On a withdrawal it is the last published state.
X-DataHub-Event: entity.publishedX-DataHub-Delivery-Id: dlv_01J8W4Q7K2M3N4P5X-DataHub-Timestamp: 2026-09-23T14:02:11.418ZX-DataHub-Signature: sha256=9f2c…e41b
{ "event": "entity.published", "deliveryId": "dlv_01J8W4Q7K2M3N4P5", "tenantId": "tnt_7c1e", "entityType": "event", "entityId": "evt_3f9a2c", "timestamp": "2026-09-23T14:02:11.418Z", "data": { "name": "Nils Wogram Root 70", "startDate": "2026-10-03T18:30:00.000Z", "timezone": "Europe/Berlin", "status": "scheduled", "url": "https://example-club.de/tickets/root-70" }}
The events
- entity.published
- A record was published to your workspace or changed afterwards. Apply data as the current state.
- entity.unpublished
- The record was withdrawn: cancelled, removed or no longer in your coverage. Take it down.
- entity.test
- Sent from the workspace when you test an endpoint. Same envelope, test: true, a fixture record.
- entity.approved
- The legacy name for a publish, kept for early integrations. Treat it as entity.published.
Verifying a delivery
Each request carries the signature, the timestamp, the event name and the delivery id in headers. Verify before you parse.
- 1Read the X-DataHub-Timestamp and X-DataHub-Signature headers.
- 2Compute an HMAC-SHA256 over "<timestamp>.<raw body>" with your webhook secret and prefix it with "sha256=".
- 3Compare it to the signature header in constant time.
- 4Reject deliveries whose timestamp is older than a few minutes; the window is yours to choose.
- 5Answer 2xx only after you have stored the delivery. Anything else is retried.
Change semantics
- A change to a published record is delivered again as entity.published with the full current record. You never receive a partial patch.
- Withdrawals are explicit. A record that leaves your coverage is delivered as entity.unpublished, never silently dropped.
- Parents come first. A venue or organizer a new event depends on is delivered before the event.
- Deliveries are at-least-once. Deduplicate on deliveryId; a later delivery of the same record supersedes an earlier one.
The API
A versioned REST API for events, venues, organizers and artists, with keys scoped per consumer and the same record shape as the webhook data field. The OpenAPI reference lives in your workspace under Integrations.
Open the client workspaceRetries and timeouts
A webhook that does not answer 2xx within ten seconds is retried with exponential backoff. Every attempt is logged in your workspace with status, latency and an excerpt of the response.
A paused workspace collects deliveries and drains them in order when it resumes.
A publish that is still queued when the record is withdrawn is dropped, so a slow retry never resurrects a cancelled event.