GET /v1/triggers/new-message-received

Most recent inbound messages from your contacts, used by polling integrations like n8n and Zapier.

Returns up to 100 most-recent inbound messages for the tenant, sorted by created_at DESC. This is the polling source for n8n's Qyvo trigger node and equivalent integrations.

GET /api/v1/triggers/new-message-received

Query parameters

Param Type Description
message_type string Optional. Filter by text, image, audio, document, video, location, contacts, interactive

Request

curl 'https://www.qyvo.io/api/v1/triggers/new-message-received?message_type=text' \
  -H "Authorization: Bearer YOUR_TOKEN_HERE"
const messages = await fetch(
  'https://www.qyvo.io/api/v1/triggers/new-message-received?message_type=text',
  { headers: { Authorization: `Bearer ${process.env.QYVO_TOKEN}` } },
).then((r) => r.json());
$messages = Http::withToken(env('QYVO_TOKEN'))
    ->get('https://www.qyvo.io/api/v1/triggers/new-message-received', [
        'message_type' => 'text',
    ])
    ->json();
import os, httpx
messages = httpx.get(
    'https://www.qyvo.io/api/v1/triggers/new-message-received',
    params={'message_type': 'text'},
    headers={'Authorization': f"Bearer {os.environ['QYVO_TOKEN']}"},
).json()

Response — 200 OK

An array (not an envelope). Empty [] when there are no messages.

[
  {
    "id": "01J4M...",
    "direction": "inbound",
    "type": "text",
    "content": { "body": "Hi, do you ship to Canada?" },
    "status": "received",
    "contact_id": "01J1Y...",
    "contact_phone": "+14155550123",
    "contact_name": "Romain",
    "contact_email": null,
    "sent_at": null,
    "delivered_at": null,
    "read_at": null,
    "created_at": "2026-05-07T08:14:23+00:00"
  }
]
Field Type Notes
id UUID Qyvo message id
direction string Always inbound
type string text, image, audio, …
content object Shape depends on type{body} for text, {url, mime_type} for media
status string received for normal inbound; never sent/delivered/read (those apply to outbound)
contact_* various Denormalized fields from the joined contact
created_at ISO 8601 Server insertion time — the field you compare for new-since-last-poll

Polling pattern

Remember the most recent id you've processed. On the next poll, stop iterating when you hit it. See Pagination for the canonical pattern.

Webhook alternative

If you can receive HTTPS callbacks, use the message.received webhook instead — same payload, no polling.