Returning.AIDevelopers
v1

API reference / Users

.md

Update User XP and Currency

Add to, subtract from or set one trader's XP, coin balance or both, and get back the new balances.

Last updated 26 Sep 2026API v1

Method
POST
Path
https://api.returning.ai/v1/users/update-xp-currency
Permission
manageUser
Retries
No Idempotency-Key; read back before retrying

When to use this

  • Credit coins or XP for something your platform tracks, such as a funded account or a completed course.
  • Correct a trader's balance after a support case.
  • Set a balance to an exact figure with overwrite, for example when you migrate from another loyalty system.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
manageUserShown in the dashboard as “Delete/Restore User”

This endpoint needs manageUser, the permission shown in the dashboard as Delete/Restore User. The key limits every change to traders in its own community. Keep it on your server.

Behaviour#

Each change is saved to the trader's XP or coin history, and the response returns the new balance. overwrite sets the balance to exactly value, and later changes count from there. subtract has no floor, so it can take a balance below zero. A coin earning cap set for your community does not limit changes made here.

When you send both xp and currency, XP is saved first and coins second. If the request fails in between, the XP change stays.

Request#

Headers#

Authorization#stringREQUIRED
Community API key with manageUser.

RuleBearer <API_KEY>

Content-Type#stringREQUIRED
Request body format.

Ruleapplication/json

Body#

Send identifier and at least one of xp or currency. The two can use different actions. Values are JSON numbers of 0 or more; subtract a positive number to lower a balance.

identifier#objectREQUIRED
Selects the trader to change.

Eg{"type": "platform_user_id", "value": "3247779"}

type#stringREQUIRED
How value identifies the trader. custom_user_identifier uses your community's active identifier field, usually the broker customer ID.

Ruleplatform_user_id, username, email, custom_user_identifier

Eg"platform_user_id"

value#string | numberREQUIRED
The identifier value to match. Emails and usernames are not case-sensitive.

RuleNon-empty string, or a number

Eg"3247779"

xp#objectOPTIONAL
The XP change. Send xp, currency or both.

RuleSend xp, currency or both

Eg{"action": "add", "value": 100}

action#stringREQUIRED
add and subtract change the balance by value. overwrite sets the balance to exactly value.

Ruleadd, subtract, overwrite

Eg"add"

value#numberREQUIRED
The amount. Send a JSON number, not a string.

RuleNumber, 0 or more

Eg100

currency#objectOPTIONAL
The coin change. Send xp, currency or both.

RuleSend xp, currency or both

Eg{"action": "add", "value": 500}

action#stringREQUIRED
add and subtract change the balance by value. overwrite sets the balance to exactly value.

Ruleadd, subtract, overwrite

Eg"add"

value#numberREQUIRED
The number of coins. Send a JSON number, not a string.

RuleNumber, 0 or more

Eg500

curl --request POST \
  --url https://api.returning.ai/v1/users/update-xp-currency \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "identifier": {
      "type": "platform_user_id",
      "value": "3247779"
    },
    "xp": {
      "action": "add",
      "value": 100
    },
    "currency": {
      "action": "add",
      "value": 500
    }
  }'

Response#

A 200 means every change you sent is saved. data.xp and data.currency are the balances after the change, and each is present only when you sent it. Branch on the HTTP status and code, never on message.

status#stringALWAYS
Result of the request.

Rulesuccess

code#stringALWAYS
Machine-readable result code.

RuleUSER_XP_CURRENCY_UPDATED

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

Eg"User XP and currency updated successfully"

data#objectALWAYS
The trader's new balances.

Eg{"userId": 3247779, "xp": 100, "currency": 500}

userId#integerALWAYS
Platform user ID. This endpoint returns it as a number; store it as a string.

RuleInteger

Eg3247779

xp#numberWHEN xp SENT
The trader's XP balance after the change.

Eg100

currency#numberWHEN currency SENT
The trader's coin balance after the change. Get User Data calls the same balance coins.

Eg500

{
  "status": "success",
  "code": "USER_XP_CURRENCY_UPDATED",
  "message": "User XP and currency updated successfully",
  "data": {
    "userId": 3247779,
    "xp": 100,
    "currency": 500
  }
}

Errors#

Errors from the API key check, such as 401 and 403, carry the code in meta.code; other JSON errors carry it in code. A validation 400 has no code; its detail names each invalid field. Two malformed bodies return an HTML 500 instead of JSON, as listed below.

Fix the request04

400Fix the request
A field is missing or invalid, such as an unknown identifier.type, an action other than add, subtract or overwrite, a negative value, or a number sent as a string. detail names the field. Nothing was written.
500Fix the request
The body has neither xp nor currency, or has a top-level field this endpoint does not accept (such as updates). The response is an HTML error page, not JSON. Nothing was written; fix the body.
401AUTHENTICATION_REQUIREDFix the request
The key is missing, invalid or expired. Send Authorization: Bearer <API_KEY> with a current key.
403API_KEY_PERMISSION_DENIEDFix the request
The key is valid but lacks manageUser. Add the permission in Settings > Integration > API Keys.

Fix the data03

404USER_NOT_FOUNDFix the data
No trader in your community matches the identifier. Check the type and value.
400ACTIVE_IDENTIFIER_NOT_CONFIGUREDFix the data
You sent custom_user_identifier, but your community has no single active identifier field. Use the platform user ID, email or username instead.
404COMMUNITY_NOT_FOUNDFix the data
The key's community no longer exists. Use a key from an active community.

Retry with backoff02

500USER_XP_CURRENCY_UPDATE_FAILEDRetry with backoff
The update failed unexpectedly, or a custom_user_identifier lookup was not ready or matched more than one trader. If you sent both balances, XP may already be saved. Read the balances with Get User Data before you retry.
500AUTHENTICATION_FAILEDRetry with backoff
The key could not be checked. Retry the same request with backoff.
{
  "meta": {
    "status": "error",
    "statusCode": 400
  },
  "message": "Update user gamification endpoint validation error.",
  "detail": {
    "currency": {
      "value": "Number must be greater than or equal to 0"
    }
  },
  "solution": "Check your body in request and try again"
}

Next step#

Get User DataPOST/v1/users/infoRead back the trader's XP and coins. The coin balance is called coins there.