Returning.AIDevelopers
v1

API reference / User Fields / User Field History

.md

Update a user field value

Set, increase or decrease one trader's value for one user field, and record the change in that field's history.

Last updated 26 Sep 2026API v1

Method
POST
Path
https://api.returning.ai/v1/communities/{communityId}/users/{userId}/user-fields/{fieldIdOrName}/histories
Permission
userFields
Retries
Send an Idempotency-Key; reuse it to retry

When to use this

  • A trader's status changes on your platform, such as passing KYC, and your rewards community should know.
  • You sync a running metric, such as deposits or challenges purchased, by adding to it after each event.
  • You set the broker identifier for a trader who doesn't have one yet.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
userFieldsShown in the dashboard as “User Fields”

Use a Community API key with the userFields permission, and keep it on your server. communityId must be the ID of the community that owns the key.

Behaviour#

Each successful write adds one entry to the field's history and updates the trader's current value, which Get User Data returns when you list the key in customFields. Milestones, referral conditions and data workflows that use the field react after the response.

  • increase and decrease start from the trader's latest total for the field, or from 0 if they have none; the field's default is not used. Totals can go below zero.
  • Numerical writes to the same trader and custom field run one at a time. A write that waits more than 5 seconds returns 409 USER_FIELD_MUTATION_IN_PROGRESS and changes nothing.
  • The built-in total_xp and total_coins fields change the trader's XP or coin balance: overwrite sets it, increase and decrease adjust it.
  • If the field is your broker identifier field, each value can belong to one trader only, and once a trader has one it can only be replaced with Update User Data.

Request#

Path parameters#

communityId#stringREQUIRED
Your community's ID. It must be the community that owns your API key.

Rule24 hex characters

Eg"66f000000000000000000010"

userId#stringREQUIRED
The trader. Use the platform user ID, or their internal record ID, email or username. URL-encode an email.

RulePlatform user ID recommended

Eg"3247779"

fieldIdOrName#stringREQUIRED
The field key, or the definition's _id. Not the display name.

RuleField key or 24-character ID

Eg"kycstatus"

Headers#

Authorization#stringREQUIRED
Community API key with userFields.

RuleBearer <API_KEY>

Idempotency-Key#stringOPTIONAL
Optional, and strongly recommended. One value per logical change, such as your event ID plus the field key. Reuse it only to retry that exact request. Kept for 24 hours.

Rule1-200 chars; ^[!-~]{1,200}$

Eg"kyc-evt-1001-kycstatus"

Content-Type#stringREQUIRED
Request body format.

Ruleapplication/json

Body#

value must suit the field's type. Values are not converted between types except as listed:

  • single-line-text: a string of 1-255 characters with no line breaks.
  • multi-line-text: any string, including an empty one.
  • numerical: a number, or a string holding one, such as "12.5". The only type that takes increase and decrease.
  • boolean: true, false, "true", "false", 1 or 0.
  • date: YYYY-MM-DD.
  • time: HH:mm:ss, 24-hour.
  • date-time: YYYY-MM-DDTHH:mm:ss, optionally ending in Z or an offset such as +08:00. Milliseconds are rejected, so send 2026-09-26T08:30:00Z, not 2026-09-26T08:30:00.000Z.
  • single-select-dropdown and multi-select-dropdown: not supported yet.

false, 0 and an empty multi-line string are real values and are kept.

value#anyREQUIRED
The new value, or for increase and decrease the amount. Must suit the field's type; see Request body.

RuleMatches the field type

Eg"verified"

action#stringOPTIONAL
overwrite sets the value. increase and decrease add or subtract, on numerical fields only.

Ruleoverwrite, increase, decrease; default overwrite

Eg"overwrite"

curl --request POST \
  --url https://api.returning.ai/v1/communities/66f000000000000000000010/users/3247779/user-fields/kycstatus/histories \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: write-field-<unique-id>' \
  --data '{
    "value": "verified",
    "action": "overwrite"
  }'

Response#

A 201 means the value is saved. Branch on the HTTP status and meta.code, never on message. storedValue is the trader's value now; for numerical fields it is the new total, also in meta.sum.

meta#objectALWAYS

Eg{ ... }

status#stringALWAYS

Rulesuccess

statusCode#integerALWAYS

Rule201

code#stringALWAYS
Machine-readable result code.

RuleUSER_FIELD_VALUE_UPDATED

updated#booleanALWAYS
Always true.

Ruletrue

idempotencyPersistence#stringWHEN DEGRADED
degraded when the write was saved but a retry with the same key may not replay it. Treat the write as done; read it back before any other change.

Ruledegraded

idempotentReplay#booleanON REPLAY
true when this repeats the first response for your Idempotency-Key. Nothing new was written.

Ruletrue

sum#numberNUMERICAL FIELDS
The trader's new total. Numerical fields only.
message#stringALWAYS
Human-readable summary. Do not branch on it.

Eg"Update user field value api success."

data#objectALWAYS
The history entry this write created.

Eg{ ... }

_id#stringALWAYS
ID of the new history entry.

Rule^[0-9a-fA-F]{24}$

Eg"66f000000000000000000511"

communityID#stringALWAYS
Your community ID.

Rule^[0-9a-fA-F]{24}$

Eg"66f000000000000000000010"

userID#stringALWAYS
The trader's internal record ID.

Rule^[0-9a-fA-F]{24}$

Eg"<userObjectId>"

userNumericID#integerALWAYS
The trader's platform user ID, as a number here. Store it as a string.

Eg3247779

fieldID#stringALWAYS
The definition's _id.

Rule^[0-9a-fA-F]{24}$

Eg"66f000000000000000000510"

fieldName#stringALWAYS
The field key.

Eg"kycstatus"

fieldType#stringALWAYS
The field type.

Rulesingle-line-text, multi-line-text, numerical, date, time, date-time, boolean, single-select-dropdown, multi-select-dropdown

Eg"single-line-text"

value#anyALWAYS
The value or amount you sent.

Eg"verified"

storedValue#anyALWAYS
The trader's value after this write. For numerical fields, the new total.

Eg"verified"

updatedValue#anyALWAYS
Same as storedValue.

Eg"verified"

action#stringALWAYS
The action applied.

Ruleoverwrite, increase, decrease

Eg"overwrite"

createdAt#stringALWAYS
When the change was recorded.

RuleDate-time

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

updatedAt#stringALWAYS
When the entry last changed.

RuleDate-time

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

updated#booleanALWAYS
Always true.

Ruletrue

{
  "meta": {
    "status": "success",
    "statusCode": 201,
    "code": "USER_FIELD_VALUE_UPDATED",
    "updated": true
  },
  "message": "Update user field value api success.",
  "data": {
    "_id": "66f000000000000000000511",
    "communityID": "66f000000000000000000010",
    "userID": "<userObjectId>",
    "userNumericID": 3247779,
    "fieldID": "66f000000000000000000510",
    "fieldName": "kycstatus",
    "fieldType": "single-line-text",
    "value": "verified",
    "storedValue": "verified",
    "updatedValue": "verified",
    "action": "overwrite",
    "createdAt": "2026-09-26T08:30:00.000Z",
    "updatedAt": "2026-09-26T08:30:00.000Z",
    "updated": true
  }
}

Errors#

Every JSON error carries its code in meta.code. The exception is a request with no Authorization header and a JSON body: it returns 400 with a non-JSON body instead of 401. On a 500, meta.mutationState says what happened: rolled-back means nothing was kept, ambiguous means the write may have been kept.

Fix the request07

400Fix the request
No Authorization header was sent. With a JSON body this returns 400 with a non-JSON body (Request body must encrypted), not 401. Send Authorization: Bearer <API_KEY>.
400INVALID_FIELD_VALUEFix the request
value is missing or doesn't suit the field's type, or the field is a select-dropdown, which can't be written yet. Nothing was written. detail gives the reason.
400INVALID_FIELD_ACTIONFix the request
action isn't overwrite, increase or decrease, or you sent increase or decrease to a field that isn't numerical.
400INVALID_IDEMPOTENCY_KEYFix the request
The Idempotency-Key must be 1-200 visible ASCII characters with no spaces.
401AUTHENTICATION_REQUIREDFix the request
The key is invalid or expired, or no key was sent with an empty body. Send Authorization: Bearer <API_KEY> with a current Community API key.
403API_KEY_PERMISSION_DENIEDFix the request
The key lacks userFields. Add the permission in Settings > Integration > API Keys.
403API_KEY_COMMUNITY_MISMATCHFix the request
communityId is not the community that owns your key. Use your own community's ID.

Fix the data07

404USER_NOT_FOUNDFix the data
No active trader matches userId. Check it, or create the trader first. A 12-character username or email can't be matched; use the platform user ID.
404USER_FIELD_NOT_FOUNDFix the data
No field in your community has this key or ID. Check the key with List user field definitions.
403USER_NOT_IN_COMMUNITYFix the data
The trader exists but isn't a member of your community. Check the ID, or add them to the community first.
400USER_IDENTIFIER_UPDATE_REJECTEDFix the data
The field is your broker identifier field and this write broke its rules: only overwrite is allowed, the value can't be empty, and a trader's identifier can't be changed here once set (use Update User Data). Rarely it is a 500 after a failed save; nothing was kept, so send it again.
409USER_IDENTIFIER_CONFLICTFix the data
Another trader already has this identifier value. Nothing was written. Reconcile the two accounts first.
409IDEMPOTENCY_KEY_CONFLICTFix the data
This Idempotency-Key was used with a different trader, field, value or action. Use a new key for a new change.
404COMMUNITY_NOT_FOUNDFix the data
The community this key belongs to no longer exists. Contact Returning.AI support.

Retry with backoff04

409USER_FIELD_MUTATION_IN_PROGRESSRetry with backoff
Another numerical write for this trader and field didn't finish within 5 seconds. Nothing was written. Retry the same request, with the same key, after a short wait.
500USER_FIELD_VALUE_PROJECTION_FAILEDRetry with backoff
The write failed and was undone (meta.mutationState is rolled-back). Retry the same request, with the same key.
503IDEMPOTENCY_STORE_UNAVAILABLERetry with backoff
Nothing was written. Retry the same request, with the same key, after a short wait.
503USER_FIELD_MUTATION_LOCK_UNAVAILABLERetry with backoff
Nothing was written. Retry the same request, with the same key, after a short wait.

Do not retry03

409IDEMPOTENCY_REQUEST_IN_PROGRESSDo not retry
The first request with this key is still running, or its outcome is unclear. Read the field's history for this trader before doing anything else, and never switch to a new key for the same change.
500USER_FIELD_HISTORY_RECONCILIATION_REQUIREDDo not retry
The write may or may not have been kept (meta.mutationState is ambiguous). Read the field's history for this trader before any other change.
500USER_FIELD_HISTORY_INTERNAL_ERRORDo not retry
The write failed unexpectedly and may be partly done. Read the field's history, and for XP or coins the trader's balance, before you try again.
{
  "meta": {
    "status": "error",
    "statusCode": 400,
    "code": "INVALID_FIELD_VALUE",
    "fieldName": "kycstatus",
    "fieldType": "single-line-text"
  },
  "message": "Update user field value api error.",
  "detail": "This value can't be assigned as single-line-text type.",
  "solution": "Check the request fields and try again."
}

Next step#

Get a trader's field historyGET/v1/communities/{communityId}/users/{userId}/user-fields/{fieldIdOrName}/historiesRead this trader's history for the field to confirm the write.