Referrals API
The referrals API lets you create referral codes, track conversion milestones, and manage rewards programmatically. All endpoints require a valid API key (publishable or secret).
Create a referral code
Section titled “Create a referral code”Generate a referral code for a user. If the user already has a pending referral, the existing code is returned instead of creating a new one.
POST /v1/api/referral/createRequest body:
{ "user_id": "user_123", "user_name": "Jane Doe", "metadata": { "source": "dashboard" }, "ip": "203.0.113.42", "device_id": "device_abc123"}| Field | Required | Description |
|---|---|---|
user_id | Yes | Your internal user ID for the referrer |
user_name | No | Display name (shown in the leaderboard) |
metadata | No | Arbitrary JSON for your own use |
ip | No | Referrer’s IP address for fraud detection. Falls back to server-observed IP if omitted. |
device_id | No | Referrer’s device identifier for fraud detection (e.g. IDFA, GAID, or a fingerprint). |
Response 200:
{ "referral_code": "ABC123", "referral_url": "https://myapp.tolinku.com/ref/ABC123", "referral_id": "doc_id"}referral_url is null if no domains are configured on the Appspace.
Errors:
| Status | Error |
|---|---|
400 | user_id is required |
400 | Maximum referrals per user reached |
403 | Referrals are not enabled for this Appspace |
Webhook: Dispatches referral.created with { referral_code, referrer_id, referral_url }.
Look up a referral
Section titled “Look up a referral”Get the current status of a referral by its code.
GET /v1/api/referral/:codeURL parameters: :code is the referral code (e.g. ABC123).
Response 200:
{ "referrer_id": "user_123", "status": "pending", "milestone": "signed_up", "milestone_history": [ { "milestone": "installed", "timestamp": "2026-01-10T08:00:00Z" }, { "milestone": "signed_up", "timestamp": "2026-01-11T09:00:00Z" } ], "reward_type": "discount", "reward_value": "20", "reward_claimed": false, "referee_reward_type": "credit", "referee_reward_value": "10", "referee_reward_claimed": false, "created_at": "2026-01-09T12:00:00Z"}Errors:
| Status | Error |
|---|---|
404 | Referral not found |
Update milestone
Section titled “Update milestone”Update the milestone on a pending referral without marking it complete. Useful for multi-step funnels (e.g. installed, then signed_up, then purchased).
POST /v1/api/referral/milestoneRequest body:
{ "referral_code": "ABC123", "milestone": "signed_up"}| Field | Required | Description |
|---|---|---|
referral_code | Yes | The referral code |
milestone | Yes | The new milestone name |
Response 200:
{ "referral": { "id": "doc_id", "referral_code": "ABC123", "milestone": "signed_up", "status": "pending", "reward_type": "discount", "reward_value": "20" }}If the milestone update triggers auto-completion (based on your Appspace’s referral settings), the status will be "completed" and the referral.completed webhook fires.
Errors:
| Status | Error |
|---|---|
400 | referral_code is required |
400 | milestone is required |
404 | Referral not found, expired, or invalid milestone |
Complete a referral
Section titled “Complete a referral”Mark a referral as completed. Call this when the referred user has taken the required action.
POST /v1/api/referral/completeRequest body:
{ "referral_code": "ABC123", "referred_user_id": "user_456", "referred_user_name": "John Doe", "milestone": "completed", "ip": "198.51.100.7", "device_id": "device_xyz789"}| Field | Required | Description |
|---|---|---|
referral_code | Yes | The referral code |
referred_user_id | Yes | Your internal user ID for the referred person |
referred_user_name | No | Display name |
milestone | No | Defaults to "completed" |
ip | No | Referred user’s IP address for fraud detection. Falls back to server-observed IP if omitted. |
device_id | No | Referred user’s device identifier for fraud detection. |
Response 200:
{ "referral": { "id": "doc_id", "referrer_id": "user_123", "referred_user_id": "user_456", "status": "completed", "milestone": "completed", "completed_at": "2026-01-15T10:30:00Z", "reward_type": "discount", "reward_value": "20", "referee_reward_type": "credit", "referee_reward_value": "10" }}Errors:
| Status | Error |
|---|---|
400 | referral_code is required |
400 | referred_user_id is required |
404 | Referral not found |
404 | Referral not found or already completed |
409 | Referral flagged for abuse (includes reason field) |
Abuse reasons: self_referral, already_referred, reverse_referral, same_ip, same_device. See Preventing abuse for details.
Webhook: Dispatches referral.completed with { referral_code, referrer_id, referred_user_id, milestone }.
Claim reward (referrer)
Section titled “Claim reward (referrer)”Mark the reward as claimed for a completed referral.
POST /v1/api/referral/claim-rewardRequest body:
{ "referral_code": "ABC123"}Response 200:
{ "success": true, "referral_code": "ABC123", "reward_claimed": true}Errors:
| Status | Error |
|---|---|
400 | referral_code is required |
404 | Referral not found or not completed |
Claim reward (referee)
Section titled “Claim reward (referee)”Mark the referee reward as claimed for a completed referral. Use this when the referred user redeems their reward.
POST /v1/api/referral/claim-referee-rewardRequest body:
{ "referral_code": "ABC123"}Response 200:
{ "success": true, "referral_code": "ABC123", "referee_reward_claimed": true}Errors:
| Status | Error |
|---|---|
400 | referral_code is required |
404 | Referral not found or not completed |
List referrals by user
Section titled “List referrals by user”Get all referrals created by a specific user, with optional status filtering.
GET /v1/api/referral/by-user/:userIdURL parameters: :userId is the referrer’s user ID.
Query parameters:
| Param | Default | Max | Description |
|---|---|---|---|
limit | 50 | 200 | Number of referrals to return |
status | (all) | Filter by status: pending, completed, or expired |
Response 200:
{ "referrals": [ { "referral_code": "ABC123", "referred_user_id": "user_456", "referred_user_name": "John Doe", "status": "completed", "milestone": "first_purchase", "milestone_history": [ { "milestone": "pending", "timestamp": "2026-01-09T12:00:00Z" }, { "milestone": "signed_up", "timestamp": "2026-01-11T09:00:00Z" }, { "milestone": "first_purchase", "timestamp": "2026-01-15T10:30:00Z" } ], "reward_type": "credit", "reward_value": "10", "reward_claimed": true, "created_at": "2026-01-09T12:00:00Z", "completed_at": "2026-01-15T10:30:00Z" }, { "referral_code": "DEF456", "referred_user_id": null, "referred_user_name": null, "status": "pending", "milestone": "pending", "milestone_history": [ { "milestone": "pending", "timestamp": "2026-02-01T08:00:00Z" } ], "reward_type": null, "reward_value": null, "reward_claimed": false, "created_at": "2026-02-01T08:00:00Z", "completed_at": null } ], "total": 2}Errors:
| Status | Error |
|---|---|
400 | userId is required |
Referral counts for many users
Section titled “Referral counts for many users”Get referral counts for a list of users in one request. Built for syncing counts into another system, where asking once per user is thousands of requests and runs into the rate limit.
POST /v1/api/referral/counts-by-usersRequires a secret key. Unlike the other referral endpoints, publishable keys are refused, because one request reads up to 500 users’ counts and a publishable key ships inside your app.
Request body:
| Field | Type | Description |
|---|---|---|
userIds | string[] | Referrer user IDs. Up to 500 per request. |
{ "userIds": ["user_123", "user_456", "user_789"] }Response 200:
{ "counts": { "user_123": { "total": 5, "completed": 3, "pending": 2 }, "user_456": { "total": 1, "completed": 0, "pending": 1 }, "user_789": { "total": 0, "completed": 0, "pending": 0 } }}Every ID you send is returned, including IDs with no referrals and IDs Tolinku
has never seen, both as zeros. That way a 0 is distinguishable from an ID that
was dropped. Duplicate IDs collapse to a single entry, and an empty array
returns { "counts": {} }.
Performance: a request costs the same whether you send 5 IDs or 500, and the same whether your Appspace holds a thousand referrals or a million. Counts are updated whenever a referral is created, completed, or expires.
Errors:
| Status | Error |
|---|---|
400 | userIds must be an array |
400 | userIds must contain non-empty strings |
400 | Too many userIds. Maximum 500 per request. |
403 | Publishable key used |
Leaderboard
Section titled “Leaderboard”Get the top referrers ranked by completed referral count.
GET /v1/api/referral/leaderboardQuery parameters:
| Param | Default | Max | Description |
|---|---|---|---|
limit | 25 | 100 | Number of entries to return |
Response 200:
{ "leaderboard": [ { "referrer_id": "user_123", "referrer_name": "Jane Doe", "total": 18, "completed": 15, "pending": 3, "total_reward_value": "75" }, { "referrer_id": "user_456", "referrer_name": "John Smith", "total": 14, "completed": 12, "pending": 2, "total_reward_value": "60" } ]}