How webhooks work
1
Register an endpoint
Add an HTTPS URL in Settings → Integrations → Webhooks, or create a subscription with the Webhooks API.
2
Choose events
Pick from the event catalog: submissions, contacts, companies, deals, tasks, meetings and calls. Each object needs its read scope when you subscribe with an API key or an app.
3
Receive signed deliveries
When an event happens, Orbit POSTs a JSON envelope to your URL, signed with the webhook’s secret.
4
Respond with 2xx
Return any 2xx status within the webhook’s timeout (30 seconds by default). Anything else is retried.
What you can subscribe to
Events fire however the change was made: in the dashboard, by an import, through the API or MCP, or by a workflow. Submission events can be limited to one form; every other event is workspace-wide.
GET /api/v1/webhooks/events returns the same catalog with the scopes your credential holds.
The envelope
Every delivery has the same top-level shape.data is specific to the event and is documented per object on the events page.
Imports
A CSV import, the API’s bulk import endpoints and a CRM migration can create tens of thousands of records in minutes. By default their events are not delivered: no webhook or connected app receives them, so a migration never turns into thousands of deliveries nobody asked for. A workspace owner or admin can change that under Settings → Integrations → Connected apps → Send imported records to integrations. Turning it on is an explicit acceptance (recorded with who, when and the wording), applies to every webhook and connected app in the workspace, and only affects imports that run after it. Those deliveries carry"source": "import", so a receiver that wants to treat them differently (skip them, batch them, not bill for them) can tell them apart. Records added one at a time, by a person, a form, a workflow or the API, always carry "source": "app" and are always delivered.
Workflows are unaffected: an import never starts a workflow unless the person importing picks one in the import dialog.
Changes your app made
When a connected app changes a contact, company, deal, task or tag through the API (or an import it runs), the events that change raises carry the app’s id inactor.app_id: the id of your OAuth app, the one GET /api/v1/me returns. Your app receives them like any other event. An app that keeps another system in sync with Orbit should skip them: they describe a write it has already applied on its side, and sending them back is how two systems end up overwriting each other in a loop.
submission.created, submission.qualified and the meeting events) carry app_id: null for now. See Build a two-way sync.
Headers
Delivery
- Timing. Form submissions and meeting events are sent as they happen. Contact, company, deal, task, call and submission-change events are collected from the database and sent within about a minute.
- Retries. A delivery that fails (a timeout, a connection error, a 5xx, or a 429) is retried with exponential backoff starting from the webhook’s retry delay (60 seconds by default), capped at 5 minutes between attempts, up to the webhook’s retry count (3 by default, 5 at most). A
Retry-Afterheader on a 429 is honoured. Other 4xx responses are not retried: fix the endpoint and the next event will get through. - Auto-disable. After 10 consecutive events that failed every attempt, the webhook is switched off and
last_errorrecords why. Switch it back on in the dashboard or withPATCH /api/v1/webhooks/:id. - At least once. Treat deliveries as at-least-once and de-duplicate on
id. Events are not guaranteed to arrive in order; useoccurred_atwhen order matters. - Logs. Every attempt is recorded. See them under the webhook in the dashboard or with
GET /api/v1/webhooks/:id/deliveries.
Learn more
Events
Every event and its payload
Security
Verify signatures and guard against replays
Webhooks API
Create and manage subscriptions from code
Webhooks for apps
Subscribe on behalf of the workspaces that installed your app