Engage

LinkedIn & WhatsApp

Read conversations, see who needs a reply or a follow-up, check LinkedIn connections, send invitations and messages — from the accounts connected in Meetzy.

These calls act on the LinkedIn and WhatsApp accounts the key’s user connected in Meetzy › Integrations & API › Personal integrations — each teammate connects their own WhatsApp (connecting needs their sign-in, in the app). Without a connected account they answer 409. Messages you send are logged on the contact’s timeline and fire contact.replied when they answer. LinkedIn limits apply: send invitations at a human pace.

In a chat
Copy a ready promptPaste it in any AI: it reads the docs and follows the rules of the API.
Open in Claude or ChatGPTA new conversation with the prompt already written.
This page as MarkdownFor an AI that cannot open links: paste the text itself.
In your editor
Claude Code or CodexAdd this line to CLAUDE.md or AGENTS.md.Meetzy API reference (read before calling the API): https://www.meetzy.ai/llms-full.txt
CursorSettings › Indexing & Docs › Add Doc, then type @Meetzy in the chat.https://www.meetzy.ai/llms-full.txt
Connect Meetzy as tools (MCP)The AI can then read and change your CRM itself — Claude Code:claude mcp add --transport http meetzy https://meetzy.me/api/mcp/mcp
Same for Codexcodex mcp add meetzy --url https://meetzy.me/api/mcp/mcp
GET/linkedin/status

Connection status with a contact

connected, invitation_pending (with invitation_type: SENT or RECEIVED) or not_connected (with network_distance), the LinkedIn profile, and the provider id. The contact needs a LinkedIn URL or username in the CRM.

Scope: read

Query parameters

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).
Request
curl "https://meetzy.me/api/v1/linkedin/status?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/linkedin/status?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/linkedin/status?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "status": "not_connected",
  "lead": {
    "id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "name": "Camille Laurent"
  },
  "provider_id": "ACoAAB…",
  "linkedin_username": "camille-laurent",
  "network_distance": "SECOND_DEGREE",
  "profile": {
    "first_name": "Camille",
    "last_name": "Laurent",
    "headline": "Head of Sales at Payfit"
  },
  "message": "Not connected with Camille Laurent on LinkedIn. You can send them a connection request."
}
GET/linkedin/inbox

LinkedIn inbox: who to answer, who to chase

Recent conversations sorted into needs_reply (they wrote last), needs_follow_up (you wrote last, no answer for N days) and waiting, each with the CRM contact when matched, the last messages and days since. Won and lost leads are left out.

Scope: read

Query parameters

daysinteger
How far back. Default 30.
max_chatsinteger
Per category. Default 30.
follow_up_daysinteger
Days without an answer before a follow-up is due. Default 5.

Answer: total_conversations, needs_reply, needs_follow_up, waiting — each conversation with chat_id, the person (and lead when they are in the CRM), status, last_message_from_them / last_message_from_me and days_since_last_message.

Request
curl "https://meetzy.me/api/v1/linkedin/inbox" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/linkedin/inbox", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/linkedin/inbox",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200

See the notes on the left.

GET/linkedin/messages

Conversation with a contact

Recent LinkedIn messages with one contact, oldest first, each with text, timestamp and is_from_me.

Scope: read

Query parameters

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).
limitinteger
Default 20.
Request
curl "https://meetzy.me/api/v1/linkedin/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc&limit=10" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/linkedin/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc&limit=10", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/linkedin/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc&limit=10",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "lead": {
    "id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "name": "Camille Laurent"
  },
  "chat_id": "chat_9f2…",
  "message_count": 2,
  "messages": [
    {
      "text": "Thanks for connecting, Camille!",
      "timestamp": "2026-10-05T08:12:00Z",
      "is_from_me": true,
      "sender_id": "me"
    },
    {
      "text": "Sounds good — can you send the deck?",
      "timestamp": "2026-10-06T17:40:00Z",
      "is_from_me": false,
      "sender_id": "ACoAAB…"
    }
  ]
}
GET/linkedin/connectable

Leads you could connect with

Contacts with a LinkedIn profile you are not connected to yet (no pending invitation), best score first — the list to send invitations to.

Scope: read

Query parameters

min_scoreinteger
Minimum lead score.
stagestring
CRM stage.
limitinteger
Default 20.

Answer: connectable (the leads, capped to what you can still send today), connectable_count, total_with_linkedin, already_connected, invitation_pending, daily_limit, sent_today, remaining_today and a summary.

Request
curl "https://meetzy.me/api/v1/linkedin/connectable?min_score=50&limit=10" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/linkedin/connectable?min_score=50&limit=10", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/linkedin/connectable?min_score=50&limit=10",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200

See the notes on the left.

POST/linkedin/invitations

Send a LinkedIn invitation

Sends a connection request to the contact (without a note). The contact is marked invitation_sent; contact.linkedin_connected fires when they accept.

Scope: write

Body

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).

status is already_connected or invitation_already_sent when there was nothing to send.

Request
curl -X POST "https://meetzy.me/api/v1/linkedin/invitations" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc"
  }'
const res = await fetch("https://meetzy.me/api/v1/linkedin/invitations", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/linkedin/invitations",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc"
    },
)
data = res.json()
Response201
{
  "status": "sent",
  "message": "Invitation sent to Camille Laurent."
}
POST/linkedin/messages

Send a LinkedIn message

Only to 1st-degree connections (400 otherwise — send an invitation first).

Scope: write

Body

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).
messagestringrequired
Exact text to send.
Request
curl -X POST "https://meetzy.me/api/v1/linkedin/messages" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "message": "Here is the deck, Camille: https://acme.com/deck"
  }'
const res = await fetch("https://meetzy.me/api/v1/linkedin/messages", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "message": "Here is the deck, Camille: https://acme.com/deck"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/linkedin/messages",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "contact_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
        "message": "Here is the deck, Camille: https://acme.com/deck"
    },
)
data = res.json()
Response201
{
  "status": "sent",
  "message": "Message sent to Camille Laurent."
}
GET/whatsapp/account

Your WhatsApp connection

The WhatsApp the key’s user reads and writes from — their own (each teammate connects theirs, in Meetzy › Integrations & API › Personal integrations), or a number a colleague shared / the team number (via: own, chosen, team, with its owner). needs_reconnect is true when WhatsApp asks to scan the QR code again.

Scope: read
Request
curl "https://meetzy.me/api/v1/whatsapp/account" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/account", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/whatsapp/account",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "connected": true,
  "phone": "+33612345678",
  "name": "Tristan",
  "status": "OK",
  "needs_reconnect": false,
  "connected_at": "2026-09-18T08:30:00Z",
  "via": "own",
  "owner": null
}
GET/whatsapp/accounts

The team’s WhatsApp numbers

Every WhatsApp connected in the workspace and who uses which. mode: personal (each person their own number; someone without one, or who prefers, uses a number a colleague shared, else the team number) or shared (everyone uses the team number). options are the numbers the key’s user may pick; using is the one they use now, with via: own, chosen or team. A personal number is only usable by others once its owner shares it.

Scope: read
Request
curl "https://meetzy.me/api/v1/whatsapp/accounts" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/accounts", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/whatsapp/accounts",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "mode": "personal",
  "team_account_id": "acc_7Hq…",
  "can_manage": true,
  "mine": {
    "id": "acc_7Hq…",
    "phone": "+33612345678",
    "name": "Tristan",
    "owner": {
      "email": "tristan@acme.com",
      "name": "Tristan Cassius"
    },
    "mine": true,
    "shared": true,
    "is_team": true,
    "needs_reconnect": false,
    "connected_at": "2026-09-18T08:30:00Z"
  },
  "using": {
    "id": "acc_7Hq…",
    "phone": "+33612345678",
    "name": "Tristan",
    "owner": {
      "email": "tristan@acme.com",
      "name": "Tristan Cassius"
    },
    "mine": true,
    "shared": true,
    "is_team": true,
    "needs_reconnect": false,
    "connected_at": "2026-09-18T08:30:00Z",
    "via": "own"
  },
  "choice": null,
  "options": [
    {
      "id": "acc_7Hq…",
      "phone": "+33612345678",
      "name": "Tristan",
      "owner": {
        "email": "tristan@acme.com",
        "name": "Tristan Cassius"
      },
      "mine": true,
      "shared": true,
      "is_team": true,
      "needs_reconnect": false,
      "connected_at": "2026-09-18T08:30:00Z"
    }
  ],
  "accounts": [
    {
      "id": "acc_7Hq…",
      "phone": "+33612345678",
      "name": "Tristan",
      "owner": {
        "email": "tristan@acme.com",
        "name": "Tristan Cassius"
      },
      "mine": true,
      "shared": true,
      "is_team": true,
      "needs_reconnect": false,
      "connected_at": "2026-09-18T08:30:00Z"
    }
  ],
  "members": [
    {
      "email": "camille@acme.com",
      "name": "Camille Durand",
      "memoji": null,
      "uses": {
        "phone": "+33612345678",
        "owner": "Tristan Cassius",
        "via": "team"
      }
    }
  ]
}
PUT/whatsapp/accounts/choice

Pick the number you use

The key’s user picks one of their options (their own, a shared number, the team number), or null to go back to automatic (own number first, then the team number).

Scope: write

Body

account_idstring
An id from options, or null.

Answers like GET whatsapp/accounts.

Request
curl -X PUT "https://meetzy.me/api/v1/whatsapp/accounts/choice" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "acc_7Hq…"
  }'
const res = await fetch("https://meetzy.me/api/v1/whatsapp/accounts/choice", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "account_id": "acc_7Hq…"
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/whatsapp/accounts/choice",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "account_id": "acc_7Hq…"
    },
)
data = res.json()
Response200

See the notes on the left.

PATCH/whatsapp/account

Share your WhatsApp with the team

Lets teammates pick your number (and the owner make it the team number) — or stops it: then nobody else uses it any more.

Scope: write

Body

sharedbooleanrequired
true to share, false to stop.

Answers like GET whatsapp/accounts.

Request
curl -X PATCH "https://meetzy.me/api/v1/whatsapp/account" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shared": true
  }'
const res = await fetch("https://meetzy.me/api/v1/whatsapp/account", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "shared": true
  }),
});
const data = await res.json();
import os, requests

res = requests.patch(
    "https://meetzy.me/api/v1/whatsapp/account",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "shared": True
    },
)
data = res.json()
Response200

See the notes on the left.

PUT/whatsapp/accounts/settings

How the team uses WhatsApp (owner)

Workspace owner only. personal: each person their own number, the team number as a fallback. shared: everyone uses the team number. The team number must be the owner’s own or one shared by its owner.

Scope: write

Body

modestring
personal or shared.
team_account_idstring
The team number (an account id), or null.

403 for anyone but the owner. Answers like GET whatsapp/accounts.

Request
curl -X PUT "https://meetzy.me/api/v1/whatsapp/accounts/settings" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "shared",
    "team_account_id": "acc_7Hq…"
  }'
const res = await fetch("https://meetzy.me/api/v1/whatsapp/accounts/settings", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "mode": "shared",
    "team_account_id": "acc_7Hq…"
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/whatsapp/accounts/settings",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "mode": "shared",
        "team_account_id": "acc_7Hq…"
    },
)
data = res.json()
Response200

See the notes on the left.

GET/contacts/{id}/conversations

Where you can talk to a contact

The networks this contact can be reached on: WhatsApp (always listed — it needs a phone number), and LinkedIn, Instagram, Facebook and X when the contact has a profile on them. preferred is the one to open first.

Scope: read

Path parameters

idstringrequired
Id of the record (UUID).
Request
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "channels": [
    {
      "id": "whatsapp",
      "label": "WhatsApp",
      "handle": "06 12 34 56 78",
      "ready": true
    },
    {
      "id": "linkedin",
      "label": "LinkedIn",
      "handle": "camille-laurent",
      "ready": true
    }
  ],
  "preferred": "whatsapp"
}
GET/contacts/{id}/conversations/{channel}

A contact’s conversation, on any network

The same shape for whatsapp, linkedin, instagram, facebook and twitter: messages oldest first, each with from_me, read receipts, reactions, quoted message and attachments (download WhatsApp and LinkedIn files with the attachment route; social networks give a direct url). state says what to show when there are no messages: not_connected (the key’s user has not connected that network), needs_reconnect, no_handle (no phone number or profile on the contact), no_chat (no conversation yet), or ok.

Scope: read

Path parameters

idstringrequired
Id of the record (UUID).
channelstringrequired
Path parameter.

Query parameters

beforedatetime
Older messages: the at of the first message you have (WhatsApp and LinkedIn).
limitinteger
Default 40, max 100.
Request
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "channel": "linkedin",
  "state": "ok",
  "can_attach": true,
  "account": null,
  "contact": {
    "name": "Camille Laurent",
    "picture": "https://media.licdn.com/…",
    "handle": "Head of Sales at Payfit"
  },
  "messages": [
    {
      "id": "msg_1…",
      "text": "Thanks, see you Thursday!",
      "at": "2026-10-07T09:02:00Z",
      "from_me": false,
      "seen": true,
      "delivered": true,
      "edited": false,
      "deleted": false,
      "forwarded": false,
      "view_once": false,
      "event": null,
      "reactions": [],
      "quoted": null,
      "attachments": []
    }
  ],
  "cursor": null
}
POST/contacts/{id}/conversations/{channel}

Send a message on any network

Writes to the contact on the chosen network from the key’s user’s account, into the existing conversation or a new one. WhatsApp and LinkedIn take files too. LinkedIn only lets you write to 1st-degree connections; Instagram, Facebook and X only once the person has written to you.

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).
channelstringrequired
Path parameter.

Body

textstring
The message.
attachmentsarray
WhatsApp and LinkedIn: up to 10 files { name, type, data } (base64, 16 MB each).
quote_idstring
WhatsApp: reply to this message id.

400 with code not_connected_on_linkedin, no_handle or no_chat when the network refuses; 409 when the network is not connected.

Request
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Great to meet you yesterday, Camille!"
  }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "text": "Great to meet you yesterday, Camille!"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/conversations/%7Bchannel%7D",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "text": "Great to meet you yesterday, Camille!"
    },
)
data = res.json()
Response201
{
  "sent": true,
  "channel": "linkedin",
  "chat_id": "chat_9f2…",
  "message_id": "msg_8Ld…"
}
POST/contacts/{id}/photo

Fetch a contact’s profile photo

Gives the contact a lasting photo: their LinkedIn profile picture, else their WhatsApp one (from the key’s user’s accounts), stored by Meetzy so it does not expire. A photo already on the contact is kept and stored the same way while it still loads. When nothing is found, the networks are asked again after 3 days at the earliest.

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

source: linkedin, whatsapp or existing; avatar_url null when there is no photo.

Request
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/photo" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/photo", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/photo",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response201
{
  "avatar_url": "https://…/storage/v1/object/public/profile-photos/contacts/…/e43414d6-….jpg",
  "source": "linkedin"
}
GET/conversations/attachments/{message_id}/{attachment_id}

Download a message’s file

An image, video, voice note or document of a WhatsApp or LinkedIn message — only from the key’s user’s own conversations.

Scope: read

Path parameters

message_idstringrequired
Path parameter.
attachment_idstringrequired
Path parameter.

Binary answer, not JSON.

Request
curl "https://meetzy.me/api/v1/conversations/attachments/%7Bmessage_id%7D/%7Battachment_id%7D" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/conversations/attachments/%7Bmessage_id%7D/%7Battachment_id%7D", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/conversations/attachments/%7Bmessage_id%7D/%7Battachment_id%7D",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200

See the notes on the left.

GET/contacts/{id}/whatsapp

A contact’s WhatsApp conversation

The conversation with this contact on the key’s user’s WhatsApp, found from the contact’s phone number however it was typed (+33 6 12…, 06 12… with the contact’s country, 0033…) or a chat already linked to them. Messages oldest first, with from_me, read receipts (seen, delivered), reactions, quoted messages and attachments (images, videos, voice notes, files — download each with the attachment route). chat is null when there is no conversation yet: number is then where a first message would go.

Scope: read

Path parameters

idstringrequired
Id of the record (UUID).

Query parameters

beforedatetime
Older messages: pass the at of the first message you have.
limitinteger
Default 40, max 100.

connected: false when the key’s user has no WhatsApp connected.

Request
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "connected": true,
  "needs_reconnect": false,
  "account_phone": "+33698765432",
  "phones": [
    "06 12 34 56 78"
  ],
  "number": "+33612345678",
  "chat": {
    "id": "Xk3…",
    "name": "Camille Laurent",
    "picture": "https://pps.whatsapp.net/…"
  },
  "messages": [
    {
      "id": "msg_1…",
      "text": "Here is the photo of the shelf",
      "at": "2026-10-07T09:02:00Z",
      "from_me": false,
      "seen": true,
      "delivered": true,
      "edited": false,
      "deleted": false,
      "forwarded": false,
      "view_once": false,
      "event": null,
      "reactions": [
        {
          "emoji": "👍",
          "mine": true
        }
      ],
      "quoted": null,
      "attachments": [
        {
          "id": "3AE6…",
          "kind": "image",
          "mime": "image/jpeg",
          "name": null,
          "size": 292374,
          "width": 1152,
          "height": 2048,
          "duration": null,
          "voice": false,
          "unavailable": false
        }
      ]
    }
  ],
  "cursor": null
}
POST/contacts/{id}/whatsapp

Send a WhatsApp message to a contact

From the key’s user’s WhatsApp, into the existing conversation or a new one at the contact’s number. Text, files, or both. The message is logged on the contact’s timeline.

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

Body

textstring
The message.
attachmentsarray
Up to 10 files: { name, type, data } with data in base64 (16 MB each).
quote_idstring
Reply to this message id.
phonestring
Number to use when the contact has none saved (international, e.g. +33612345678).

400 when the contact has no phone number (code no_phone) or the number is not on WhatsApp; 409 when no WhatsApp is connected.

Request
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Hi Camille, 3pm works. Talk soon!"
  }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "text": "Hi Camille, 3pm works. Talk soon!"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/whatsapp",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "text": "Hi Camille, 3pm works. Talk soon!"
    },
)
data = res.json()
Response201
{
  "sent": true,
  "chat_id": "Xk3…",
  "message_id": "msg_8Ld…",
  "to": "+33612345678"
}
GET/whatsapp/attachments/{message_id}/{attachment_id}

Download a WhatsApp attachment

The file itself (image, video, voice note, document) with its content type — only from the key’s user’s own conversations.

Scope: read

Path parameters

message_idstringrequired
Path parameter.
attachment_idstringrequired
Path parameter.

Binary answer, not JSON.

Request
curl "https://meetzy.me/api/v1/whatsapp/attachments/%7Bmessage_id%7D/%7Battachment_id%7D" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/attachments/%7Bmessage_id%7D/%7Battachment_id%7D", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/whatsapp/attachments/%7Bmessage_id%7D/%7Battachment_id%7D",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200

See the notes on the left.

GET/whatsapp/inbox

WhatsApp inbox: who to answer, who to chase

Conversations where you need to reply, where a follow-up is due, and where you are waiting. Names come from the CRM when matched, else from WhatsApp’s saved contact name.

Scope: read

Query parameters

qstring
Only conversations whose name or number contains this text.
max_chatsinteger
Per category. Default 30.
follow_up_daysinteger
Default 3.
Request
curl "https://meetzy.me/api/v1/whatsapp/inbox" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/inbox", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/whatsapp/inbox",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "summary": "📩 1 people are waiting for YOUR reply on WhatsApp: Camille Laurent",
  "total_conversations": 9,
  "needs_reply_count": 1,
  "needs_follow_up_count": 0,
  "waiting_count": 2,
  "matched_to_crm_leads": 6,
  "follow_up_threshold_days": 3,
  "needs_reply": [
    {
      "chat_id": "Xk3…",
      "name": "Camille Laurent",
      "phone": "33612345678",
      "last_activity": "2026-10-07T09:02:00Z",
      "days_since_last_message": 0,
      "last_message_preview": "Can we move the call to 3pm?",
      "matched_lead": {
        "id": "e43414d6-f56f-42be-a64c-a836d6015efc",
        "name": "Camille Laurent"
      }
    }
  ],
  "needs_follow_up": [],
  "waiting": []
}
GET/whatsapp/messages

WhatsApp conversation

Recent messages with a contact, a phone number or a known chat, oldest first. Page back with before.

Scope: read

Query parameters

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).
chat_idstring
A chat id from the inbox or a search — the most reliable.
phonestring
International number without + (33612345678) for someone not in the CRM.
limitinteger
Default 20, max 100.
beforedatetime
Messages before this time.
afterdatetime
Messages after this time.
Request
curl "https://meetzy.me/api/v1/whatsapp/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/whatsapp/messages?contact_id=e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "lead": {
    "id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "name": "Camille Laurent"
  },
  "contact_name": "Camille Laurent",
  "chat_id": "Xk3…",
  "cursor": null,
  "message_count": 1,
  "messages": [
    {
      "text": "Can we move the call to 3pm?",
      "timestamp": "2026-10-07T09:02:00Z",
      "is_from_me": false
    }
  ]
}
POST/whatsapp/messages

Send a WhatsApp message

To a CRM contact, a known chat, or any number — no prior conversation needed.

Scope: write

Body

contact_iduuid
CRM contact (preferred).
namestring
Or the contact’s name (fuzzy match).
chat_idstring
Existing chat.
phonestring
International number without +.
messagestringrequired
Exact text to send.
Request
curl -X POST "https://meetzy.me/api/v1/whatsapp/messages" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "33612345678",
    "message": "Hi Camille, 3pm works. Talk soon!"
  }'
const res = await fetch("https://meetzy.me/api/v1/whatsapp/messages", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "phone": "33612345678",
    "message": "Hi Camille, 3pm works. Talk soon!"
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/whatsapp/messages",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "phone": "33612345678",
        "message": "Hi Camille, 3pm works. Talk soon!"
    },
)
data = res.json()
Response201
{
  "status": "sent",
  "chat_id": "Xk3…",
  "message_id": "msg_8Ld…",
  "to": "33612345678@s.whatsapp.net",
  "matched_lead": {
    "id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "name": "Camille Laurent"
  }
}