Contacts

A contact is one person, with their phone numbers, email, custom field values, lists and tags. You create contacts before you add them to lists for campaigns. You look them up to check their consent and do-not-contact status before you send. Tags, notes, activity history, follow-ups, owners and dispositions for a single contact are on Contact details.

Routes

Method Route Scope What it does
GET /contact/public/contacts contacts:read List contacts, with filters
GET /contact/public/contacts/search contacts:read Find contacts by phone number or email
POST /contact/public/contacts contacts:write Create contacts, or update the ones that already exist
GET /contact/public/contacts/{contact_id} contacts:read Get one contact in full
PUT /contact/public/contacts/{contact_id} contacts:write Update a contact's field values
DELETE /contact/public/contacts/{contact_id} contacts:write Delete a contact

List contacts

Returns a page of contacts. Page with offset and limit, and stop when you've read total_contacts. Pass sort_by when you page, so the order stays the same from page to page.

Field Type Required Description
list_id string No Only contacts on this list.
search_term string No Free-text search across field values, such as a name, phone number or email.
disposition string No Only contacts with this disposition id. none returns contacts without one.
owner string No Only contacts owned by this user id.
brand_id string No Only contacts of this brand. Without it you get every brand.
sort_by string No modified_at, created_at, last_activity, last_called_at or first_name.
sort_order string No asc or desc.
limit integer No Page size. Default 25.
offset integer No Number of contacts to skip. Default 0.
curl "https://api-v2.dropcowboy.com/contact/public/contacts?list_id=3b2f0314-e849-4799-9969-af93349bef75&sort_by=created_at&limit=25&offset=0" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
  "data": {
    "contacts": [
      {
        "contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
        "first_name": "Dana",
        "last_name": "Reyes",
        "email": "dana@example.com",
        "main_phone": "+13125550142",
        "phone_numbers": ["+13125550142"],
        "list_ids": ["3b2f0314-e849-4799-9969-af93349bef75"],
        "tags": [
          {
            "tag_id": "fbd9fdcb-59ac-42ba-991e-3b469b9df791",
            "tagged_at": 1790870333466,
            "tagged_by": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
            "deleted_at": null,
            "deleted_by": null
          }
        ],
        "owner": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
        "dnc": false,
        "email_dnc": false,
        "has_tcpa_consent": true,
        "created_at": 1790870333466,
        "modified_at": 1790870333466
      }
    ],
    "total_contacts": 1,
    "next_cursor": null
  },
  "meta": { "request_id": "35f86685-859f-4a8d-926a-45ec7fba7ddc" }
}

Each contact also carries its standard field values flattened by type, such as company or city, plus disposition, location and activity summaries (call_info, message_info, email_info). The sample leaves those out.

Search contacts

Finds contacts with an exact phone number or email. Use it to look someone up before you create them or send to them. Send the phone number in E.164 format, URL-encoded (%2B13125550142). Emails match without regard to case.

Field Type Required Description
phone string One of phone or email Phone number in E.164 format.
email string One of phone or email Email address.
brand_id string No Only contacts of this brand.
limit integer No Page size. Default 25.
offset integer No Number of contacts to skip. Default 0.
curl "https://api-v2.dropcowboy.com/contact/public/contacts/search?phone=%2B13125550142" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

The response has the same shape as List contacts. No match returns an empty contacts array.

Create contacts

Creates one or more contacts in a single call. You describe your columns once in fields, then send one row per contact in values. A row that matches an existing contact by record_id, email or phone number updates that contact instead, following conflict_mode.

By default this route doesn't send webhooks or start automations. Set fire_webhook_events or fire_automation_events if you want them.

Field Type Required Description
fields array Yes One mapping per column, such as { "type": "first_name" }. For a custom field use { "type": "custom_field", "field_id": "<custom_field_id>" }.
values array Yes One array per contact, with values in the same order as fields.
add_list_ids array No List ids to add every contact in this call to.
add_tag_ids array No Tag ids to add to every contact in this call.
conflict_mode string No How to treat a row that matches an existing contact. append (default) keeps existing values and only fills empty fields. overwrite replaces the values of the fields you send and leaves the rest alone. replace makes the row's values win and keeps existing values only where the row has none.
owner string No User id that owns the contacts.
region string No Two-letter country code for reading phone numbers that don't start with +. Default US.
return_counts boolean No Return totals instead of per-row results. Use it for large batches.
fire_webhook_events boolean No Send contact.created, contact.updated and list webhooks. Default false.
fire_automation_events boolean No Start automations triggered by these contacts. Default false.

Common field types: first_name, last_name, email, main_phone, mobile_phone, home_phone, office_phone, other_phone, company, website, address, city, state, zip_code, country, record_id, lead_source, tcpa_consent, tcpa_consent_date and custom_field. Get your custom field ids from List custom fields.

Every row needs a record_id, an email or a phone number. Rows without one are rejected.

curl -X POST "https://api-v2.dropcowboy.com/contact/public/contacts" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      { "type": "first_name" },
      { "type": "last_name" },
      { "type": "main_phone" },
      { "type": "email" },
      { "type": "custom_field", "field_id": "34f38d24-632d-4a9c-bf89-b9371a722b35" }
    ],
    "values": [
      ["Dana", "Reyes", "+13125550142", "dana@example.com", "Gold"],
      ["Sam", "Okafor", "+13125550187", "", "Silver"]
    ],
    "add_list_ids": ["3b2f0314-e849-4799-9969-af93349bef75"],
    "conflict_mode": "append"
  }'

The response is 201. index is the row's position in values.

{
  "data": {
    "inserted": [
      { "index": 1, "contact_id": "22b934c0-e7e6-4f07-8608-e2bc91f06e39" }
    ],
    "updated": [
      { "index": 0, "contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66" }
    ],
    "rejected": []
  },
  "meta": { "request_id": "8e42bc36-efeb-42c1-b99b-41ae9c60aa66" }
}

With return_counts: true, data is { "accepted_count", "rejected_count", "inserted_count", "updated_count" }.

Get a contact

Returns everything about one contact: field values, phone numbers, lists, tags, pinned notes, consent and do-not-contact flags. Read the consent flags here before you choose a channel. Consent explains each one.

curl "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
{
  "data": {
    "status": 200,
    "contact": {
      "contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
      "first_name": "Dana",
      "last_name": "Reyes",
      "email": "dana@example.com",
      "main_phone": "+13125550142",
      "field_data": [
        {
          "field_id": "8e42bc36-efeb-42c1-b99b-41ae9c60aa66",
          "type": "first_name",
          "display_name": "First Name",
          "value": "Dana"
        },
        {
          "field_id": "c99a62ba-d867-42e7-8814-c718d2254493",
          "type": "main_phone",
          "display_name": "Main Phone",
          "value": "+13125550142"
        }
      ],
      "phone_numbers": ["+13125550142"],
      "list_ids": ["3b2f0314-e849-4799-9969-af93349bef75"],
      "tags": [],
      "notes": [],
      "owner": "d8ea4045-3e3c-45e6-b2ba-3917287c378c",
      "dnc": false,
      "email_dnc": false,
      "has_tcpa_consent": true,
      "tcpa_opted_out_at": null,
      "has_sms_consent": true,
      "sms_opted_out_at": null,
      "has_email_consent": false,
      "email_opted_out_at": null,
      "created_at": 1790870333466
    }
  },
  "meta": { "request_id": "c99a62ba-d867-42e7-8814-c718d2254493" }
}

The contact is in data.contact. If no contact has that id, the response is still 200 and data.contact is null, so check for it.

field_data holds every field value with its field_id. You need those ids to update a contact. notes holds only the notes pinned to the contact.

Update a contact

Changes a contact's field values. Send a contact object with the field_data entries you want to change. Each entry needs the field_id from Get a contact and the new value. To add a field the contact doesn't have yet, send a new UUID as its field_id.

Top-level fields such as first_name don't change the contact's values. Change them in field_data. Use the dedicated routes for lists, tags, the owner and the disposition.

Field Type Required Description
contact.field_data array Yes Entries of { "field_id", "type", "value" }.
curl -X PUT "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "contact": {
      "field_data": [
        { "field_id": "8e42bc36-efeb-42c1-b99b-41ae9c60aa66", "type": "first_name", "value": "Danielle" }
      ]
    }
  }'

The response is the updated contact as stored, with its full field_data.

{
  "data": {
    "contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
    "field_data": [
      {
        "field_id": "8e42bc36-efeb-42c1-b99b-41ae9c60aa66",
        "type": "first_name",
        "display_name": "First Name",
        "value": "Danielle"
      }
    ],
    "phone_numbers": ["+13125550142"],
    "list_ids": ["3b2f0314-e849-4799-9969-af93349bef75"],
    "modified_at": 1790870396012
  },
  "meta": { "request_id": "34f38d24-632d-4a9c-bf89-b9371a722b35" }
}

The sample is shortened. The full response includes every stored field of the contact.

Delete a contact

Deletes a contact. It no longer appears when you list, search or get contacts.

curl -X DELETE "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

The response is the deleted contact with deleted_at and deleted_by set.

{
  "data": {
    "contact_id": "756c1b7d-c27d-4faf-9365-bb83f0cbed66",
    "deleted_at": 1790870421733,
    "deleted_by": "d8ea4045-3e3c-45e6-b2ba-3917287c378c"
  },
  "meta": { "request_id": "9782bc36-7d8f-413c-9a21-228562d0b10c" }
}

The sample is shortened.

Errors

On these routes, the type URL in an error doesn't tell errors apart. Branch on status.

Status When What to do
400 Search without phone or email. Send one of them.
400 Create without fields and values, or the batch can't be read. Check that every row has one value per entry in fields.
400 Update fails validation. Check each field_data value against its type, for example a valid email for email.
402 Create while your subscription is inactive. See Payment required.
403 Update changes the owner of a contact someone else owns. Only the current owner or a manager can reassign it.
404 Update or delete a contact that doesn't exist or that you can't see. Check the contact_id. Contacts owned by others may be hidden from your user.

A row in rejected isn't an error for the whole call. Read its reasons, fix the row and send it again on its own.

For everything else, see Responses, errors and limits.


While Drop Cowboy provides tools to support compliance efforts, customers remain solely responsible for obtaining proper consent, maintaining opt-out lists, and complying with all federal and state telemarketing regulations. Consult with your legal counsel to ensure your specific use case and consent mechanisms comply with applicable laws.

Code samples

The requests from this page, ready to copy. Set DC_KEY and DC_SECRET to your API key pair first.

List contacts
curl "https://api-v2.dropcowboy.com/contact/public/contacts?list_id=3b2f0314-e849-4799-9969-af93349bef75&sort_by=created_at&limit=25&offset=0" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Search contacts
curl "https://api-v2.dropcowboy.com/contact/public/contacts/search?phone=%2B13125550142" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Create contacts
curl -X POST "https://api-v2.dropcowboy.com/contact/public/contacts" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": [
      { "type": "first_name" },
      { "type": "last_name" },
      { "type": "main_phone" },
      { "type": "email" },
      { "type": "custom_field", "field_id": "34f38d24-632d-4a9c-bf89-b9371a722b35" }
    ],
    "values": [
      ["Dana", "Reyes", "+13125550142", "dana@example.com", "Gold"],
      ["Sam", "Okafor", "+13125550187", "", "Silver"]
    ],
    "add_list_ids": ["3b2f0314-e849-4799-9969-af93349bef75"],
    "conflict_mode": "append"
  }'
Get a contact
curl "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Update a contact
curl -X PUT "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "contact": {
      "field_data": [
        { "field_id": "8e42bc36-efeb-42c1-b99b-41ae9c60aa66", "type": "first_name", "value": "Danielle" }
      ]
    }
  }'
Delete a contact
curl -X DELETE "https://api-v2.dropcowboy.com/contact/public/contacts/756c1b7d-c27d-4faf-9365-bb83f0cbed66" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"