Contacts
People in your CRM: create, search, update, their full 360° view, notes, emails and everything that happened with them.
A contact is one person. It carries their details, owner, lifecycle stage, temperature, score and tags, and links to a company. Creating a contact with an email that already exists returns the existing contact instead of a duplicate — use POST /contacts/upsert to create or update in one call.
/contactsList and search contactsPOST/contactsCreate a contactPOST/contacts/upsertCreate or update a contact by emailGET/contacts/{id}Get a contact (360° view)PATCH/contacts/{id}Update a contactDELETE/contacts/{id}Delete a contactPOST/contacts/{id}/notesAdd a noteGET/contacts/{id}/interactionsEverything that happened with a contactGET/contacts/{id}/copilotWhat to do next with a contactPOST/contacts/{id}/copilotWhat to do next, with the AI’s readPOST/contacts/{id}/associate-companyLink the contact to its companyGET/contacts/{id}/company-suggestionsCompanies this contact may belong toGET/contacts/{id}/companiesAll the contact’s companiesPOST/contacts/{id}/companiesAdd a company to the contactDELETE/contacts/{id}/companies/{companyId}Remove a company from the contactPOST/contacts/{id}/companies/{companyId}/mainMake it the main companyPUT/contacts/{id}/companyChoose the contact’s companyPOST/contacts/{id}/emailSend an email to a contactGET/contacts/{id}/emailsEmails sent to a contactPOST/contacts/bulk/enrollEnroll contacts in a sequence/contactsList and search contacts
Contacts sorted by lead score (highest first) by default. Combine any filters. Returns total for paging.
Query parameters
qstring- Search in name, email, company and job title.
company_iduuid- Only people of this company.
ownerstring- Owner email (
assigned_to). stagestring- CRM board stage (
pipeline_stage). lifecycle_stagestring- Lifecycle stage.
min_scoreinteger- Minimum lead score.
updated_sincedatetime- Only contacts changed since this ISO date — use it to sync incrementally.
sortstring- Column to sort by (
lead_score,created_at,updated_at,display_name…). Defaultlead_score. orderstringascordesc(default).limitinteger- Page size, 1–1000. Default 50.
offsetinteger- Rows to skip. Default 0.
curl "https://meetzy.me/api/v1/contacts?q=payfit&min_score=40&limit=20" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts?q=payfit&min_score=40&limit=20", {
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?q=payfit&min_score=40&limit=20",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"contacts": [
{
"id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"display_name": "Camille Laurent",
"first_name": "Camille",
"last_name": "Laurent",
"primary_email": "camille@payfit.com",
"phone": "+33612345678",
"title": "Head of Sales",
"company": "Payfit",
"company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
"avatar_url": null,
"lead_score": 0,
"lead_status": "cold",
"pipeline_stage": "new_leads",
"lifecycle_stage": "lead",
"assigned_to": null,
"primary_source": "manual",
"last_contact_at": null,
"created_at": "2026-10-07T13:22:38.585893+00:00",
"linkedin_profile_url": null,
"country": null,
"city": null,
"tags": [
"inbound"
]
}
],
"total": 1
}/contactsCreate a contact
Creates a contact and links it to a company (found by email domain or company name, created if needed). If a contact with the same email exists, it is returned unchanged — the response then has the same id. Needs an email or a name.
Body
emailstringemail or name- Email address. Also accepted as
primary_email. first_namestring- First name.
last_namestring- Last name.
display_namestring- Full name as shown in the app. Built from first and last name when omitted.
phonestring- Phone number, ideally in international format (
+33612345678). titlestring- Job title.
companystring- Company name as written on the contact. Meetzy links the contact to its company when it is clear (email domain of one company, else exactly the same name) unless
associate_companyis false. company_iduuid- Link to an existing company.
company_websitestring- Company website, used to find the company by domain.
lifecycle_stagestring- Where the person is in the funnel:
subscriber,lead,mql,sql,opportunity,customer,evangelist,churned,other. Defaultlead. pipeline_stagestring- Stage on the CRM board of their sales cycle (see Sales cycles). Default
new_leads. sales_cycle_idstring- Sales cycle the contact belongs to (
defaultor a cycle id fromGET /crm/cycles). lead_statusstring- Temperature:
hot,warmorcold. Defaultcold. Setting it by hand stops the automatic temperature. lead_scoreinteger- Score from 0 to 100. Usually moved by scoring and workflows.
assigned_tostring- Owner — email of a teammate.
countrystring- Country.
citystring- City.
regionstring- Region or state.
headlinestring- Professional headline (LinkedIn).
linkedin_profile_urlstring- LinkedIn profile URL — needed for LinkedIn steps.
tagsstring[]- Free labels, e.g.
["inbound", "webinar"]. custom_propertiesobject- Values of your custom properties, keyed by property key (see Properties).
do_not_contactboolean- Never email or message this person (sequences and campaigns skip them).
reminder_datedate- Follow-up date (
YYYY-MM-DD) shown in Follow-ups. reminder_notestring- What the follow-up is about.
reminder_assigned_tostring- Teammate who should do the follow-up (email).
label_iduuid- CRM board label.
notesstring- Free text notes field (for timestamped notes use
POST /contacts/{id}/notes). secondary_emailsstring[]- Other addresses of the same person — their emails are matched to this contact.
instagram_usernamestring- Instagram handle.
facebook_usernamestring- Facebook handle.
twitter_usernamestring- X / Twitter handle.
tiktok_usernamestring- TikTok handle.
threads_usernamestring- Threads handle.
sourcestring- Where the contact comes from (
website,event,import…). Defaultmanual. associate_companyboolean- Link to a company automatically. Default
true.
curl -X POST "https://meetzy.me/api/v1/contacts" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "email": "camille@payfit.com", "first_name": "Camille", "last_name": "Laurent", "title": "Head of Sales", "company": "Payfit", "assigned_to": "olivia@acme.com", "lifecycle_stage": "mql", "tags": [ "inbound" ], "source": "website" }'
const res = await fetch("https://meetzy.me/api/v1/contacts", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "email": "camille@payfit.com", "first_name": "Camille", "last_name": "Laurent", "title": "Head of Sales", "company": "Payfit", "assigned_to": "olivia@acme.com", "lifecycle_stage": "mql", "tags": [ "inbound" ], "source": "website" }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"email": "camille@payfit.com",
"first_name": "Camille",
"last_name": "Laurent",
"title": "Head of Sales",
"company": "Payfit",
"assigned_to": "olivia@acme.com",
"lifecycle_stage": "mql",
"tags": ["inbound"],
"source": "website"
},
)
data = res.json(){
"id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"display_name": "Camille Laurent",
"first_name": "Camille",
"last_name": "Laurent",
"primary_email": "camille@payfit.com",
"phone": null,
"title": "Head of Sales",
"company": "Payfit",
"company_id": null,
"avatar_url": null,
"lead_score": 0,
"lead_status": "cold",
"pipeline_stage": "new_leads",
"lifecycle_stage": "lead",
"assigned_to": null,
"primary_source": "manual",
"last_contact_at": null,
"created_at": "2026-10-07T13:22:38.585893+00:00",
"linkedin_profile_url": null,
"country": null,
"city": null,
"tags": [
"inbound"
]
}/contacts/upsertCreate or update a contact by email
The safest call for syncing from another tool: creates the contact, or updates every field you send on the existing one with the same email. The response has created: true or false.
Body
emailstringrequired- Email address used to find the contact.
first_namestring- First name.
last_namestring- Last name.
display_namestring- Full name as shown in the app. Built from first and last name when omitted.
phonestring- Phone number, ideally in international format (
+33612345678). titlestring- Job title.
companystring- Company name as written on the contact. Meetzy links the contact to its company when it is clear (email domain of one company, else exactly the same name) unless
associate_companyis false. company_iduuid- Link to an existing company.
company_websitestring- Company website, used to find the company by domain.
lifecycle_stagestring- Where the person is in the funnel:
subscriber,lead,mql,sql,opportunity,customer,evangelist,churned,other. Defaultlead. pipeline_stagestring- Stage on the CRM board of their sales cycle (see Sales cycles). Default
new_leads. sales_cycle_idstring- Sales cycle the contact belongs to (
defaultor a cycle id fromGET /crm/cycles). lead_statusstring- Temperature:
hot,warmorcold. Defaultcold. Setting it by hand stops the automatic temperature. lead_scoreinteger- Score from 0 to 100. Usually moved by scoring and workflows.
assigned_tostring- Owner — email of a teammate.
countrystring- Country.
citystring- City.
regionstring- Region or state.
headlinestring- Professional headline (LinkedIn).
linkedin_profile_urlstring- LinkedIn profile URL — needed for LinkedIn steps.
tagsstring[]- Free labels, e.g.
["inbound", "webinar"]. custom_propertiesobject- Values of your custom properties, keyed by property key (see Properties).
do_not_contactboolean- Never email or message this person (sequences and campaigns skip them).
reminder_datedate- Follow-up date (
YYYY-MM-DD) shown in Follow-ups. reminder_notestring- What the follow-up is about.
reminder_assigned_tostring- Teammate who should do the follow-up (email).
label_iduuid- CRM board label.
notesstring- Free text notes field (for timestamped notes use
POST /contacts/{id}/notes). secondary_emailsstring[]- Other addresses of the same person — their emails are matched to this contact.
instagram_usernamestring- Instagram handle.
facebook_usernamestring- Facebook handle.
twitter_usernamestring- X / Twitter handle.
tiktok_usernamestring- TikTok handle.
threads_usernamestring- Threads handle.
curl -X POST "https://meetzy.me/api/v1/contacts/upsert" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "email": "camille@payfit.com", "phone": "+33612345678", "lead_score": 55, "tags": [ "inbound", "demo-requested" ] }'
const res = await fetch("https://meetzy.me/api/v1/contacts/upsert", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "email": "camille@payfit.com", "phone": "+33612345678", "lead_score": 55, "tags": [ "inbound", "demo-requested" ] }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts/upsert",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"email": "camille@payfit.com",
"phone": "+33612345678",
"lead_score": 55,
"tags": ["inbound", "demo-requested"]
},
)
data = res.json(){
"id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"display_name": "Camille Laurent",
"first_name": "Camille",
"last_name": "Laurent",
"primary_email": "camille@payfit.com",
"phone": "+33612345678",
"title": "Head of Sales",
"company": "Payfit",
"company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
"avatar_url": null,
"lead_score": 0,
"lead_status": "cold",
"pipeline_stage": "new_leads",
"lifecycle_stage": "lead",
"assigned_to": null,
"primary_source": "manual",
"last_contact_at": null,
"created_at": "2026-10-07T13:22:38.585893+00:00",
"linkedin_profile_url": null,
"country": null,
"city": null,
"tags": [
"inbound"
],
"created": false
}/contacts/{id}Get a contact (360° view)
Everything about one person: their record (with email engagement totals, LinkedIn status and AI summary), their company with company_summary (last 12 months bought, last order, orders, open quotes, unpaid — from any ERP or shop synced), deals, tasks, timeline activities, notes, sequence enrollments and the CRM board context (sales cycle, stages, labels).
Path parameters
idstringrequired- Id of the record (UUID).
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/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/contacts/e43414d6-f56f-42be-a64c-a836d6015efc",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"contact": {
"id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"display_name": "Camille Laurent",
"first_name": "Camille",
"last_name": "Laurent",
"primary_email": "camille@payfit.com",
"phone": "+33612345678",
"title": "Head of Sales",
"company": "Payfit",
"company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
"avatar_url": null,
"lead_score": 0,
"lead_status": "cold",
"pipeline_stage": "new_leads",
"lifecycle_stage": "lead",
"assigned_to": null,
"primary_source": "manual",
"last_contact_at": null,
"created_at": "2026-10-07T13:22:38.585893+00:00",
"linkedin_profile_url": null,
"country": null,
"city": null,
"tags": [
"inbound"
],
"headline": null,
"about": null,
"seniority": null,
"organization_industry": null,
"organization_num_employees": null,
"company_website": null,
"total_emails_sent": 0,
"total_emails_opened": 0,
"total_emails_clicked": 0,
"total_email_replies": 0,
"total_website_visits": 0,
"total_meetings_booked": 0,
"linkedin_connection_status": null,
"score_breakdown": {},
"ai_summary": null,
"custom_properties": {},
"do_not_contact": false,
"reminder_date": null,
"reminder_note": null,
"reminder_assigned_to": null,
"label_id": null,
"pipeline_history": [],
"pipeline_changed_at": null,
"pipeline_changed_by": null,
"assigned_at": null,
"added_at": "2026-10-07T13:22:38.553+00:00",
"secondary_emails": null,
"instagram_username": null,
"facebook_username": null,
"twitter_username": null,
"tiktok_username": null,
"threads_username": null
},
"company": {
"id": "166c436d-a874-4730-a0d8-c8d7fa090268",
"user_from": "acme",
"name": "Payfit",
"domain": "payfit.com",
"website": null,
"industry": "Software",
"employees": 42,
"annual_revenue": null,
"country": null,
"city": null,
"address": null,
"phone": null,
"linkedin_url": null,
"description": null,
"logo_url": null,
"owner_email": "olivia@acme.com",
"lifecycle_stage": "lead",
"company_type": "prospect",
"tier": "B",
"health_score": null,
"tags": [
"api",
"vip"
],
"custom": {},
"parent_company_id": null,
"apollo_id": null,
"last_activity_at": null,
"created_by": "olivia@acme.com",
"created_at": "2026-10-07T13:22:31.105534+00:00",
"updated_at": "2026-10-07T13:22:37.766452+00:00"
},
"deals": [],
"tasks": [],
"activities": [],
"notes": [],
"enrollments": [],
"crm": {
"cycle_id": "default",
"cycles": [
{
"id": "default",
"name": "Main pipeline",
"color": "#007AFF",
"is_default": true,
"stages": [
{
"id": "new_leads",
"name": "New leads",
"color": "#8E8E93",
"fixed": true
},
{
"id": "in_discussion",
"name": "In discussion",
"description": null,
"color": "#5856D6",
"won": false
},
{
"id": "negotiation",
"name": "Negotiation",
"description": null,
"color": "#007AFF",
"won": false
}
],
"count": 1
}
],
"multi_supported": true,
"stages": [
{
"id": "new_leads",
"name": "New leads",
"color": "#8E8E93",
"fixed": true
},
{
"id": "in_discussion",
"name": "In discussion",
"description": null,
"color": "#5856D6",
"won": false
},
{
"id": "negotiation",
"name": "Negotiation",
"description": null,
"color": "#007AFF",
"won": false
}
],
"labels": []
}
}/contacts/{id}Update a contact
Send only the fields to change. Moving pipeline_stage records the move in the stage history; changing assigned_to sets the assignment date. Changes fire events (contact.stage_changed, contact.owner_changed…) that workflows and webhooks react to.
Path parameters
idstringrequired- Id of the record (UUID).
Body
first_namestring- First name.
last_namestring- Last name.
display_namestring- Full name as shown in the app. Built from first and last name when omitted.
phonestring- Phone number, ideally in international format (
+33612345678). titlestring- Job title.
companystring- Company name as written on the contact. Meetzy links the contact to its company when it is clear (email domain of one company, else exactly the same name) unless
associate_companyis false. company_iduuid- Link to an existing company.
company_websitestring- Company website, used to find the company by domain.
lifecycle_stagestring- Where the person is in the funnel:
subscriber,lead,mql,sql,opportunity,customer,evangelist,churned,other. Defaultlead. pipeline_stagestring- Stage on the CRM board of their sales cycle (see Sales cycles). Default
new_leads. sales_cycle_idstring- Sales cycle the contact belongs to (
defaultor a cycle id fromGET /crm/cycles). lead_statusstring- Temperature:
hot,warmorcold. Defaultcold. Setting it by hand stops the automatic temperature. lead_scoreinteger- Score from 0 to 100. Usually moved by scoring and workflows.
assigned_tostring- Owner — email of a teammate.
countrystring- Country.
citystring- City.
regionstring- Region or state.
headlinestring- Professional headline (LinkedIn).
linkedin_profile_urlstring- LinkedIn profile URL — needed for LinkedIn steps.
tagsstring[]- Free labels, e.g.
["inbound", "webinar"]. custom_propertiesobject- Values of your custom properties, keyed by property key (see Properties).
do_not_contactboolean- Never email or message this person (sequences and campaigns skip them).
reminder_datedate- Follow-up date (
YYYY-MM-DD) shown in Follow-ups. reminder_notestring- What the follow-up is about.
reminder_assigned_tostring- Teammate who should do the follow-up (email).
label_iduuid- CRM board label.
notesstring- Free text notes field (for timestamped notes use
POST /contacts/{id}/notes). secondary_emailsstring[]- Other addresses of the same person — their emails are matched to this contact.
instagram_usernamestring- Instagram handle.
facebook_usernamestring- Facebook handle.
twitter_usernamestring- X / Twitter handle.
tiktok_usernamestring- TikTok handle.
threads_usernamestring- Threads handle.
curl -X PATCH "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lifecycle_stage": "sql", "assigned_to": "olivia@acme.com", "reminder_date": "2026-10-14", "reminder_note": "Send the pricing" }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc", { method: "PATCH", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "lifecycle_stage": "sql", "assigned_to": "olivia@acme.com", "reminder_date": "2026-10-14", "reminder_note": "Send the pricing" }), }); const data = await res.json();
import os, requests
res = requests.patch(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"lifecycle_stage": "sql",
"assigned_to": "olivia@acme.com",
"reminder_date": "2026-10-14",
"reminder_note": "Send the pricing"
},
)
data = res.json(){
"id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"display_name": "Camille Laurent",
"first_name": "Camille",
"last_name": "Laurent",
"primary_email": "camille@payfit.com",
"phone": "+33612345678",
"title": "Head of Sales",
"company": "Payfit",
"company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
"avatar_url": null,
"lead_score": 40,
"lead_status": "cold",
"pipeline_stage": "new_leads",
"lifecycle_stage": "mql",
"assigned_to": null,
"primary_source": "manual",
"last_contact_at": null,
"created_at": "2026-10-07T13:22:38.585893+00:00",
"linkedin_profile_url": null,
"country": null,
"city": null,
"tags": [
"inbound"
]
}/contacts/{id}Delete a contact
Deletes the contact permanently. Its deals and tasks stay, without the link.
Path parameters
idstringrequired- Id of the record (UUID).
curl -X DELETE "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc", { method: "DELETE", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` }, }); const data = await res.json();
import os, requests
res = requests.delete(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"deleted": true
}/contacts/{id}/notesAdd a note
Adds a timestamped note on the contact, signed by the key’s user. Notes show on the timeline and fire contact.note_added.
Path parameters
idstringrequired- Id of the record (UUID).
Body
contentstringrequired- Text of the note. Also accepted as
note.
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/notes" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Met at the Paris fair — wants a demo in November." }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/notes", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "content": "Met at the Paris fair — wants a demo in November." }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/notes",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"content": "Met at the Paris fair — wants a demo in November."
},
)
data = res.json(){
"id": "e1c95777-748f-40ba-a93e-d272c644e0f1",
"lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
"user_from": "acme",
"author_email": "olivia@acme.com",
"author_name": "Olivia Martin",
"content": "Met at the fair",
"mentions": [],
"created_at": "2026-10-07T13:22:43.291381+00:00",
"updated_at": "2026-10-07T13:22:43.291381+00:00",
"read_by": []
}/contacts/{id}/interactionsEverything that happened with a contact
One feed, newest first, beyond logged activities: website visits and forms, email opens, clicks, replies, bounces and unsubscribes, LinkedIn invitation, connection and messages, WhatsApp messages, meetings, sequences joined or left, stage, owner and status changes, deals, quotes and tasks. Plus a summary (visits, opens, clicks, messages, last inbound).
Path parameters
idstringrequired- Id of the record (UUID).
Query parameters
socialstring0to skip reading LinkedIn and WhatsApp messages live (faster). Default on.
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/interactions" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/interactions", {
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/interactions",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"items": [
{
"id": "ev-3295",
"type": "system",
"subject": "Lifecycle: mql",
"occurred_at": "2026-10-07T13:22:42.488773+00:00",
"actor_email": null
},
{
"id": "ev-3291",
"type": "system",
"subject": "Added to the CRM",
"occurred_at": "2026-10-07T13:22:38.585893+00:00",
"actor_email": null
}
],
"summary": {
"website_visits": 0,
"email_opens": 0,
"email_clicks": 0,
"linkedin_messages": 0,
"whatsapp_messages": 0,
"meetings": 0,
"last_30_days": 2,
"last_inbound_at": null
}
}/contacts/{id}/copilotWhat to do next with a contact
The lead copilot reads everything Meetzy knows and answers with ONE next step (next) and the other suggestions (rules), each with why, often how (the stage’s playbook, their usual basket) and an action. It looks at every conversation wherever it happened — the team’s mailboxes, the key’s user’s WhatsApp and LinkedIn, logged calls and meetings, sequences — to know who wrote last and on which channel; at the contact’s sales cycle and what its next stage takes (an order form, a demo, a proforma…); at what the ERP says about their company (order rhythm, usual basket, reorder due or late, orders that arrived while the lead sat in an early stage, open quotes, unpaid invoices, colleagues already in touch); and at follow-ups, tasks, order forms, quotes, deals and meetings. signals carries those facts; priority the 0-100 score with its reasons. When a channel knew a newer touch than the CRM, the contact’s last_contact_at is updated (lead_patch).
Path parameters
idstringrequired- Id of the record (UUID).
action.type: message (open the conversation on channel), email, task, reminder, stage, cycle_stage, assign_me, deal, order_form, company or link.
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/copilot" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/copilot", {
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/copilot",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"priority": {
"score": 71,
"level": "now",
"reasons": [
"Hot",
"Reorder late"
]
},
"next": {
"id": "reorder_late",
"score": 90,
"tone": "amber",
"channel": "whatsapp",
"title": "Reorder 23 days late",
"why": "Orders about every 62 days — last one 30 Jul, €4,180. It was expected around 30 Sep and has not come.",
"how": "Usually: Erba Pura EDP 100ML, Naxos EDP 100ML · about €4,200 an order. Ask if something changed.",
"action": {
"type": "message",
"channel": "whatsapp",
"label": "Open WhatsApp"
}
},
"rules": [
{
"id": "follow_up",
"score": 80,
"tone": "blue",
"channel": "whatsapp",
"title": "Follow up with Camille on WhatsApp",
"why": "You wrote 6 days ago and had no answer.",
"action": {
"type": "message",
"channel": "whatsapp",
"label": "Open WhatsApp"
}
}
],
"signals": {
"ball": "ours",
"last_touch": {
"channel": "whatsapp",
"direction": "out",
"at": "2026-10-02T09:12:00Z",
"days": 6
},
"unanswered_outbound": 1,
"stage": {
"cycle": "Already client",
"name": "Follow-up",
"days": 4,
"next": {
"name": "Order form Sent",
"kind": "document",
"object": "order_form",
"verb": "send"
}
},
"buying": {
"status": "at_risk",
"last_order": {
"date": "2026-07-30",
"amount": 4180
},
"rhythm": {
"every": 62,
"usual_amount": 4200,
"next": "2026-09-30",
"lateness": 0.37
}
}
},
"lead_patch": null,
"ai_available": true,
"ai": null
}/contacts/{id}/copilotWhat to do next, with the AI’s read
Same as GET, plus ai: a summary, a temperature, a next action, risks, a ready email and — when WhatsApp or LinkedIn is the right channel — a short chat message, all written from the same facts. Uses AI credits.
Path parameters
idstringrequired- Id of the record (UUID).
Works with a read-only key: it changes nothing in the CRM.
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/copilot" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/copilot", { 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/copilot",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()See the notes on the left.
/contacts/{id}/associate-companyLink the contact to its company
Links the contact when its company is clear: the website or email domain of exactly one company, else exactly the same company name. Nothing is created; ambiguous is true when several companies match (choose with PUT /contacts/{id}/company).
Path parameters
idstringrequired- Id of the record (UUID).
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/associate-company" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/associate-company", { 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/associate-company",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"company_id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"company_name": "Lumière Paris",
"created": false,
"ambiguous": false
}/contacts/{id}/company-suggestionsCompanies this contact may belong to
The companies matching the contact’s email domain (reason: domain) or company name (reason: name), best when one is clear, and with q a search by name, domain or ERP code.
Path parameters
idstringrequired- Id of the record (UUID).
Query parameters
qstring- Search companies.
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/company-suggestions" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/company-suggestions", {
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/company-suggestions",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"current": null,
"link": null,
"domain": "lumiere.fr",
"best": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"suggested": [
{
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr",
"code": "C000412",
"reason": "domain"
}
],
"results": [],
"create": {
"name": "Lumière",
"domain": "lumiere.fr"
}
}/contacts/{id}/companiesAll the contact’s companies
A contact can work for several companies: primary is their main company (company_id, used by default everywhere), others the rest. The contact shows on each of them (people, timeline, counts).
Path parameters
idstringrequired- Id of the record (UUID).
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies", {
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/companies",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"primary": {
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr"
},
"others": [
{
"id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a",
"name": "Lumière Group",
"domain": "lumiere-group.com"
}
]
}/contacts/{id}/companiesAdd a company to the contact
Links one more company. The first company of a contact becomes its main one. create makes the company (or reuses the one with the same domain or name).
Path parameters
idstringrequired- Id of the record (UUID).
Body
company_iduuid- The company.
createobject{ name, domain }to create it instead.
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "company_id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a" }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "company_id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a" }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"company_id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a"
},
)
data = res.json(){
"primary": {
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr"
},
"others": [
{
"id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a",
"name": "Lumière Group",
"domain": "lumiere-group.com"
}
],
"added": {
"id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a",
"name": "Lumière Group",
"domain": "lumiere-group.com"
},
"existing": false
}/contacts/{id}/companies/{companyId}Remove a company from the contact
Removing the main company makes the next one the main one.
Path parameters
idstringrequired- Id of the record (UUID).
companyIdstringrequired- Id of the company (UUID).
curl -X DELETE "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies/%7BcompanyId%7D" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies/%7BcompanyId%7D", { method: "DELETE", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` }, }); const data = await res.json();
import os, requests
res = requests.delete(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies/%7BcompanyId%7D",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"primary": {
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr"
},
"others": []
}/contacts/{id}/companies/{companyId}/mainMake it the main company
One of the contact’s other companies becomes the main one; the previous main one stays among the others.
Path parameters
idstringrequired- Id of the record (UUID).
companyIdstringrequired- Id of the company (UUID).
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies/%7BcompanyId%7D/main" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/companies/%7BcompanyId%7D/main", { 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/companies/%7BcompanyId%7D/main",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"primary": {
"id": "9d8e7f6a-5b4c-4d3e-8f2a-1b0c9d8e7f6a",
"name": "Lumière Group",
"domain": "lumiere-group.com"
},
"others": [
{
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr"
}
]
}/contacts/{id}/companyChoose the contact’s company
Links the contact to a company by hand — from then on, automatic linking leaves this contact alone. company_id: null unlinks it; create makes a new company (or reuses the one with the same domain or name).
Path parameters
idstringrequired- Id of the record (UUID).
Body
company_iduuid- The company, or
nullto unlink. createobject{ name, domain }to create the company instead.
curl -X PUT "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/company" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "company_id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636" }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/company", { method: "PUT", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "company_id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636" }), }); const data = await res.json();
import os, requests
res = requests.put(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/company",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"company_id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636"
},
)
data = res.json(){
"company_id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"company": {
"id": "3cdc3e21-931a-4e8b-a189-3cab5dfbd636",
"name": "Lumière Paris",
"domain": "lumiere.fr"
},
"existing": false
}/contacts/{id}/emailSend an email to a contact
Sends one email now from the key user’s connected mailbox, with open and click tracking, and logs it on the timeline. Use a template or write a subject and body; merge tags like {{contact.first_name}} are filled. To reply inside an existing thread with attachments, use Mailbox › contact threads.
Path parameters
idstringrequired- Id of the record (UUID).
Body
subjectstring- Subject. Required without
template_id. bodystring- Body, plain text or HTML. Required without
template_id. template_iduuid- Email template to use (its subject and body fill what you leave empty).
deal_iduuid- Deal the email is about —
{{deal.*}}tags become available. trackboolean- Track opens and clicks. Default
true.
curl -X POST "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/email" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "subject": "Your demo, {{contact.first_name}}", "body": "Hi {{contact.first_name}},\n\nHere is the recording of today’s demo…", "track": true }'
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/email", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "subject": "Your demo, {{contact.first_name}}", "body": "Hi {{contact.first_name}},\n\nHere is the recording of today’s demo…", "track": true }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/email",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"subject": "Your demo, {{contact.first_name}}",
"body": "Hi {{contact.first_name}},\n\nHere is the recording of today’s demo…",
"track": True
},
)
data = res.json(){
"sent": true,
"from": "olivia@acme.com",
"subject": "Your demo, Camille",
"send_id": "9b1f0c52-3c1e-4a8e-a2f1-6f0b2c7d1e44"
}/contacts/{id}/emailsEmails sent to a contact
Emails Meetzy sent to this person (campaigns, workflows, one-off sends) with their status, opens, clicks and replies, and the mailing lists they are on.
Path parameters
idstringrequired- Id of the record (UUID).
curl "https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/emails" \ -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/contacts/e43414d6-f56f-42be-a64c-a836d6015efc/emails", {
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/emails",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json(){
"sends": [],
"lists": []
}/contacts/bulk/enrollEnroll contacts in a sequence
Same as POST /sequences/{id}/enroll, with the sequence in the body. Contacts already in the sequence or marked do-not-contact are skipped and listed.
Body
sequence_iduuidrequired- Sequence.
contact_idsuuid[]required- Contacts to enroll.
curl -X POST "https://meetzy.me/api/v1/contacts/bulk/enroll" \ -H "Authorization: Bearer $MEETZY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "sequence_id": "4b3c7a10-5d5e-4f43-9b0e-1a2b3c4d5e6f", "contact_ids": [ "e43414d6-f56f-42be-a64c-a836d6015efc" ] }'
const res = await fetch("https://meetzy.me/api/v1/contacts/bulk/enroll", { method: "POST", headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "sequence_id": "4b3c7a10-5d5e-4f43-9b0e-1a2b3c4d5e6f", "contact_ids": [ "e43414d6-f56f-42be-a64c-a836d6015efc" ] }), }); const data = await res.json();
import os, requests
res = requests.post(
"https://meetzy.me/api/v1/contacts/bulk/enroll",
headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
json={
"sequence_id": "4b3c7a10-5d5e-4f43-9b0e-1a2b3c4d5e6f",
"contact_ids": ["e43414d6-f56f-42be-a64c-a836d6015efc"]
},
)
data = res.json(){
"enrolled": 1,
"skipped": []
}