Unified.to
All articles

Replace Polling with Unified Webhooks: Real-Time and Historical Data in One Flow

·

Unified.to_webhooks_enhancements.png

Updated September 20th, 2026

To load a connection's historical records and then receive its ongoing changes through one webhook flow, create the webhook with include_all=true: Unified.to delivers the existing records in pages marked INITIAL-PARTIAL, signals the end of the backfill with INITIAL-COMPLETE, and then delivers created, updated and, where supported, deleted records through the same subscription. This works for both native and [virtual webhooks](/blog/what_are_virtual_webhooks_how_they_differ_from_sync_based_webhooks) wherever initial sync is supported, so you don't run a separate backfill job and a separate sync pipeline.

What is the difference between a native and a virtual webhook?

A native webhook registers with the integration, which sends events to Unified.to as they happen; a virtual webhook is Unified.to checking the integration for changes on your interval and delivering what changed. You create, manage and receive both through the same API and payload format.

Native webhooks depend on the integration offering webhooks. Virtual webhooks exist for supported integrations whose APIs have no webhooks of their own, or whose webhooks are limited. As of September 2026, a virtual webhook can check as often as every minute on paid plans and every 60 minutes on the trial. Unified.to stores no customer records at rest between checks.

Where an integration supports both, you choose: native for delivery as events occur, virtual to control how often changes are checked.

How do I check whether an integration supports webhooks?

Open the integration in the Unified.to dashboard and click the Feature Support tab; each object lists its supported webhook events by type. The labels read, for example, "native & virtual created event" or "native deleted event," so you can see per object and per event whether native, virtual or both are available. The same tab lists the filter parameters the object supports.

Webhook support is per integration and per object. If an object doesn't support webhooks on an integration, creating one returns an error saying so.

How do I create a webhook subscription?

You create a Unified.to webhook by POSTing to /unified/webhook with a connection ID, an object type, an event and your endpoint URL; add include_all=true to the query string to receive existing records first. One connection can have many webhooks. Deleting the connection deletes its webhooks, and deleting a native webhook also removes the subscription registered with the integration.

POST /unified/webhook?include_all=true

{
  "connection_id": "CONNECTION_ID",
  "hook_url": "https://example.com/webhooks/unified",
  "object_type": "ats_candidate",
  "event": "updated",
  "webhook_type": "virtual",
  "interval": 5,
  "fields": "id,name,emails",
  "filters": { "company_id": "12345" }
}

The full field reference is on the Create webhook subscription page, and How to create and configure webhooks walks through setup step by step. What each field does:

  • object_type and event define the subscription. Events are created, updated and deleted.
  • webhook_type is optional. Leave it out and Unified.to picks a type the object supports. Requesting a type the integration doesn't support returns 400.
  • interval applies to virtual webhooks only. Native webhooks ignore it.
  • fields limits the payload. By default every field except raw is sent; add raw for the integration's original object and raw.fieldname for specific custom fields.
  • filters narrows which records produce events.

Which events can a webhook subscribe to?

A Unified.to webhook subscribes to one of three events: created, updated or deleted. An updated event also fires when a record is first created, so a webhook subscribed to updated alone receives new records too; compare created_at and updated_at on each record to tell them apart.

deleted events arrive on native webhooks where the integration sends them. On virtual webhooks, deletion detection is reliable only on BambooHR, Dropbox, Google Drive, Gmail, JobAdder, OneDrive, SharePoint, RingCentral, Egnyte and Box. The Feature Support tab shows which.

Can I change a webhook from virtual to native?

No. A webhook's type is set when it's created and can't be changed by an update; delete the webhook and create a new one with the other type. Native and virtual webhooks use different mechanisms, so switching in place would risk duplicates or broken subscriptions.

How does initial sync deliver historical data?

Adding include_all=true when you create a webhook makes Unified.to read the connection's existing records page by page and POST each page to your endpoint before the webhook starts on ongoing changes. Unified.to handles pagination, the integration's rate limits and backoff; you don't call list endpoints, manage cursors or store checkpoints.

Each page arrives with type: INITIAL-PARTIAL. The last page arrives with type: INITIAL-COMPLETE and may be empty. After that, ongoing events arrive with type: VIRTUAL or type: NATIVE, so your handler can, for example, keep a loading state in your product until the sync completes.

Initial sync works the same way for native and virtual webhooks wherever the integration supports it, at the page size the integration allows, and the interval setting has no effect on it. How long it takes depends on how much data there is, the integration's rate limits and how quickly your endpoint responds. Native events may arrive out of order or more than once, so make your handler idempotent.

What does a webhook payload contain?

Every delivery is a POST to your webhook URL containing an array of records, a type marker, the webhook object, your connection's external_xref, and a signature you can verify. In detail:

  • data: an array of objects in the same format the corresponding API endpoint returns. The fields option, including raw and custom fields, works the same way on webhooks as on API reads, for both webhook types.
  • type: INITIAL-PARTIAL, INITIAL-COMPLETE, VIRTUAL or NATIVE.
  • webhook: the webhook object, including its id.
  • external_xref: the value you set on the connection, so you can route the event to the right user or account.
  • nonce and sig256: for verifying the request came from Unified.to, using HMAC-SHA256 with your workspace secret.

If more records changed than fit in one page, you receive several POSTs. Respond with a success status once you've accepted the payload, and do heavy processing afterwards. The full payload schema is in the webhooks reference.

How do webhook filters work?

Filters restrict a webhook to records matching a value, such as deals belonging to one company, so your endpoint only receives events you'll act on. Filters are supported on virtual webhooks and on native webhooks for some integrations; the Feature Support tab lists the filter parameters each object accepts, typically those ending in _id or type.

Filters an integration doesn't support are accepted but have no effect. A few integrations require a filter, and create returns an error naming the integration and the filter if it's missing. See How to filter webhook events.

How do I test a webhook without waiting for an event?

Trigger a virtual webhook manually from the dashboard or the API, and it runs its next check immediately instead of waiting for the interval. It sends events only if that check finds changes, so a trigger on a quiet connection produces nothing. Manual triggering applies to virtual webhooks only; on a native webhook the endpoint returns 400. See Trigger webhook in the API reference.

What happens when my endpoint doesn't respond?

Unified.to retries the delivery three times immediately, about a second apart, and what happens next depends on the webhook type. As of September 2026:

StageVirtual webhookNative webhook
After the 3 immediate retriesBacks off progressively for up to about two weeksMarked unhealthy
What a retry sendsRe-reads the same page from the integration; no payload is storedNot applicable; no further retries
If retries are exhaustedMarked unhealthy; scheduling stopsThe event isn't redelivered unless the integration sends it again
For a virtual webhook, the read position only advances after a successful delivery, so a retry delivers the current state of the same page. For a native webhook, keep your endpoint reachable during deploys, or use a virtual webhook where longer recovery matters.

If the integration is unavailable or rate-limited, Unified.to backs off and retries, honouring the integration's retry-after guidance when it sends one. Broken authorization or missing permissions on the connection aren't retried; the webhook is marked unhealthy straight away.

How do I know when a webhook has stopped?

Every Unified.to webhook has an is_healthy field, and once it's false the webhook stops reading and delivering and does not resume on its own. There's no re-enable: fix the endpoint or the connection's auth, then recreate the webhook.

Monitoring health is your responsibility. To be notified when a webhook goes unhealthy, set a notifications webhook URL under Settings > Workspace in the dashboard and subscribe to the WEBHOOK_UNHEALTHY event. Do this when you create your first webhook, not after one breaks. The dashboard's audit trail shows each webhook's recent runs and the records delivered. For diagnosing a stopped webhook, see How to troubleshoot unhealthy webhooks.

How are webhooks billed?

Unified.to bills webhooks per page of changes successfully delivered to your webhook URL, not per record, and checks that find no changes aren't billed, so a virtual webhook on a one-minute interval costs nothing during quiet periods. As of September 2026, failed delivery attempts and retries aren't billed, and neither are retriable read errors such as rate-limit responses from the integration.

Which plans include webhooks?

Webhooks are available on all Unified.to plans, with the minimum virtual webhook interval set by tier: as of September 2026, 60 minutes on the trial and 1 minute on paid plans.

Start with a tester account or view pricing.

What does a webhook subscription replace?

One Unified.to webhook subscription replaces a backfill job, an incremental sync pipeline, and the retry and pagination code that connected them. You stop running polling infrastructure, and you receive change events from supported integrations whose APIs don't offer webhooks, through the same subscription you use for the ones that do.

For when to poll and when to use webhooks at all, see Polling vs Webhooks: When to Use One Over the Other. To move an existing polling setup over, see Replacing Polling with Event-Driven Integrations.

Frequently asked questions

Do virtual webhook checks count against the integration's rate limits? Yes. Each check calls the integration's API, so it counts against that integration's rate limits, and Unified.to backs off automatically when the integration returns a rate-limit response. What isn't consumed is your Unified.to usage: checks that find nothing aren't billed.

All articles