POST /v1/actions/search-contacts

Find contacts by name/phone/email substring, or by tag. Returns up to 50 results.

Search contacts by free-text query (name/phone/email substring, case-insensitive), and/or filter by tag and exact email. Returns up to 50 results ordered by last_message_at DESC.

POST /api/v1/actions/search-contacts

Request body

Field Type Required Notes
query string no Substring match against name, phone, email (Postgres ILIKE)
tag string no Exact tag name
email string no Exact email match

All filters are AND-combined. Empty body returns the 50 most-recently-active contacts.

curl -X POST https://www.qyvo.io/api/v1/actions/search-contacts \
  -H "Authorization: Bearer YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{"query": "smith", "tag": "vip"}'
const contacts = await fetch('https://www.qyvo.io/api/v1/actions/search-contacts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.QYVO_TOKEN}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ query: 'smith', tag: 'vip' }),
}).then((r) => r.json());
$contacts = Http::withToken(env('QYVO_TOKEN'))
    ->post('https://www.qyvo.io/api/v1/actions/search-contacts', [
        'query' => 'smith',
        'tag' => 'vip',
    ])
    ->json();
import os, httpx
contacts = httpx.post(
    'https://www.qyvo.io/api/v1/actions/search-contacts',
    headers={'Authorization': f"Bearer {os.environ['QYVO_TOKEN']}"},
    json={'query': 'smith', 'tag': 'vip'},
).json()

Response — 200 OK

[
  {
    "id": "01J1Y...",
    "phone": "+14155550123",
    "name": "Jane Smith",
    "email": "[email protected]",
    "source": "shopify",
    "tags": ["vip"],
    "last_message_at": "2026-05-07T08:14:23+00:00",
    "created_at": "2026-04-15T10:32:00+00:00"
  }
]

The result is a flat array — empty [] when nothing matches. See Pagination for the larger-result-set pattern.