The Syncdo API for leads, deals and webhooks
Bring leads in from your own systems, and get events out the moment they happen.
curl -X POST https://api.syncdo.co/v1/leads \
-H "Authorization: Bearer sya_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "phone": "+1 555 555 0123", "name": "Avery Stone",
"company": "Northwind Studio" }'
HTTP/1.1 201
{ "ok": true, "created": true, "lead": { … } }What it does
Create leads
Exactly like a form enquiry: a known number is updated, never duplicated.
{ "ok": true, "created": true, "result": "created",
"lead": { "name": "Avery Stone", "stage": "New",
"company": "Northwind Studio", "source": "inbound:Zapier" } }Find and update
By phone, email, name or when added; your own fields by key.
GET /v1/leads?phone=%2B15555550123
GET /v1/leads?q=northwindNotes and stages
Add notes and move a lead's stage.
Deals
Open, edit and close deals; read the pipeline.
Reminders
Open reminders due today, overdue or upcoming.
Webhooks out
Pick the events: new lead, stage changed, deal won, deal lost, reminder due. Each is posted as JSON, usually within a minute.
- Signed with your secret, so you can check it came from Syncdo.
- Retried 7 times, from at once to after 12 hours.
- Every delivery listed for 30 days, with Resend.
- Send test event, before anything real happens.
POST https://example.com/hooks/syncdo
Syncdo-Event: lead.stage_changed
Syncdo-Signature: t=1791364500,v1=5d2a…
{ "type": "lead.stage_changed",
"created_at": "2026-10-07T09:15:00.000Z",
"data": { "lead": { … },
"change": { "from": "New", "to": "Contacted" } } }Limits, said up front
120 a minute
Requests of each kind, shared by the workspace's keys.
60 new leads a minute
Per key.
Every refusal says why
In a sentence, not a bare code.
Getting started
The owner makes an API key in Settings → API & webhooks — one key for each tool, named after it (“Zapier”, “Website”, “n8n”). The key is shown once. Every request goes to https://api.syncdo.co/v1 with JSON bodies.
GET /v1/me is the call to make when a tool asks you to test the connection.
Authentication
Send the key in the Authorization header: Authorization: Bearer sya_…. A key belongs to the workspace, not to a person, and can read and change every lead in it — keep it on a server, never in a web page. The owner can pause a key (calls are refused until it is resumed) or revoke it (final). What a key created stays, and each lead's history says “API: <key name>” for every change it made.
An API key works only under /v1, and /v1 takes only API keys.
Errors and limits
Every answer has ok. A failure also has error (a code to branch on) and message (a sentence to show a person).
Up to 120 requests a minute for each kind of request (for example, all POST /v1/leads) in a workspace, shared by all its keys. Every answer carries X-RateLimit-Limit and X-RateLimit-Remaining. Creating leads is also limited to 60 a minute per key.
Leads
Wherever a request names a lead (:lead), send its phone number in any format (with its country code) or its id.
The lead object
fields holds the workspace's own lead fields (see GET /v1/fields); the built-in ones are at the top level.
Create a lead — POST /v1/leads
A lead sent here arrives exactly like an enquiry from a website form: a number that is already a lead updates that lead instead of creating a second one, and the key's settings decide who gets a new lead and what happens to fields the lead already has. Only phone is required.
Answers: 201 created; 200 with "result": "updated" for a number that was already a lead; 200 with "duplicate": true for a repeat. Fields Syncdo does not take are listed back inignored_fields; a key under fields that the workspace does not have is listed as fields.key. Unlike PATCH, a value that does not fit its field does not refuse the lead: that field is left out and listed inrejected_fields, as { "field": "fields.budget", "message": "Budget: send a number." }, and the lead is saved with the rest — the same as from a webhook or a Google Sheet. Errors: phone_required, contact_limit_reached (the plan's contact limit).
Find leads — GET /v1/leads
Newest first. limit is 1–100 (25 by default); pass next_cursor back as cursor for the next page.
Filters combine (all must match), and work with cursor.
Get one lead — GET /v1/leads/:lead
include=timeline adds the lead's last 10 events, newest first, each in the words the Syncdo dashboard uses (by is who did it, when that is known), and its next open reminder (null when there is none). Without it the answer is just the lead.
Update a lead — PATCH /v1/leads/:lead
Send name, email, company, city, state and the workspace's own fields underfields. A value you send replaces what is there; a blank name never erases a name. Each field is checked against its type — a number, a date as YYYY-MM-DD, true/false, one of a dropdown's options, or a list of words for tags. A field the workspace does not have is refused by name (unknown_field) rather than stored where nobody would see it. Stages have their own request.
Notes
A note is up to 4000 characters.
Stages and fields
A stage must be one of the workspace's own (any capitalisation). Moving a stage through the API runs the workspace’s rules as any move does.
Deals
A lead has at most one open deal (deal_already_open). A new deal is assigned to the person the lead is assigned to. Withoutcurrency the workspace's currency is used. A won deal needs the value it closed at; a lost deal needs a reason; cancelled needs neither. A closed deal cannot be edited (deal_not_open).
Reminders
Open reminders, earliest first. due is today, overdue (due before now), upcoming (after today) or today_and_overdue (the default). “Today” is today in the workspace's time zone (Settings → General), which the answer names. Filter by lead (phone or id) and assigned_to (a member's id, or none); limit 1–100 and cursor as for leads. On the plans with reminders (not Free: plan_required).
Pipeline
Leads in each of the workspace's stages, in its order (leads in a stage that is no longer one are listed apart); deals open now, and won and lost this month in the workspace's time zone, with totals per currency — the same numbers as Reports. deals is null, with deals_unavailable saying why, on a plan without deals.
Webhooks
The owner adds an endpoint in Settings → API & webhooks — a name, an https URL and the events to send — and is shown its signing secret once. Syncdo then posts each event to the URL as JSON, usually within a minute of it happening.
Answer with any 2xx within 10 seconds. Anything else — a timeout, an error, a redirect (they are not followed) — is tried again after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours: 7 attempts in all. id is the same on every attempt, so a receiver can ignore one it has already handled. Events may arrive out of order.
An endpoint that fails 20 times in a row over at least a day is turned off, and the settings page says why; an answer of410 Gone turns it off at once (that is how an app says it has been disconnected). The owner turns it back on with one click; events from then on are sent. Pausing an endpoint cancels the deliveries waiting to be retried, and events that happen while it is paused are not sent; any delivery can be sent again from its log (kept 30 days).
Checking a signature
Syncdo-Signature is t=<unix seconds>,v1=<signature>, where the signature is the hex HMAC-SHA256 of <t>.<the raw request body> with the endpoint's secret. Check it against the body exactly as received, and refuse a t more than five minutes old.
Subscriptions for apps
An integration app can subscribe to events with its own key, instead of someone adding an endpoint by hand. A subscription is an endpoint like any other — the owner sees it in Settings → API & webhooks — and a key sees and removes only the subscriptions it made.
For a polling trigger instead, ask for GET /v1/leads?created_since=… and keep the newest created_at you have seen.
Claude and ChatGPT (MCP)
Syncdo is also an MCP server, so a person can ask Claude, ChatGPT or another app that speaks the Model Context Protocol about their leads: “Who should I follow up with today?”, “What's happening with Avery Stone?”, “How did this month go?”. It is read only — nothing it does sends a WhatsApp message or changes anything — and it needs no API key: each person connects their own Syncdo login, and the app sees exactly what that person sees in Syncdo (with “Reps see only leads assigned to them” on, a rep's app sees only their leads).
Add it as a custom connector in the app. The app opens a Syncdo page that asks the person to sign in (as usual) and to allow it; they can disconnect it at any time in Settings → My account → Connected apps, and the workspace owner sees and can disconnect every member's apps in Settings → API & webhooks. On the paid plans, like the API — and, unlike the API, it is being turned on one workspace at a time: where it is not on yet, the Syncdo page says so.
For the people who build MCP clients: Streamable HTTP at POST /mcp (JSON answers, no session; protocol versions 2025-11-25, 2025-06-18 and 2025-03-26), and OAuth 2.1 with Syncdo as its own authorization server — protected resource metadata at /.well-known/oauth-protected-resource/mcp (a 401 from /mcp points there), authorization server metadata at /.well-known/oauth-authorization-server, dynamic client registration at /oauth/register (public clients; redirect URIs https, or http on localhost), the authorization code flow with PKCE (S256 only) and resource = the connector URL, access tokens for an hour and refresh tokens for 30 days (a new one on every refresh), and revocation at /oauth/revoke.
Questions: support@syncdo.co · Help for developers
Questions, answered
What is the Syncdo API?
It lets your own systems create, read and update leads, notes and deals in Syncdo. Webhooks send events back to you as they happen.
Which plan do I need?
Essentials or Intelligence. The workspace owner makes keys under Settings, then API & webhooks.
How do I get a key?
Make a new API key with a name and who gets its leads. It starts with sya_ and is shown once.
Do I need the API for a website form?
No. An inbound webhook URL takes form submissions directly, with no key.
Is there a Zapier or Make app?
Not yet. Their HTTP and webhook steps work with an API key and with webhooks today.