Update a Profile
PATCH https://api.botsi.com/v2/profiles/{profileId}Update a Profile's details after it's created. For example, call it when the user signs in and you learn their email, or after an app or OS update, resending os, appVersion, and device. AI Pricing reads the Profile's os and device, so keep them current.
This route accepts $BOTSI_SECRET_KEY or $BOTSI_PUBLIC_KEY in the Authorization header, with no Bearer prefix. The sample sends the secret key. From inside the app, send the public key. Delete a Profile is the exception and accepts the secret key only. See Authentication.
Sending a partial update#
Every field is optional. What you send for a field decides what happens to it:
device, os, appVersion, and country can be changed but not cleared
Sending null or an empty string for any of them returns 400. Omit the field to leave it as it is.
Path parameters#
Request body#
# Authorization: $BOTSI_SECRET_KEY or $BOTSI_PUBLIC_KEY
curl -X PATCH "https://api.botsi.com/v2/profiles/fff3c120-0ca8-480f-9b19-3955a5428e39" \
-H "Authorization: $BOTSI_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "ada@example.com",
"os": "iOS 26.5",
"appVersion": "2.0.0",
"appBuild": "412",
"phone": null
}'Fields this endpoint doesn't change#
These fields are dropped without an error
Sending them returns 200 with the field unchanged, so a request that looks successful can leave the Profile exactly as it was.
Any other field Botsi doesn't recognize is dropped the same way.
Response#
The response is the updated Profile in the same shape as Get a Profile, custom included. It isn't a bare { "ok": true }.
That shape carries the Profile's access and custom attributes, not the details you sent, so email and os don't come back. A 200 confirms the write.
{
"ok": true,
"data": {
"profileId": "fff3c120-0ca8-480f-9b19-3955a5428e39",
"appUserId": "user-123",
"state": "never-subscribed",
"totalRevenueUsd": 0,
"accessLevels": {},
"subscriptions": {},
"nonSubscriptions": {},
"custom": [
{ "id": "Kj3xQz9a", "key": "user_level", "value": "vip" }
]
}
}Errors#
A 400 lists every validation failure in error, separated by commas.