Contacts, Notes and Leads
Your agent already collects the people it talks to. With the Public API your CRM or automation can read them, keep their details current, write notes your team sees in the dashboard, create leads and move them through the statuses you set up, and change when the AI saves a lead. Every endpoint lives under one agent: /v1/agents/{agentId}/….
How do contacts, notes and leads fit together?
- A contact is a person. Mojeeb creates one the first time someone messages the agent or a lead is saved, and recognises them again by their WhatsApp number, Facebook or Instagram id, or phone. That is why the API can update a contact but not create one.
- Notes live on the contact. One timeline follows the person across every conversation and lead. It holds notes written by your team or your integration, and the status changes Mojeeb records when a lead moves.
- A lead is a sales opportunity in the dashboard's Clients table. It belongs to a contact, carries your custom fields, and moves through the statuses you defined for the agent.
See Contacts and Lead management for how your team uses them in the dashboard. To assign, filter and pin leads, or to change the agent's lead fields, see Lead Assignment, Filters and Fields.
How do I find a contact?
List the agent's contacts, newest first. Filter by channel, by search (name, mobile or email), or by creation date with date_from and date_to (dates in UTC, both days included).
curl "https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/contacts?search=sara&limit=20" \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE"
The response is a page: items, plus next_cursor and has_more. Pass next_cursor back as cursor to read the next page. Every field is in the List contacts reference.
How do I update a contact?
PATCH the contact with only the fields you want to change. custom_fields merges key by key, so you can set one field without resending the rest, and a null value clears that field. A mobile number must be E.164, such as +201001234567, and an empty string clears it; another format returns 422 invalid_request_body with param mobile.
curl -X PATCH https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/contacts/CONTACT_ID \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "name": "Sara Example", "custom_fields": { "city": "Cairo" } }'
Email and the Facebook and Instagram ids stay read-only. The mobile can be changed, but it is how Mojeeb matches WhatsApp messages and new leads to this person, so change it only to correct a wrong number: afterwards, a WhatsApp message from the old number no longer matches this contact. See the Update contact reference.
How do I add a note my team will see?
POST the text to the contact's notes. It appears on the contact's timeline in the dashboard straight away.
curl -X POST https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/contacts/CONTACT_ID/notes \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "text": "Asked for a call back on Sunday." }'
A note written with a key is signed by the person who created the key. Only a note's author can edit or delete it, so a key can change that person's notes and no one else's. Status-change notes are records Mojeeb keeps, so nobody can edit or delete them. See the Notes reference.
How do I create a lead?
POST to the agent's leads. Every field is optional. The lead starts in the agent's starting status (new unless your team chose another), unassigned. A phone, when you send one, must be a valid number in E.164, as in the example; Mojeeb links the lead to the contact with that number, or creates a new contact. Another format returns 422 invalid_request_body with param phone. An empty string is the same as leaving the phone out when you create a lead, and clears the phone when you update one.
curl -X POST https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/leads \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "name": "Sara Example", "phone": "+201001234567", "summary": "Wants a quote for 20 units." }'
The response is 201 Created with the lead. See the Create lead reference.
How do I move a lead to another status?
PATCH the lead with its new status. The status must be the value of one of the options of the field keyed status in List lead fields, and a move your team's status flow doesn't allow may be refused. If the list has no status field, or that field has no options, the agent uses the statuses new, processing and completed, and a new lead starts in new.
curl -X PATCH https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/leads/LEAD_ID \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "status": "processing" }'
Mojeeb records the change on the contact's timeline when the lead has a contact. A move to a status the agent doesn't have, or a refused move, returns 422 invalid_request and changes nothing.
In List lead fields, fields with built_in: false are the ones your team added; use their keys in custom_fields. Mojeeb keeps each value as you send it and doesn't check it against the field's type, options or required, so validate against that list before you write. To add, change or remove those fields, see Lead Assignment, Filters and Fields.
How do I delete a lead?
DELETE the lead. It is permanent: there is no undo, and a second delete of the same lead returns 404 not_found. The contact, its notes and the conversation stay, so the person and their history remain in the dashboard.
curl -X DELETE https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/leads/LEAD_ID \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE"
The response is 204 with no body. Status-change notes that name the lead stay on the contact's timeline. If the AI later saves a lead from the same conversation, it is a new lead with a new id. To take a lead out of your team's open work without losing it, move it to a final status such as completed instead. See the Delete a lead reference.
How do I change when the AI saves a lead?
Replace the lead capture prompt. Every agent has the built-in Capture Lead tool, and its prompt tells the AI when a conversation holds a lead and what to write in the lead's summary. It is the same text your team edits under Clients → ⋮ → AI Instructions in the dashboard. Read it with GET and replace it with PATCH.
curl -X PATCH https://api.mojeeb.app/v1/agents/YOUR_AGENT_ID/lead-capture \
-H "Authorization: Bearer mk_live_YOUR_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{ "prompt": "Capture a lead when the customer shares a phone number and asks about prices. In the summary, say what they want and by when." }'
The AI follows the new prompt on its next replies, usually within a minute, and sending the prompt the agent already has changes nothing. Mojeeb stores it without leading or trailing spaces and line breaks. Only the prompt can change: the tool's other settings, its on/off switch included, stay in the dashboard. For the length limits, see the Update the lead capture prompt reference; the Get the lead capture prompt reference covers reading it.
Common questions
Does updating a lead through the API assign it to someone?
No. When a teammate edits an unassigned lead in the dashboard, the lead becomes theirs. An edit through the API never assigns the lead, so your integration doesn't silently hand leads to the person who created the key. To assign a lead on purpose, use its assign endpoint; see Lead Assignment, Filters and Fields.
Why can't I create a contact?
Mojeeb creates contacts itself so one person stays one contact across channels. To add someone by hand, create a lead with their phone number, including the country code: Mojeeb links it to the contact with that number, or creates one.
What does null in custom_fields do?
It sets that one field to null; the key stays. Fields you leave out keep their values. This works the same way for contacts and leads.
Why do some leads always come first?
Pinned leads come first, on the first page only, then the rest newest first; each lead's pinned field says which, and PATCH with pinned pins or unpins a lead. Later pages never contain pinned leads, so if your team pins more leads than your limit, the extra ones aren't returned: use a limit above that number, up to the maximum in the List leads reference.
Can I delete a lead or a contact?
A lead, yes: DELETE removes it permanently, with no undo. A contact, no: deleting a person's record stays in the dashboard, where someone confirms it. You can also delete notes your key's creator wrote.
Why does lead capture return 404 lead_capture_not_found?
The agent has no Capture Lead tool, so it has no lead capture prompt, and its AI doesn't save leads from conversations either. Every agent gets the tool when it is created; if one is missing, contact Mojeeb support to add it.
What if Capture Lead is switched off?
The API still reads and replaces its prompt, but the AI saves no leads until someone switches the tool back on from its card on the Tools page. A key can't switch it, and GET on the lead capture prompt doesn't say whether the tool is on: check its card.
Can I change what Capture Lead saves or where it sends leads?
Where it sends them, no: every capture lands in the agent's Clients table. What it saves follows your lead fields: add, change or remove them through the API (see Lead Assignment, Filters and Fields) or under Edit Columns in the dashboard. The prompt decides when to save and what goes in the summary.
Why does a contact from another agent return 404?
Every contact, note and lead belongs to one agent. Asking for one under a different agent returns 404 not_found, even inside your own company, so ids never reveal data across agents.