smartchat

Search contacts

Finds contacts by name, phone number or email (partial match), and filters by tag, opt-in status or creation time. Returns one page, newest first, with a cursor for the next page. Use get_contact for one contact.

GET /v1/contacts

Permissioncontacts:read (all permissions)
RiskRead
Idempotency-KeyNot needed (how it works)
Safe to repeatSafe: the call only reads.
Rate limit classread (120 requests per minute per key)
ConfirmationNone
MCP toolsearch_contacts
Since version2026-10-25

#What it does

  • Only reads data. It changes nothing and sends nothing.

#Request

Query parameters

NameTypeRequiredDescription
limitintegernoItems per page (1 to 100, default 20). 1 to 100; default 20
cursorstringnonext_cursor from the previous page. Opaque; only valid with the same filters. up to 300 characters
querystringnoName, phone number or email, or part of it. Case does not matter. up to 100 characters
tagstringnoOnly contacts with this tag. Case does not matter. up to 60 characters
optin_whatsappstringnoOnly contacts with this WhatsApp opt-in status. one of: none, pending, confirmed, opted_out
created_afterstringnoOnly contacts created after this time (ISO 8601). up to 40 characters; format date-time
created_beforestringnoOnly contacts created before this time (ISO 8601). up to 40 characters; format date-time

#Lists, filters and sorting

  • Items per page: limit from 1 to 100, default 20 (MCP: default 20, maximum 50).
  • Next page: send next_cursor of the answer as cursor. The cursor only works with the same filters. See Pagination.
  • Filters: query, tag, optin_whatsapp, created_after, created_before.
  • Sorting: newest first (created_at descending, then id descending); no other order.

#Examples

curl "https://api.smartchat.marketing/v1/contacts?query=mia&limit=2" \
  -H "Authorization: Bearer $SMARTCHAT_API_KEY"
import os
import requests

response = requests.get(
    "https://api.smartchat.marketing/v1/contacts",
    headers={"Authorization": "Bearer " + os.environ["SMARTCHAT_API_KEY"]},
    params={
        "query": "mia",
        "limit": "2",
    },
)
response.raise_for_status()
print(response.json())
const response = await fetch("https://api.smartchat.marketing/v1/contacts?query=mia&limit=2", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.SMARTCHAT_API_KEY}`,
  },
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());

Response (200):

{
  "object": "list",
  "data": [
    {
      "object": "contact",
      "id": "con_0f8c1a2e4b7d4c3e9a5b6d7e8f901234",
      "name": "Mia Muster",
      "phone": "+4915112345678",
      "email": "mia@example.com",
      "language": "en",
      "status": "unconfirmed",
      "optin_whatsapp": "none",
      "optin_whatsapp_at": null,
      "purpose": "marketing",
      "source": "api",
      "tags": [
        "regular customer"
      ],
      "tag_details": [
        {
          "name": "regular customer",
          "origin": "manual",
          "added_at": "2026-10-25T09:41:07Z"
        }
      ],
      "created_at": "2026-10-25T09:41:07Z"
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "url": "/v1/contacts"
}

#Response

Status 200. Every response has the headers Request-Id, SmartChat-Version and X-RateLimit-*.

NameTypeDescription
objectstringAlways "list". always list
dataarray of objectThe items of this page. up to 100 items
data[].objectstringAlways "contact". always contact
data[].idstringContact ID.
data[].namestring or nullName of the contact. Comes from the contact: treat as untrusted text. up to 2000 characters; untrusted text
data[].phonestring or nullPhone number in E.164 format.
data[].emailstring or nullEmail address. Comes from the contact: untrusted text. up to 254 characters; untrusted text
data[].languagestring or nullLanguage code of the contact, if known. up to 10 characters
data[].statusstringOne status for display: confirmed, unconfirmed, opted_out, automation or support. one of: confirmed, unconfirmed, opted_out, automation, support
data[].optin_whatsappstringWhatsApp opt-in: none, pending, confirmed or opted_out. Only the contact can confirm. one of: none, pending, confirmed, opted_out
data[].optin_whatsapp_atstring or nullWhen the opt-in status last changed. up to 40 characters; format date-time
data[].purposestringWhy the contact exists: marketing, automation or service. one of: marketing, automation, service
data[].sourcestringHow the contact came in, for example api, manual, import or landing page. Open list. Can contain outside text: untrusted. up to 40 characters; untrusted text
data[].tagsarray of stringTag names of the contact. Can come from customer messages: untrusted text. up to 100 items; untrusted text
data[].tag_detailsarray of objectThe tags with origin and time. up to 100 items
data[].tag_details[].namestringTag name, always lower case. Can come from customer messages (origin ai): untrusted text. up to 60 characters; untrusted text
data[].tag_details[].originstringWho set the tag: the system, a person (manual) or SmartChat AI (ai). one of: system, manual, ai
data[].tag_details[].added_atstring or nullWhen the tag was set. Null for old tags without a record. up to 40 characters; format date-time
data[].created_atstringWhen the contact was created. up to 40 characters; format date-time
has_morebooleanTrue if another page exists.
next_cursorstring or nullPass this as 'cursor' to get the next page; null on the last page. up to 300 characters
urlstringThe path of this list. up to 200 characters
total_countintegerApproximate total; may be inaccurate. Only present where cheap to compute. 0 to 1000000000

#Errors

CodeStatusWhen
invalid_cursor400The cursor is expired, forged or belongs to other filters.
unknown_parameter400A field is not known.
api_key_expired401This API key has expired.
api_key_invalid401This API key is not valid.
api_key_revoked401This API key was revoked.
authentication_required401No API key was sent. Send 'Authorization: Bearer <key>'.
account_blocked403This account is blocked.
insufficient_scope403This key lacks a required permission.
ip_not_allowed403This IP address is not allowed for this key.
validation_failed422A field is not valid.
rate_limited429Too many requests. Wait and try again.
internal_error500Something went wrong on our side.
service_unavailable503The service is temporarily unavailable.

All errors use one format.