/v1/contacts/{id}
Changes the fields you send and leaves the rest. tags and custom_fields replace the whole list or set. The handle can’t change, since the contact’s texts are filed under it. Use the stop list operations to stop or start texting somebody.
Needs a key with the contacts:write scope.
Path parameters
idstringrequiredThe contact’s id.
Starts with
ct_.
Request body
first_namestring or nullThe first name. Send null or an empty string to clear it.
Up to 100 characters.
last_namestring or nullThe last name. Send null or an empty string to clear it.
Up to 100 characters.
companystring or nullThe company. Send null or an empty string to clear it.
Up to 200 characters.
tagsarray of stringsTags, at most 50 of up to 50 characters each. Capitals are kept but a tag counts once however it is spelled.
Up to 50 items.
custom_fieldsmap of stringYour own fields for templates, at most 50. Names are made template-safe (
Showing addressbecomesshowing_address); an empty value drops the field.
Example
/v1/contacts/ct_1Hq2LxW9cVbN3mKpRtYs0acurl -X PATCH "https://usebluebot.com/api/v1/contacts/ct_1Hq2LxW9cVbN3mKpRtYs0a" \
-H "Authorization: Bearer $BLUEBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tags": [
"buyer",
"closed"
],
"custom_fields": {
"showing": "412 Oak St",
"closing": "Dec 3"
}
}'Response
200: The contact after the change.
idstringrequiredA ct_ id.
Starts with
ct_.object"contact"requiredhandlestringrequiredA phone number in E.164 (
+15555550123) or an email address an Apple ID uses (iMessage only).kindstringrequiredphoneoremail.One of
phone,email.first_namestring or nullrequiredlast_namestring or nullrequiredcompanystring or nullrequiredtagsarray of stringsrequiredThe contact’s tags.
custom_fieldsmap of stringrequiredYour own fields, for templates.
stoppedbooleanrequiredTrue when the person is on your stop list. Texts to them are canceled.
stopped_attimestamp or nullrequiredWhen they were put on the stop list.
stop_sourcestring or nullrequiredHow:
reply(they texted a stop word),dashboard,api,importoradmin.One of
reply,dashboard,api,import,admin.last_servicestring or nullrequiredThe service of the newest text with them.
One of
imessage,sms.first_message_attimestamp or nullrequiredThe first text either way. Null for somebody you have never texted with, who counts as a new person.
last_message_attimestamp or nullrequiredThe newest text either way.
created_viastringrequiredWhat first added them.
One of
message,inbound,import,api,dashboard,widget,hook,mcp,assistant.created_attimestamprequiredWhen the contact was added.
{
"id": "ct_1Hq2LxW9cVbN3mKpRtYs0a",
"object": "contact",
"handle": "+15555550123",
"kind": "phone",
"first_name": "Maria",
"last_name": "Alvarez",
"company": null,
"tags": [
"buyer",
"closed"
],
"custom_fields": {
"showing": "412 Oak St",
"closing": "Dec 3"
},
"stopped": false,
"stopped_at": null,
"stop_source": null,
"last_service": "imessage",
"first_message_at": "2026-11-02T15:20:00.000Z",
"last_message_at": "2026-11-13T19:41:00.000Z",
"created_via": "message",
"created_at": "2026-11-02T15:20:00.000Z"
}Errors
Every refusal has the same envelope and a page of its own. These are the ones this operation can give.
| Code | Status | What it means |
|---|---|---|
| 401 | The request carried no key, or a key BlueBot doesn’t know: mistyped, revoked, or a test key sent to the live API. | |
| 403 | The key doesn’t carry the scope the endpoint needs. Each endpoint’s reference names its scope. | |
| 429 | Too many requests. A key may make 120 requests a minute. The RateLimit header says how many are left, and Retry-After how long to wait. | |
| 500 | Something went wrong on BlueBot’s side. It was reported. Send the request again; with an Idempotency-Key that is always safe. | |
| 400 | Something in the request doesn’t fit: a missing or malformed field, a bad id, or a combination the endpoint refuses. details names each field. | |
| 404 | There is no such thing on this account. Ids are prefixed by kind, so a message id starts with msg_. |
Try it
Call this operation from the page with your own key. The key stays in this tab and is forgotten when you leave.