Returning.AIDevelopers
v1

API reference / Gamification / Referral

.md

Get user's referral summary

Read one trader's referral invite link, their referral totals and each invited trader's progress through your programs.

Last updated 26 Sep 2026API v1

Method
POST
Path
https://api.returning.ai/v1/referral/summary
Permission
getUserData
Retries
Read-only; exact retries are safe

When to use this

  • Show a trader their invite link and how the people they invited are doing, in your own app.
  • Support needs to check whether a trader's invited friend has completed a stage.
  • Reconcile the referral rewards a trader has been paid.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
getUserDataShown in the dashboard as “Get User Data”

Send a Community API key with getUserData, shown in the dashboard as Get User Data. The key decides the community, so never send a community ID. The trader must be a member of that community. Keep the key on your server: the response includes emails and invite links.

Behaviour#

This read changes nothing. Identify the trader who sends invites; their invited traders come back in referees. The totals in activity and the progress in referees cover running programs only. When referrals are switched off for your community, a trader who exists still returns 200, with zero totals and no referees.

Referral progress is worked out after the invited trader acts, so a stage can take a short while to show as complete. The list of invited traders can also be up to 30 seconds old. If you are waiting for a change, read again with backoff rather than treating the first result as final.

With programId, each stage's status is only completed or not_started, and stage rewards come back as 0. Read reward amounts from Get referral programs.

Request#

Headers#

Authorization#stringREQUIRED
Community API key with getUserData.

RuleBearer <API_KEY>

Content-Type#stringREQUIRED
Request body format.

Ruleapplication/json

Body#

Send identifier with a type and value. id is the numeric platform user ID from Get User Data, not the internal record ID. For a broker customer ID stored in a custom user field, use custom-field with that field's key as fieldName, for example customerid.

Page through invited traders with pagination: send nextCursor back as pagination.cursor until hasNextPage is false. Keep the same identifier, programId and lang for every page.

identifier#objectREQUIRED
The trader whose referrals you want, the person who sends invites. Not one of the traders they invited.

Eg{"type": "email", "value": "trader@example.com"}

type#stringREQUIRED
How to find the trader: id (platform user ID), email, data-email (same as email), custom-field (a value in one of your custom user fields), or data-customer-id, which also reads a custom user field.

Ruleid, email, data-email, data-customer-id or custom-field

Eg"email"

value#stringREQUIRED
The platform user ID, email or field value. Emails ignore case; spaces at either end are removed.

RuleNon-empty text

Eg"trader@example.com"

fieldName#stringOPTIONAL
The custom user field's key, matched exactly. Required with custom-field. With data-customer-id it defaults to customerId; send it when your field's key differs.

RuleCustom field key

Eg"customerid"

pagination#objectOPTIONAL
Paging for the list of invited traders.

Eg{"limit": 20}

limit#integerOPTIONAL
Invited traders per page.

RuleDefault 20; max 100

Eg20

cursor#stringOPTIONAL
nextCursor from the previous page. Omit it for the first page. A cursor that isn't recognised starts from the first page.

RuleOpaque text

programId#stringOPTIONAL
Show progress for one program only. A programId from Get referral programs.

RuleProgram ID in your community

Eg"66f000000000000000000710"

lang#stringOPTIONAL
Language code for program, stage and requirement text, such as fr. Omit it, or send en, for the text as entered.

RuleLanguage code

Eg"en"

curl --request POST \
  --url https://api.returning.ai/v1/referral/summary \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "identifier": {
      "type": "email",
      "value": "trader@example.com"
    },
    "pagination": {
      "limit": 20
    }
  }'

Response#

A 200 returns the trader in data.user, their links in data.invite, totals in data.activity, and one page of invited traders in data.referees. Share invite.url, not platformUrl: when your community has a custom invite link, url is that link. Branch on the HTTP status.

meta#objectALWAYS
Status of the request.

Eg{"status": "success", "statusCode": 200}

status#stringALWAYS
Result of the request.

Rulesuccess

statusCode#integerALWAYS
The HTTP status, repeated.

Eg200

message#stringALWAYS
Human-readable summary. Do not branch on it.

Eg"Get referral summary success."

data#objectALWAYS
The summary.

Eg{ ... }

user#objectALWAYS
The trader you asked about.

Eg{ ... }

id#stringALWAYS
The trader's internal user record ID.

Eg"<userObjectId>"

userId#stringALWAYS
The trader's platform user ID, as a string.

Eg"3247779"

username#stringALWAYS
The trader's username, or their display name when there is no username.

Eg"sample_trader"

email#stringALWAYS
The trader's email, or null when none is stored.

Eg"trader@example.com"

invite#objectALWAYS
The trader's invite link.

Eg{ ... }

url#stringALWAYS
The link to share. Your custom invite link when one is set up for your community and the trader has every value it needs; otherwise the same as platformUrl.

Eg"https://community.example.com/v2/app/invite/66f000000000000000000010:3247779"

platformUrl#stringALWAYS
The invite link on your community's Returning.AI address, ending in /v2/app/invite/<code>. Starts with / when your community has no custom domain.

Eg"https://community.example.com/v2/app/invite/66f000000000000000000010:3247779"

code#stringALWAYS
The trader's invite code, as <communityId>:<platform user ID>.

Eg"66f000000000000000000010:3247779"

origin#stringALWAYS
Your community's custom domain, such as https://community.example.com. Empty when there is none.

Eg"https://community.example.com"

activity#objectALWAYS
The trader's referral totals across your running programs.

Eg{ ... }

totalReferrals#integerALWAYS
Traders this trader has invited who still have an account.

Eg1

inProgress#integerALWAYS
Invited traders who have completed at least one stage, but not every stage.

Eg1

completed#integerALWAYS
Invited traders who have completed every stage of every running program.

Eg0

xpEarned#integerALWAYS
XP this trader has been paid for referrals.

Eg250

coinsEarned#integerALWAYS
Coins this trader has been paid for referrals.

Eg25

referees#object[]ALWAYS
The invited traders on this page, most recently joined first. Empty when there are none.

Eg[ ... ]

userId#stringALWAYS
The invited trader's platform user ID, as a string.

Eg"3247780"

username#stringALWAYS
The invited trader's display name, falling back to their username.

Eg"Invited Trader"

avatar#stringALWAYS
Profile picture URL. Empty string when none.
joinedAt#stringALWAYS
When the invited trader joined, ISO 8601 UTC, or null when not recorded.

Eg"2026-09-20T08:30:00.000Z"

progressByProgram#object[]ALWAYS
Progress in each running program, or in the one programId you sent.

Eg[ ... ]

programId#stringALWAYS
The program's ID.

Eg"66f000000000000000000710"

programName#stringALWAYS
The program's name.

Eg"Invite a trader"

completedStages#integerALWAYS
Stages completed.

Eg1

totalStages#integerALWAYS
Stages in the program.

Eg2

percentage#integerALWAYS
completedStages as a percentage of totalStages, rounded.

Eg50

stages#object[]ALWAYS
Each stage, in order.

Eg[ ... ]

stageId#stringALWAYS
The stage's ID.

Eg"66f000000000000000000711"

stageNumber#integerALWAYS
Position in the program, starting at 1.

Eg1

name#stringALWAYS
Stage name.

Eg"Get active"

description#stringALWAYS
Stage description. Empty string when none.

Eg"Your friend earns more than 500 XP."

displaySetting#stringALWAYS
What traders are shown for the stage.

Rulecondition, description or condition_and_description

Eg"condition"

status#stringALWAYS
Where the invited trader is on this stage. in_progress means some requirements are met.

Rulecompleted, in_progress or not_started

Eg"completed"

isCompleted#booleanALWAYS
true when the invited trader has completed the stage.

Egtrue

revoked#booleanALWAYS
true when the stage was completed but the invited trader no longer meets its requirements. The reward isn't taken back.

Egfalse

rewards#objectALWAYS
The stage's reward to the referrer, as xp and coins.

Eg{"xp": 250, "coins": 25}

requirements#objectALWAYS
How many requirements are met, as met out of total, with operator and each condition group in mainConditions.

Eg{ ... }

operator#string
and when every group must be met, or when one is enough.
met#integer
Requirements met.
total#integer
Requirements needed. A group or stage set to or counts as one.
mainConditions#object[]
The condition groups.
groupId#string
The group's ID.
operator#string
and or or, for the conditions in the group.
text#stringALWAYS
The group's text for traders, or null when none is shown.
isMet#boolean
true when the group is met.
revoked#boolean
true when a condition in a completed stage is no longer met.
nestedConditions#object[]
The conditions in the group.
conditionId#string
The condition's ID.
text#string
The condition's text for traders. When none is set, the condition's key, or Complete this condition.
isMet#boolean
true when the condition is met. Every condition shows true once the stage is complete.
revoked#boolean
true when the condition was met for a completed stage and no longer is.
isRaw#boolean
true when text is the condition's key because no text for traders is set.
totalCount#integerALWAYS
Invited traders across all pages.

Eg1

pagination#objectALWAYS
Paging for the invited traders.

Eg{"nextCursor": null, "hasNextPage": false}

hasNextPage#booleanALWAYS
true when another page follows.

Egfalse

nextCursor#stringALWAYS
Send as pagination.cursor to get the next page. null on the last page.

RuleNullable

Egnull

{
  "meta": {
    "status": "success",
    "statusCode": 200
  },
  "message": "Get referral summary success.",
  "data": {
    "user": {
      "id": "<userObjectId>",
      "userId": "3247779",
      "email": "trader@example.com",
      "username": "sample_trader"
    },
    "invite": {
      "code": "66f000000000000000000010:3247779",
      "origin": "https://community.example.com",
      "url": "https://community.example.com/v2/app/invite/66f000000000000000000010:3247779",
      "platformUrl": "https://community.example.com/v2/app/invite/66f000000000000000000010:3247779"
    },
    "activity": {
      "coinsEarned": 25,
      "xpEarned": 250,
      "totalReferrals": 1,
      "inProgress": 1,
      "completed": 0
    },
    "referees": [
      {
        "userId": "3247780",
        "username": "Invited Trader",
        "avatar": "",
        "joinedAt": "2026-09-20T08:30:00.000Z",
        "progressByProgram": [
          {
            "programId": "66f000000000000000000710",
            "programName": "Invite a trader",
            "completedStages": 1,
            "totalStages": 2,
            "percentage": 50,
            "stages": [
              {
                "stageId": "66f000000000000000000711",
                "stageNumber": 1,
                "name": "Get active",
                "description": "Your friend earns more than 500 XP.",
                "displaySetting": "condition",
                "status": "completed",
                "isCompleted": true,
                "rewards": {
                  "xp": 250,
                  "coins": 25
                },
                "requirements": {
                  "operator": "and",
                  "met": 1,
                  "total": 1,
                  "mainConditions": [
                    {
                      "groupId": "66f000000000000000000712",
                      "operator": "and",
                      "text": null,
                      "isMet": true,
                      "revoked": false,
                      "nestedConditions": [
                        {
                          "conditionId": "66f000000000000000000713",
                          "text": "Earn more than 500 XP",
                          "isMet": true,
                          "revoked": false,
                          "isRaw": false
                        }
                      ]
                    }
                  ]
                },
                "revoked": false
              },
              {
                "stageId": "66f000000000000000000714",
                "stageNumber": 2,
                "name": "Fund an account",
                "description": "",
                "displaySetting": "condition",
                "status": "not_started",
                "isCompleted": false,
                "rewards": {
                  "xp": 0,
                  "coins": 100
                },
                "requirements": {
                  "operator": "and",
                  "met": 0,
                  "total": 1,
                  "mainConditions": [
                    {
                      "groupId": "66f000000000000000000715",
                      "operator": "and",
                      "text": null,
                      "isMet": false,
                      "revoked": false,
                      "nestedConditions": [
                        {
                          "conditionId": "66f000000000000000000716",
                          "text": "Make a first deposit",
                          "isMet": false,
                          "revoked": false,
                          "isRaw": false
                        }
                      ]
                    }
                  ]
                },
                "revoked": false
              }
            ]
          }
        ]
      }
    ],
    "totalCount": 1,
    "pagination": {
      "nextCursor": null,
      "hasNextPage": false
    }
  }
}

Errors#

Validation 400 errors and the key errors (401, 403) carry a code in meta.code. Other errors have no code: read detail, which says what went wrong, and branch on the HTTP status. message on a validation error can vary; don't branch on it.

Fix the request05

400Fix the request
The lookup couldn't run. detail says why: Custom field identifier does not exist. (no custom user field has that key; data-customer-id without fieldName looks for customerId), or Custom field identifier value is invalid. (the value doesn't fit the field's type).
400VALIDATION_FAILEDFix the request
A field is missing or invalid: no identifier, an unknown identifier.type, an empty value, custom-field without fieldName, or pagination.limit outside 1-100. detail names each field, such as identifier.fieldName.
401AUTH_API_KEY_REQUIREDFix the request
No key was sent. Send Authorization: Bearer <API_KEY>.
401AUTH_API_KEY_INVALIDFix the request
The key is unknown, expired or malformed. Use a current Community API key.
403AUTH_PERMISSION_REQUIREDFix the request
The key lacks getUserData. Add Get User Data in Settings > Integration > API Keys.

Fix the data02

404Fix the data
detail says which: User not found (nothing matches the identifier; for id, send the platform user ID, not the internal record ID), User is not exists in this community (the trader isn't a member of your community; a trader created through Create User can also get this while Get User Data finds them, in which case contact Returning.AI support), or Referral program not found (check programId with Get referral programs).
409Fix the data
More than one trader has this custom field value (Duplicate users found for this custom field identifier.). Use id or email instead, and fix the duplicate values.

Retry with backoff04

503Retry with backoff
The custom field lookup isn't ready yet. Retry with backoff, or look the trader up by id or email.
502STORE_DEPENDENCY_UNAVAILABLERetry with backoff
Referral data is briefly unavailable. Retry the same request with exponential backoff.
500INTERNAL_ERRORRetry with backoff
The read failed unexpectedly. A 500 with message Get referral summary error. and no code means the same. Retry with exponential backoff.
401AUTH_API_KEY_VALIDATION_FAILEDRetry with backoff
The key could not be checked just now. Retry with backoff; the key itself may be fine.
{
  "meta": {
    "status": "error",
    "statusCode": 400,
    "code": "VALIDATION_FAILED"
  },
  "message": "Validation failed",
  "detail": {
    "identifier": "identifier should not be null or undefined"
  },
  "solution": "Please check the request and try again"
}

Next step#

Get referral programsGET/v1/referral/programsRead every stage's requirements and rewards, and the program completion bonus.