How webhooks work
When a subscribed event occurs, Tilta sends an HTTP POST request to your registered endpoint with a JSON body describing the event. Your endpoint must respond with an HTTP2xx status code within a reasonable timeout to acknowledge receipt. If it does not, Tilta will retry the delivery automatically.
Event object structure
Every webhook payload follows the same envelope structure regardless of event type:string
required
A UUID uniquely identifying this event delivery. Use this field to implement idempotency – log processed IDs and skip any event you have already handled.
integer
required
Unix timestamp (seconds) of when the event occurred on Tilta’s side. Use this alongside the resource ID to determine the most recent state when events arrive out of order.
string
required
The dot-separated event type in
RESOURCE.PROCESS.OUTCOME format – for example, FACILITY.CREATION.ACCEPTED or ORDER.CONFIRMED. See the Event Reference for all available types.object
required
Event-specific payload. The fields present depend on the event type. Refer to the Event Reference for the exact shape of each event’s
data.Event subscriptions
Tilta uses a hierarchical dot-separated naming convention –RESOURCE.PROCESS.OUTCOME – which allows you to subscribe at any level of specificity. A subscription to a prefix automatically receives all descendant events.
Subscribe only to the events your integration actually needs. Broad prefix subscriptions are convenient but increase the volume of webhook traffic your endpoint must handle.
Setting up a webhook endpoint
1
Build and deploy your endpoint
Create an HTTPS endpoint on your server that accepts POST requests and returns a
2xx HTTP status code promptly. Perform any heavy processing asynchronously after acknowledging receipt – do not block the response while you process the event.2
Register your endpoint with Tilta
Call Tilta returns a subscription object that includes your signing secret. Store this secret securely – you will use it to verify incoming webhook signatures.
POST /v1/webhooks to subscribe your endpoint to one or more event types. The type field accepts either a full event type or a prefix.3
Implement signature verification
Every webhook request includes a
Tilta-Signature header. Verify this signature before processing any event to ensure the request genuinely came from Tilta. See Signature Verification below for the full implementation.4
Test with the sandbox
Use the sandbox base URL (
https://api.tilta-sandbox.io) to register test endpoints and trigger events without affecting production data. Verify that your endpoint correctly receives, validates, and processes events before going live.Signature verification
Tilta signs every webhook request so you can confirm it originated from Tilta and has not been tampered with. The signature is included in theTilta-Signature HTTP header.
Signature header format
t– Unix timestamp (seconds) of when Tilta signed the requestv1– HMAC-SHA256 hex digest of{webhookPayload}.{webhookTimestamp}, signed with your webhook signing secret
How to verify
To verify a signature, reconstruct the expected HMAC using the raw request body, the timestamp from the header, and your signing secret. Compare the result to thev1 value in the header using a timing-safe comparison to prevent timing attacks.
Rotating signing keys
Rotate your webhook signing secret periodically to limit the blast radius of a potential secret leak. Call the rotate endpoint and update your application configuration with the new secret before the old one expires.Retry behavior
If your endpoint does not return a2xx response – whether due to a server error, timeout, or any other failure – Tilta automatically retries the delivery. Retries continue for up to 12 hours using exponential backoff, giving your platform time to recover from transient outages without losing events.
Because retries can result in the same event being delivered more than once, always implement idempotency in your event handler. Log each processed event
id and skip any event whose id you have already seen.Managing subscriptions
List your subscriptions
Replace a subscription
UsePUT /v1/webhooks/{type} to update the endpoint URL or configuration for an existing subscription.
Unsubscribe
Best practices
Implement idempotent event handling
Implement idempotent event handling
The same event can be delivered more than once due to retries. Before processing any event, check whether you have already handled an event with the same
id. Store processed event IDs in a durable store (database, Redis, etc.) and skip duplicates. This prevents double-charging, duplicate fulfillment, or other unintended side effects.Subscribe only to the events you need
Subscribe only to the events you need
Broad prefix subscriptions (e.g., subscribing to
FACILITY instead of FACILITY.CREATION.ACCEPTED) send your endpoint every descendant event, including ones you may not care about. This increases traffic and processing load unnecessarily. Subscribe to the most specific type that covers your use case.Do not assume event ordering
Do not assume event ordering
Tilta does not guarantee that events arrive in chronological order. Network conditions and retry timing can cause earlier events to arrive after later ones. Always use the
occurred_at timestamp combined with the resource’s external ID to determine the current state of a resource – do not rely solely on arrival order.Respond quickly; process asynchronously
Respond quickly; process asynchronously
Your endpoint should acknowledge receipt by returning
200 OK as fast as possible. Push the event onto a queue and process it in a background worker. If your handler performs slow database writes or downstream API calls synchronously, it risks timing out and causing Tilta to retry an event you have already received.Rotate signing keys periodically
Rotate signing keys periodically
Treat your webhook signing secret like a password. Rotate it on a regular schedule using
POST /v1/webhooks/{type}/signature_key. Update your deployed secret before discarding the old one to avoid a gap in verification. Store secrets in environment variables or a secrets manager – never hardcode them in source code.