Skip to content

Search the documentation by title, section, or page text.

Add Custom Attributes

POST https://api.botsi.com/v2/custom-attributes

Custom attributes enrich a Profile with metadata. Provide as much as possible for better results with Botsi AI Pricing Models.

Request body#

ParameterTypeRequiredDescription
profileIdstringRequiredBotsi profile ID from Create a Profile
customarrayRequiredAttribute objects. Must contain at least one
custom[].keystringRequiredThe attribute key
custom[].valuestringRequiredThe attribute value
curl -X POST "https://api.botsi.com/v2/custom-attributes" \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
    "custom": [
      { "key": "user_level", "value": "premium" },
      { "key": "subscription_type", "value": "annual" },
      { "key": "referral_source", "value": "facebook" }
    ]
  }'

Multi-select answers#

Send one attribute per option shown.

Set key to <question>.<option>, for example goal.level_up_my_life. Both parts are short identifiers you choose: lowercase letters, digits, and underscores, with no spaces. Use dot notation to separate the question from the option. Keep the whole key under 120 characters.

Choose key identifiers and keep those consistent. If an option's wording changes but its meaning does not, keep its identifier.

Set value to "true" if the user picked the option, and "false" if it was shown but not picked. Send strings, not booleans.

Send every option that was shown, in one request. Leave out options the user never saw. POST creates that key or replaces its value.

If the user changes their answers, send every option for that question again. Options you do not resend keep their previous value.

{
  "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
  "custom": [
    { "key": "goal.level_up_my_life", "value": "true" },
    { "key": "goal.turn_vision_into_action", "value": "false" },
    { "key": "goal.get_clarity", "value": "true" },
    { "key": "goal.see_if_right_for_me", "value": "true" },
    { "key": "user_level", "value": "premium" }
  ]
}

The response has the same shape as the Response example: {"ok": true, "data": [...]}, with one { id, key, value } entry per key sent. id is assigned by the server.

{
  "ok": true,
  "data": [
    { "id": "abc123", "key": "goal.level_up_my_life", "value": "true" },
    { "id": "def456", "key": "goal.turn_vision_into_action", "value": "false" },
    { "id": "ghi789", "key": "goal.get_clarity", "value": "true" },
    { "id": "jkl012", "key": "goal.see_if_right_for_me", "value": "true" },
    { "id": "mno345", "key": "user_level", "value": "premium" }
  ]
}

Don't repeat a key

A repeated key keeps only its last value, with no error, and the response lists that key once. Earlier values in the request are lost. Only see_if_right_for_me is saved:

"custom": [
  { "key": "goal", "value": "level_up_my_life" },
  { "key": "goal", "value": "see_if_right_for_me" }
]

Errors#

CodeMessageCause
400custom must contain at least 1 elementsThe custom array was empty
400custom.0.value must be a stringA value was not a string, for example a JSON boolean or an array. The number is the item's position in custom.
400custom.0.key must be a stringA key was missing or misspelled, for example "Key" instead of "key". The number is the item's position in custom.
404No profile found by id: 0072102a-c00c-4ea5-9271-1b6e975f2d63No Profile exists for that profileId

Response#

{
  "ok": true,
  "data": [
    { "id": "abc123", "key": "user_level", "value": "premium" },
    { "id": "def456", "key": "subscription_type", "value": "annual" },
    { "id": "ghi789", "key": "referral_source", "value": "facebook" }
  ]
}