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.
/linkedin/statusConnection status with a contactGET/linkedin/inboxLinkedIn inbox: who to answer, who to chaseGET/linkedin/messagesConversation with a contactGET/linkedin/connectableLeads you could connect withPOST/linkedin/invitationsSend a LinkedIn invitationPOST/linkedin/messagesSend a LinkedIn messageGET/whatsapp/accountYour WhatsApp connectionGET/whatsapp/accountsThe team’s WhatsApp numbersPUT/whatsapp/accounts/choicePick the number you usePATCH/whatsapp/accountShare your WhatsApp with the teamPUT/whatsapp/accounts/settingsHow the team uses WhatsApp (owner)GET/contacts/{id}/conversationsWhere you can talk to a contactGET/contacts/{id}/conversations/{channel}A contact’s conversation, on any networkPOST/contacts/{id}/conversations/{channel}Send a message on any networkPOST/contacts/{id}/photoFetch a contact’s profile photoGET/conversations/attachments/{message_id}/{attachment_id}Download a message’s fileGET/contacts/{id}/whatsappA contact’s WhatsApp conversationPOST/contacts/{id}/whatsappSend a WhatsApp message to a contactGET/whatsapp/attachments/{message_id}/{attachment_id}Download a WhatsApp attachmentGET/whatsapp/inboxWhatsApp inbox: who to answer, who to chaseGET/whatsapp/messagesWhatsApp conversationGET/whatsapp/searchSearch WhatsApp messagesPOST/whatsapp/messagesSend a WhatsApp message/linkedin/statusConnection 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.
Query parameters
contact_iduuid- CRM contact (preferred).
namestring- Or the contact’s name (fuzzy match).
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(){
"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."
}/linkedin/inboxLinkedIn 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.
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.
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()See the notes on the left.
/linkedin/messagesConversation with a contact
Recent LinkedIn messages with one contact, oldest first, each with text, timestamp and is_from_me.
Query parameters
contact_iduuid- CRM contact (preferred).
namestring- Or the contact’s name (fuzzy match).
limitinteger- Default 20.
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(){
"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…"
}
]
}/linkedin/connectableLeads 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.
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.
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()See the notes on the left.
/linkedin/invitationsSend 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.
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.
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(){
"status": "sent",
"message": "Invitation sent to Camille Laurent."
}/linkedin/messagesSend a LinkedIn message
Only to 1st-degree connections (400 otherwise — send an invitation first).
Body
contact_iduuid- CRM contact (preferred).
namestring- Or the contact’s name (fuzzy match).
messagestringrequired- Exact text to send.
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(){
"status": "sent",
"message": "Message sent to Camille Laurent."
}/whatsapp/accountYour 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.
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(){
"connected": true,
"phone": "+33612345678",
"name": "Tristan",
"status": "OK",
"needs_reconnect": false,
"connected_at": "2026-09-18T08:30:00Z",
"via": "own",
"owner": null
}/whatsapp/accountsThe 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.
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(){
"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"
}
}
]
}/whatsapp/accounts/choicePick 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).
Body
account_idstring- An id from
options, or null.
Answers like GET whatsapp/accounts.
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()See the notes on the left.
/whatsapp/accountShare 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.
Body
sharedbooleanrequired- true to share, false to stop.
Answers like GET whatsapp/accounts.
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()See the notes on the left.
/whatsapp/accounts/settingsHow 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.
Body
modestringpersonalorshared.team_account_idstring- The team number (an account id), or null.
403 for anyone but the owner. Answers like GET whatsapp/accounts.
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()See the notes on the left.
/contacts/{id}/conversationsWhere 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.
Path parameters
idstringrequired- Id of the record (UUID).
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(){
"channels": [
{
"id": "whatsapp",
"label": "WhatsApp",
"handle": "06 12 34 56 78",
"ready": true
},
{
"id": "linkedin",
"label": "LinkedIn",
"handle": "camille-laurent",
"ready": true
}
],
"preferred": "whatsapp"
}/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.
Path parameters
idstringrequired- Id of the record (UUID).
channelstringrequired- Path parameter.
Query parameters
beforedatetime- Older messages: the
atof the first message you have (WhatsApp and LinkedIn). limitinteger- Default 40, max 100.
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(){
"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
}/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.
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.
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(){
"sent": true,
"channel": "linkedin",
"chat_id": "chat_9f2…",
"message_id": "msg_8Ld…"
}/contacts/{id}/photoFetch 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.
Path parameters
idstringrequired- Id of the record (UUID).
source: linkedin, whatsapp or existing; avatar_url null when there is no photo.
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(){
"avatar_url": "https://…/storage/v1/object/public/profile-photos/contacts/…/e43414d6-….jpg",
"source": "linkedin"
}/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.
Path parameters
message_idstringrequired- Path parameter.
attachment_idstringrequired- Path parameter.
Binary answer, not JSON.
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()See the notes on the left.
/contacts/{id}/whatsappA 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.
Path parameters
idstringrequired- Id of the record (UUID).
Query parameters
beforedatetime- Older messages: pass the
atof the first message you have. limitinteger- Default 40, max 100.
connected: false when the key’s user has no WhatsApp connected.
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(){
"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
}/contacts/{id}/whatsappSend 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.
Path parameters
idstringrequired- Id of the record (UUID).
Body
textstring- The message.
attachmentsarray- Up to 10 files:
{ name, type, data }withdatain 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.
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(){
"sent": true,
"chat_id": "Xk3…",
"message_id": "msg_8Ld…",
"to": "+33612345678"
}/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.
Path parameters
message_idstringrequired- Path parameter.
attachment_idstringrequired- Path parameter.
Binary answer, not JSON.
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()See the notes on the left.
/whatsapp/inboxWhatsApp 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.
Query parameters
qstring- Only conversations whose name or number contains this text.
max_chatsinteger- Per category. Default 30.
follow_up_daysinteger- Default 3.
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(){
"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": []
}/whatsapp/messagesWhatsApp conversation
Recent messages with a contact, a phone number or a known chat, oldest first. Page back with before.
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.
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(){
"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
}
]
}/whatsapp/searchSearch WhatsApp messages
Finds messages containing a text, in one conversation or across recent ones.
Query parameters
qstringrequired- Text to find.
contact_iduuid- CRM contact (preferred).
namestring- Or the contact’s name (fuzzy match).
chat_idstring- One conversation.
phonestring- One number.
afterdatetime- From.
beforedatetime- To.
limitinteger- Max results.
max_scaninteger- Max messages scanned.
curl "https://meetzy.me/api/v1/whatsapp/search?q=invoice" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/whatsapp/search?q=invoice", {
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/search?q=invoice",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"query": "invoice",
"scope": "all_whatsapp_conversations",
"scanned_messages": 640,
"match_count": 1,
"matches": [
{
"chat_id": "Xk3…",
"text": "Did you get the invoice for September?",
"timestamp": "2026-10-02T10:20:00Z",
"is_from_me": true,
"contact_name": "Camille Laurent"
}
]
}/whatsapp/messagesSend a WhatsApp message
To a CRM contact, a known chat, or any number — no prior conversation needed.
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.
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(){
"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"
}
}