Skip to main content
Documentation
GuidesReferrals

Test referrals

Test a referral end to end on a real phone: the iPhone paste path, the Android Play install referrer, the test webhook, and the Referrals report.

A referral test follows the same path a friend takes: tap the link, install from a store, open the app, sign up, and claim. This page shows the steps for iPhone and Android, how to test your webhook without a phone, where to read the result, and what a failure usually means. Start with the setup checks, then run the platform test that fits your app.

Before you test

  1. Update the app to SDK 1.2.0 or later. Builds on 1.1.x cannot read an invitation.
  2. Open the app in the dashboard, go to Referral handoff, and choose Setup. Fix anything the checks list. The check ids are ios_recovery_store_url, ios_recovery_sdk and android_recovery_fingerprint. GET /v1/apps/{id} returns the same answer as referral_readiness.
  3. For iPhone, turn on Offer referral handoff on iOS.
  4. Create a referral link, or turn on Referral link for an existing one. A tap from before the link became a referral link is not a referral.
  5. Add a webhook endpoint under Referral handoff, then Webhook.

Test the webhook without a phone

Send test on the webhook tab sends one signed webhook.test event to the saved address and shows what your server answered. The event has the same shape and headers as a real one, with an id that starts evt_test_. We send it once and never retry it. It appears in the delivery log.

The MCP tool send_test_webhook does the same. A passing test proves your address, your signature check and your reply. It does not prove the link or the SDK, so run a phone test next. Receive referral webhooks covers the signature steps.

Test on an iPhone

  1. Delete the app from the phone, so the tap counts as a first install.
  2. Open the referral link on the phone. You see the invitation page, then the App Store or a TestFlight build.
  3. Install and open the app. Tap the paste button on your first screen.
  4. Check that redeemInvitation returned a link. A nil result means nothing was confirmed.
  5. Sign up as a new test user with a new installer id, and call claimReferral.

An invitation pasted on an iPhone is an exact match: matchMethod is install_token and isExact is true. If your app pastes into a field of your own, as in React Native and Flutter, paste the text from the invitation page into that field.

Test the paste step from a build that went through the store path, such as TestFlight. The system paste button pastes in one tap with no prompt, so the person sees only your screen.

Test the Android install referrer

The Play install referrer exists only when Google Play installs the app. A debug build installed from a cable does not go through the store, so it does not test the real path. To test it:

  1. Upload a build to a Google Play internal testing track and install it from the store listing on a test phone.
  2. Delete the app from the phone before each run.
  3. Open the referral link on the phone. It goes to Google Play with the invitation inside the install referrer.
  4. Install, then open the app. The SDK reads the referrer at first launch, and the match arrives in onLink with isDeferred true.
  5. Sign up as a new test user with a new installer id, and call claimReferral.

The match is exact: matchMethod is android_referrer. Two details explain most Android surprises:

  • The check runs once per install. It runs on the first launch and does not run again until a reinstall. To repeat a test, delete the app and install again.
  • Sideloaded installs have no referrer. An install by adb install or a direct APK, a device without Google Play Services, and referrer data that has expired all lack the install referrer. Such an install gets no referral credit.

Register the signing certificate SHA256 fingerprint on the app before you test. For a build from a Play track, use the fingerprint of the key that signed that build. Find your app identifiers shows where to find it.

Read the result

In the app. claimReferral returns a result with a status. A claimed status means the install is credited. See the quickstart for your SDK: iOS, Android, React Native, Flutter.

In the Referrals report. Open Referral handoff, then Referrals, or /referrals in the dashboard. Each row shows the link, the installer id, the match, and the webhook result. Open a row to see the claims, the events we sent with their payloads, and every delivery attempt.

Over the API. GET /v1/referrals returns the same list, newest first. Filter it to your test user:

The filters are installer_id, link_id, status, match, platform, app_id, from and to. The key needs referrals:read. The MCP tools list_referrals and get_referral return the same data. See the Referrals API.

The report status tells you how far the referral got:

StatusMeaning
claimedRecorded. No webhook delivery has finished yet
deliveredYour endpoint answered 2xx
retryingA delivery failed and another attempt is scheduled
failedEvery attempt failed. Resend it after you fix the endpoint
flaggedClaimed after the credit window
duplicateA later claim for an installer that already held a credit

Run the test again

The first valid claim per app and installer id wins, so use a fresh installer id for each run. To start over with the same id, delete the test referral with DELETE /v1/referrals/{id} or the MCP tool delete_referral. Then delete the app from the phone and repeat the steps.

Common failures

The claim answers none and you expected a credit. Check the link first: it must be a referral link, and the tap must be after referral_since. Then check the credit window you chose: 24 hours, 7 days or 30 days from the tap. Last, check whether the phone already had the app. That counts only when Count people who already have the app is on, and it is off by default.

The claim answers flagged. The claim came after the credit window closed, and the referral carries the flag outside_window. Tap the link again, or choose a longer window.

The claim answers ignored. This installer id already holds a credit. The result names the first referral in duplicateOf. Use a fresh installer id.

redeemInvitation returns no link on iPhone. The text was not an invitation, or it matched nothing. Copy the invitation again from the invitation page. Confirm that the app's ios_recovery_sdk check passes and that the iOS handoff is on.

An error says the invitation expired or is invalid. RECOVERY_TOKEN_EXPIRED means the invitation ran out, or its link is paused or ended. RECOVERY_TOKEN_INVALID means the text was changed, is incomplete, or belongs to another app. Open the link again. See the errors page.

409 LINK_NOT_REFERRAL. The link_id names an ordinary link. Turn on is_referral for it.

403 SDK_KEY_ROUTE_FORBIDDEN. An SDK key reached a route other than the SDK routes. Use an API key with referrals:read or referrals:write for the report and webhook routes.

No webhook arrives. Open the referral in the report and read its delivery attempts. A 5xx answer, a timeout or a failed connection triggers a retry, and the event is tried up to 5 times over 20 minutes. A 4xx or 3xx answer ends the event as failed. Fix the endpoint, then choose Resend. A signature that does not match usually means a JSON parser touched the body before you verified it. Verify the raw body.

The iOS switch will not turn on. Setup lists what is missing. Add the App Store URL to the app. A build on SDK 1.2.0 or later that was opened once clears the SDK warning.

Next