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
- RevenueCat
- Superwall
- Stripe
- Shopify
- Apple App Store
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 fromsubscriber_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
TheAuthorization 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 sameattribution_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:- Click token on the event — resolves at
0.95withresolution_method: "link". - Creator code typed as a discount or passed in metadata — resolves at
0.9withresolution_method: "code"and bumps the code’s usage counters. - Install id — the SDK install with that id, whose attribution the event adopts.
- Parent purchase — for a renewal or refund only, the most recent purchase with the same
external_refand the same sandbox flag. This is what keeps a renewal credited after an uninstall or a rotated user id. - Otherwise
unattributedat confidence0. 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.