Returning.AIDevelopers
v1

API reference / Users

.md

Create User

Register one trader in the community that owns your API key, and store their broker customer ID in the same call.

Last updated 26 Sep 2026API v1

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

When to use this

  • A trader signs up on your platform and needs a loyalty account straight away.
  • You sign traders in with your own login (OAuth or single sign-on), so they never get a separate password.
  • You want the broker customer ID attached from the start, so activity data matches the right trader.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
createUserShown in the dashboard as “Create User”

The API key decides which community the trader joins, so never send a communityId. Keep the key on your server, and never place an API key, broker credential or login token in customFields.

Request#

Headers#

Authorization#stringREQUIRED
Community API key with createUser.

RuleBearer <API_KEY>

Content-Type#stringREQUIRED
Request body format.

Ruleapplication/json

Body#

Required fields are firstname, lastname, username and accessLevel. For traders who sign in through your platform, omit password and confirmPassword and set joinServer to true.

firstname#stringREQUIRED
The trader's first name, or a placeholder such as Trader.

Rule1-64 chars

Eg"Sample"

lastname#stringREQUIRED
The trader's last name, or a placeholder such as your customer ID.

Rule1-64 chars

Eg"Trader"

username#stringREQUIRED
Unique username. Letters, numbers, underscores and periods; cannot start or end with _ or .; no @.

Rule2-32 chars; ^[a-zA-Z0-9][a-zA-Z0-9._]*[a-zA-Z0-9]$

Eg"sample_trader"

displayname#stringOPTIONAL
Public display name. Defaults to username.

RuleMax 50 chars

Eg"Sample Trader"

email#stringOPTIONAL
The trader's email. Optional; leave it out to run without personal data.

RuleEmail format

Eg"trader@example.com"

accessLevel#integerREQUIRED
Access level. Most broker-created traders use 1.

Rule0-99999

Eg1

joinServer#booleanOPTIONAL
Make the trader a full community member immediately. Use true for traders who sign in through your platform.

RuleDefault false

Egtrue

password#stringOPTIONAL
Local-password accounts only. Omit for traders who sign in through your platform. Never returned.

Rule8-20 chars, one number, one special character, no spaces, not equal to username

Eg"StrongPass1!"

confirmPassword#stringOPTIONAL
Required with password and must match it.

RuleMust equal password

Eg"StrongPass1!"

sendEmail#booleanOPTIONAL
Send the create-account email. Use false for traders who sign in through your platform.

RuleDefault false

Egfalse

emailPassword#booleanOPTIONAL
Include the password in that email. Use false for traders who sign in through your platform.

RuleDefault false

Egfalse

emailTemplate#stringOPTIONAL
Email template to use when sendEmail is true.

Eg"0"

phoneNumber#stringOPTIONAL
Phone number, digits only.

Rule^\d+$

Eg"080374893013"

country#stringOPTIONAL
Country name from the supported country list.

RuleSupported country name

Eg"Thailand"

customFields#object[]OPTIONAL
Custom field values to write at creation. Use it for the broker customer ID when externalId is not configured.

Eg[{"fieldIdorName": "customerid", "value": "<brokerCustomerId>"}]

fieldIdorName#stringREQUIRED
Field key or ID. Preferred spelling on this endpoint. Required, as this or its alias fieldIdOrName.

RuleSend this or fieldIdOrName

Eg"customerid"

fieldIdOrName#stringOPTIONAL
Accepted alias for fieldIdorName.

RuleAlias; send one of the two

Eg"customerid"

value#string | number | booleanREQUIRED
The value. false, 0 and an empty multi-line string are kept.

RuleMatches the field's type

Eg"<brokerCustomerId>"

externalId#stringOPTIONAL
Shortcut for your community's active identifier field, usually the broker customer ID.

RuleNeeds an active identifier field

Eg"<brokerCustomerId>"

referral#stringOPTIONAL
Referrer's referral value, matched against your referral mapping.

Eg"<referrerReferralValue>"

curl --request POST \
  --url https://api.returning.ai/v1/users \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "firstname": "Sample",
    "lastname": "Trader",
    "username": "sample_trader",
    "displayname": "Sample Trader",
    "email": "trader@example.com",
    "accessLevel": 1,
    "joinServer": true,
    "sendEmail": false,
    "emailPassword": false,
    "externalId": "<brokerCustomerId>"
  }'

Response#

A 200 means the trader and their community membership are saved. Save data.userId, then confirm the trader with Get User Data. Email, referral tracking and analytics follow after the response and never turn a saved trader into an error.

status#stringALWAYS
Result of the request.

Rulesuccess

code#stringALWAYS
Machine-readable result code.

RuleUSER_CREATED

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

Eg"User created successfully"

data#objectALWAYS
The created trader.

Eg{ ... }

userId#stringALWAYS
Platform user ID. Use it for follow-up reads; never do arithmetic on it.

RuleDecimal digits

Eg"3247779"

username#stringALWAYS
The stored username.

Eg"sample_trader"

email#stringALWAYS
The stored email.

RuleEmail format

Eg"trader@example.com"

communityMemberId#stringALWAYS
ID of the community membership record created for this trader.

Eg"66f000000000000000000001"

identifierKey#stringWHEN CONFIGURED
The active identifier field key used for this request.

Eg"customerid"

externalId#stringWHEN CONFIGURED
The stored broker identifier.

Eg"<brokerCustomerId>"

created#booleanALWAYS
true when a new trader was saved.

Egtrue

{
  "status": "success",
  "code": "USER_CREATED",
  "message": "User created successfully",
  "data": {
    "userId": "3247779",
    "username": "sample_trader",
    "email": "trader@example.com",
    "communityMemberId": "66f000000000000000000001",
    "identifierKey": "customerid",
    "externalId": "<brokerCustomerId>",
    "created": true
  }
}

Errors#

401 and 403 responses carry the code in meta.code. A body that fails validation returns 400 with a detail object naming each field, and no code or data. Every other error carries its code in code, and for coded 400 and 409 errors data.created is false. No 400 or 409 saves a trader.

Fix the request08

400Fix the request
A field is missing or breaks its rule, such as a missing accessLevel or a username with a character other than letters, numbers, _ and .. There is no code or data; detail names each field. Nothing was saved.
400PASSWORD_MISMATCHFix the request
password and confirmPassword differ. Send matching values.
400PASSWORD_MATCHES_USERNAMEFix the request
The password equals the username. Choose a different password.
400EXTERNAL_IDENTIFIER_REQUIREDFix the request
Your community expects an identifier. Send externalId or the identifier in customFields.
400EXTERNAL_IDENTIFIER_CONFLICTFix the request
externalId and the identifier in customFields disagree. Send one value.
400INVALID_CUSTOM_FIELDSFix the request
A custom field name or value failed validation. Check errorFields, and keep valid false, 0 and empty values.
401AUTHENTICATION_REQUIREDFix the request
The key is missing or invalid. Send Authorization: Bearer <API_KEY> with a current key.
403API_KEY_PERMISSION_DENIEDFix the request
The key lacks createUser. Add the permission in Settings > Integration > API Keys.

Fix the data04

400DUPLICATE_EMAILFix the data
The email already belongs to a trader. Look them up with Get User Data instead of creating again.
400DUPLICATE_USERNAMEFix the data
The username is taken. Choose another username, or look up the existing trader.
409DUPLICATE_EXTERNAL_IDFix the data
Another trader already has this identifier. Look up that trader instead of creating another.
400EXTERNAL_IDENTIFIER_NOT_CONFIGUREDFix the data
Your community has no active identifier field. Send the value in customFields, or set up the field first.

Retry with backoff01

500USER_CREATE_FAILEDRetry with backoff
Creation failed unexpectedly. Check with Get User Data before you try again.

Do not retry01

500USER_CREATION_RECONCILIATION_REQUIREDDo not retry
The outcome is unclear. Stop automatic retries and reconcile using data.userId and your identifier.
{
  "status": "fail",
  "code": "DUPLICATE_EMAIL",
  "message": "Email already exists",
  "data": {
    "created": false
  }
}

Next step#

Update User DataPOST/v1/users/updateChange a trader's profile or roles, or replace their identifier. Needs manageUser, plus bulkUpdateUser for role changes.