API reference / Contacts
Contact details
These routes change one contact at a time. Use them when your integration acts on a single person: tagging a lead your form qualified, logging a note from your CRM, reading what happened with them, scheduling a call-back, or handing the contact to a rep. To manage the tags themselves, see Tags. Follow-ups become Inbox Tasks when they're due.
Routes
| Method | Route | Scope | What it does |
|---|---|---|---|
POST |
/contact/public/contacts/{contact_id}/tags/{tag_id} |
contacts:write |
Add a tag to a contact |
DELETE |
/contact/public/contacts/{contact_id}/tags/{tag_id} |
contacts:write |
Remove a tag from a contact |
POST |
/contact/public/contacts/{contact_id}/notes |
contacts:write |
Add a note |
GET |
/contact/public/contacts/{contact_id}/notes |
contacts:read |
List a contact's notes |
GET |
/contact/public/contacts/{contact_id}/timeline |
contacts:read |
Get a contact's activity history |
GET |
/contact/public/contacts/{contact_id}/follow-ups |
contacts:read |
List a contact's follow-ups |
POST |
/contact/public/contacts/{contact_id}/follow-ups |
contacts:write |
Schedule a follow-up |
PUT |
/contact/public/follow-ups/{followup_id} |
contacts:write |
Change a follow-up |
DELETE |
/contact/public/follow-ups/{followup_id} |
contacts:write |
Cancel a follow-up |
PUT |
/contact/public/contacts/{contact_id}/owner |
contacts:write |
Assign an owner |
PUT |
/contact/public/contacts/{contact_id}/disposition |
contacts:write |
Set a disposition |
GET |
/contact/public/fields |
contacts:read |
List your custom fields |
Add a tag to a contact
Adds an existing tag to the contact. Get tag ids from List tags. Adding a tag the contact already has is safe.
curl -X POST "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/tags/fbd9fdcb-59ac-42ba-991e-3b469b9df791" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
The response lists the contact's tags after the change.
{
"data": [
{
"tag_id": "fbd9fdcb-59ac-42ba-991e-3b469b9df791",
"tagged_at": 1790870333466,
"tagged_by": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
"deleted_at": null,
"deleted_by": null
}
],
"meta": { "request_id": "35f86685-859f-4a8d-926a-45ec7fba7ddc" }
}
Remove a tag from a contact
Removes the tag from the contact. The tag itself still exists.
curl -X DELETE "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/tags/fbd9fdcb-59ac-42ba-991e-3b469b9df791" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
The response lists the tags the contact still has, which can be an empty array.
Add a note
Adds a note to the contact. note can contain basic HTML, which is sanitized. The note shows on the contact in the app.
| Field | Type | Required | Description |
|---|---|---|---|
note |
string | Yes | The note. Basic HTML is allowed. |
note_text |
string | No | Plain-text version. Built from note if you leave it out. |
curl -X POST "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/notes" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{ "note": "<p>Asked for a quote on the <b>annual</b> plan.</p>" }'
The response is 201 with the note.
{
"data": {
"note_id": "9782bc36-7d8f-413c-9a21-228562d0b10c",
"contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
"user_id": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
"type": "contact",
"note": "<p>Asked for a quote on the <b>annual</b> plan.</p>",
"note_text": "Asked for a quote on the annual plan.",
"attachments": [],
"created_at": 1790870333466,
"created_by": "d8ea4045-3e3c-45e6-b2ba-3917287c378c"
},
"meta": { "request_id": "22b934c0-e7e6-4f07-8608-e2bc91f06e39" }
}
New notes aren't pinned. Get a contact returns only pinned notes; to read them all, list the contact's notes.
List a contact's notes
Returns every note on the contact, pinned or not, newest first. Each note has the same fields as the one Add a note returns, plus username, the author's name.
curl "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/notes" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Get a contact's timeline
Returns the contact's activity, newest first: calls, texts, tag changes, consent changes, follow-ups and more. Each entry has a type, such as call, sms, tag_added, consent_granted, consent_revoked or followup.created.
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | No | Only entries of this type. |
limit |
integer | No | Page size, 1 to 100. Default 50. |
offset |
integer | No | Number of entries to skip. Default 0. |
curl "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/timeline?limit=50" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
"data": {
"entries": [
{
"entry_id": "aed010d0-8904-4539-bb15-6e0d2807154c",
"type": "tag_added",
"contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
"tag_id": "fbd9fdcb-59ac-42ba-991e-3b469b9df791",
"tag_label": "Hot lead",
"created_at": 1790870333466
}
],
"total": 1
},
"meta": { "request_id": "f5f9c5e4-158a-4e3c-89a6-a1574aad9e8d" }
}
total is the number of entries in this response, not in the whole timeline. The type filter is applied to each page after it's read, so a filtered page can come back short, or empty, while older entries of that type still exist. To collect every entry of one type, page without type until a page has fewer than limit entries, and filter yourself.
List a contact's follow-ups
Returns all of the contact's follow-ups, soonest first. Cancelled follow-ups are left out unless you ask for them with status. The route returns every match in one response.
| Field | Type | Required | Description |
|---|---|---|---|
status |
string | No | pending, triggered, completed or cancelled. |
curl "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/follow-ups?status=pending" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
"data": [
{
"followup_id": "a29a27a4-9b92-4696-bf96-ecc7fe7a5366",
"contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
"scheduled_at": 1791129600000,
"status": "pending",
"description": "<p>Call back about the annual plan</p>",
"description_text": "Call back about the annual plan",
"assigned_to": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
"assigned_type": "user",
"task_id": null,
"created_at": 1790870333466,
"created_by": "d8ea4045-3e3c-45e6-b2ba-3917287c378c"
}
],
"meta": { "request_id": "3b2f0314-e849-4799-9969-af93349bef75" }
}
Schedule a follow-up
Schedules a reminder to get back to the contact. When it's due, the follow-up becomes triggered and creates an Inbox Tasks task for whoever it's assigned to.
| Field | Type | Required | Description |
|---|---|---|---|
scheduled_at |
integer or string | Yes | When it's due. Epoch milliseconds, epoch seconds or an ISO 8601 string. Must be in the future. Returned as epoch milliseconds. |
description |
string | No | What to do. Basic HTML is allowed. |
assigned_to |
string | No | User id to assign it to. Defaults to you. |
assigned_type |
string | No | user (default) or team. |
curl -X POST "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/follow-ups" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{
"scheduled_at": "2026-10-04T15:00:00Z",
"description": "Call back about the annual plan",
"assigned_to": "75d223ec-db93-449b-8cd3-1b7da58e3477"
}'
The response is 201 with the follow-up, in the same shape as List a contact's follow-ups.
Change a follow-up
Changes when it's due, what it says, or who it's assigned to. Send only the fields you're changing. You can change pending follow-ups only. To close one, cancel it.
| Field | Type | Required | Description |
|---|---|---|---|
scheduled_at |
integer or string | No | New due time. Must be in the future. |
description |
string | No | New description. Send an empty string to clear it. |
assigned_to |
string | No | User id to assign it to. |
assigned_type |
string | No | user or team. |
curl -X PUT "https://api-v2.dropcowboy.com/contact/public/follow-ups/a29a27a4-9b92-4696-bf96-ecc7fe7a5366" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{ "scheduled_at": 1791216000000 }'
The response is the updated follow-up.
Cancel a follow-up
Cancels a pending follow-up so it never becomes a task.
curl -X DELETE "https://api-v2.dropcowboy.com/contact/public/follow-ups/a29a27a4-9b92-4696-bf96-ecc7fe7a5366" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
"data": {
"followup_id": "a29a27a4-9b92-4696-bf96-ecc7fe7a5366",
"cancelled": true,
"message": "Follow-up cancelled successfully"
},
"meta": { "request_id": "5292b8c9-4b2d-44c5-84b7-5dd37627aeb8" }
}
Assign an owner
Makes a user the contact's owner. Only the current owner or a manager can change the owner of a contact someone else owns.
| Field | Type | Required | Description |
|---|---|---|---|
owner_id |
string | Yes | User id of the new owner. |
curl -X PUT "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/owner" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{ "owner_id": "75d223ec-db93-449b-8cd3-1b7da58e3477" }'
The response is the updated contact, as in Update a contact.
Set a disposition
Records the outcome of your last conversation with the contact, such as "Interested" or "Call back". Get disposition ids from the dispositions route on Automation.
| Field | Type | Required | Description |
|---|---|---|---|
disposition_id |
string | Yes | Id of the disposition. |
curl -X PUT "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66/disposition" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
-H "Content-Type: application/json" \
-d '{ "disposition_id": "7eaad39b-476d-40f4-bc53-a9ea0c5b306d" }'
The response is the updated contact. Filter contacts by disposition with disposition on List contacts.
List custom fields
Returns your account's custom fields, newest first. Use custom_field_id when you create contacts with a custom_field column.
curl "https://api-v2.dropcowboy.com/contact/public/fields" \
-H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
"data": [
{
"custom_field_id": "34f38d24-632d-4a9c-bf89-b9371a722b35",
"type": "list",
"display_name": "Membership tier",
"slug": "membership_tier",
"list_items": [
{ "item_id": "e8e9cf83-3e9d-49d3-849e-eadf9f515863", "display_name": "Gold", "value": "gold" },
{ "item_id": "bcac033f-843f-41e6-bb7a-be87fe890c63", "display_name": "Silver", "value": "silver" }
],
"created_at": 1790870333466
}
],
"meta": { "request_id": "7d2ea476-c51d-4968-9cda-4d7701f922ac" }
}
type is string, text or list. For a list field, send an item's value or display_name when you create contacts. A value that matches no item is skipped.
Errors
On these routes, the type URL in an error doesn't tell errors apart. Branch on status.
| Status | When | What to do |
|---|---|---|
400 |
Adding a note without note. |
Send note. |
400 |
scheduled_at is missing, unreadable or in the past. |
Send a future time in epoch milliseconds or ISO 8601. |
400 |
assigned_type is something other than user or team. |
Use user or team. |
400 |
Setting a disposition without disposition_id. |
Send disposition_id as a string. |
403 |
Changing the owner of a contact someone else owns. | Ask the owner or a manager to reassign it. |
404 |
Contact not found or Tag not found: the contact or tag isn't on your account. Nothing changes. |
Check the ids with List contacts and List tags, or create the tag first. |
404 |
Removing a tag the contact doesn't have. Nothing changes. | Check the contact's tags with Get a contact first. |
404 |
The follow-up doesn't exist. | Check the followup_id with List a contact's follow-ups. |
409 |
Changing or cancelling a follow-up that isn't pending. | Leave it. It has already triggered, completed or been cancelled. |
For everything else, see Responses, errors and limits.