Skip to main content
A connector lets your billing provider report revenue server-side, so attribution does not depend on a browser beacon or an SDK call firing. Create one per provider in the client portal under Results → Attribution → Connect your billing. Dialed generates one inbound URL per provider:
The random URL token (evw_…) is the baseline authentication for every provider. Signing secrets add provider-native verification, are encrypted at rest, and are never returned to the portal — it only reports has_signing_secret.

Set up your provider

What you paste where

In RevenueCat, open Integrations → Webhooks → New webhook. Paste the generated URL. Under Authorization header value, paste your connection token. Leave all events selected.No signing secret is needed — the Authorization header is the verification.

The one line of code

Right after you configure RevenueCat:

Events we ingest

Amount comes from event.price; a trial is recorded at zero. takehome_percentage, when present, produces the net amount alongside the gross.

How matching works

The install id is read from subscriber_attributes.evo_install_id.value. If that is missing, EVO falls back to the first UUID-shaped value among the event’s aliases, app_user_id, and original_app_user_id — which is why passing the EVO install ID as the RevenueCat app user id also works.

Signature verification

The Authorization header must equal the connection token, with or without a Bearer prefix. A mismatch returns 401 with invalid_authorization.

Confirm it

Press Send test in RevenueCat. The portal will show Connected.

Ledger semantics

Every connector event lands in the same attribution_events ledger as pixel and SDK conversions.

Signs and totals

Refund rows store negative amounts, so an ordinary SUM(amount_cents) produces net revenue with no special-casing.

Net vs gross

amount_cents is the gross value the provider reported. net_cents is the provider’s own take-home figure when it supplies one — RevenueCat’s takehome_percentage and Superwall’s proceeds. Providers that do not supply it leave net_cents empty.

Sandbox

Sandbox and test rows still flip a connection to Connected, so you can confirm setup end to end. They are excluded from client-facing conversion and revenue totals by the reporting serializers. Sandbox rows are detected per provider: environment: "SANDBOX" (RevenueCat, Superwall), livemode: false (Stripe), test: true (Shopify), and data.environment: "Sandbox" (Apple).

Deduplication

The dedup key is <provider>:<transaction id>, prefixed with refund: for refunds and sandbox: for sandbox events. A double-fired webhook cannot count a purchase twice, and a sandbox event never collides with the live event that shares its id.

Matching order

For every connector event, the first rung wins:
  1. Click token on the event — resolves at 0.95 with resolution_method: "link".
  2. Creator code typed as a discount or passed in metadata — resolves at 0.9 with resolution_method: "code" and bumps the code’s usage counters.
  3. Install id — the SDK install with that id, whose attribution the event adopts.
  4. Parent purchase — for a renewal or refund only, the most recent purchase with the same external_ref and the same sandbox flag. This is what keeps a renewal credited after an uninstall or a rotated user id.
  5. Otherwise unattributed at confidence 0. The revenue still lands, so the brand total and the unattributed gap stay honest.

Webhook responses

Any error also sets the connection’s status to error and stores the reason in last_error, which the portal displays. A successful delivery clears it and sets the status back to active.