Back to site
Syncro

Leads

Endpoints to create, fetch, update and move leads (deals) through the pipeline, plus tags, sequences and per-lead WhatsApp sending.

Base URLhttps://app.syncro.chat/api/v1AuthX-API-Key: crm_SUA_CHAVE_AQUI

The Lead object

Most endpoints return the lead in this base format (additional fields are added via ?include):

{
  "id": 123,
  "name": "João Silva",
  "phone": "+5511999887766",
  "email": "[email protected]",
  "company": "ACME",
  "birthday": "1990-01-15",
  "value": 5000.0,
  "source": "site",
  "tags": ["vip", "enterprise"],
  "pipeline_id": 1,
  "stage_id": 5,
  "notes": "Anotações do lead",
  "utm_source": "google",
  "utm_medium": "cpc",
  "utm_campaign": "verao_2026",
  "utm_term": null,
  "utm_content": null,
  "stage": { "id": 5, "name": "Proposta" },
  "pipeline": { "id": 1, "name": "Vendas" },
  "created_at": "2026-06-30T10:00:00Z",
  "custom_fields": { "tamanho_empresa": "100+" }
}

List leads

GET/leads
Permission: leads:read

Lists the account leads, paginated, with filters.

Query parameters

pipeline_idintegeroptional
Filters by pipeline
stage_idintegeroptional
Filters by stage
assigned_tointegeroptional
Filters by the assignee ID
sourcestringoptional
Filters by source
statusstringoptional
Filters by status
tagsarrayoptional
Tags (names); returns leads with **any** of them
qstringoptional
Search by name, email or phone
updated_sincedate (ISO 8601)optional
Only leads changed from this date on (ideal for sync)
created_fromdateoptional
Created from
created_todateoptional
Created until
pageintegeroptional
Page (default 1)
per_pageintegeroptional
Items per page (default 50, max 200)
includestringoptional
Extra relations separated by comma (see below)
Request
curl "https://app.syncro.chat/api/v1/leads?pipeline_id=1&per_page=2&include=owner" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Response
{
  "success": true,
  "data": [
    {
      "id": 123,
      "name": "João Silva",
      "phone": "+5511999887766",
      "email": "[email protected]",
      "company": "ACME",
      "value": 5000,
      "source": "site",
      "tags": [
        "vip"
      ],
      "pipeline_id": 1,
      "stage_id": 5,
      "stage": {
        "id": 5,
        "name": "Proposta"
      },
      "pipeline": {
        "id": 1,
        "name": "Vendas"
      },
      "created_at": "2026-06-30T10:00:00Z",
      "custom_fields": {},
      "assigned_to": 12,
      "owner": {
        "id": 12,
        "name": "Ana",
        "email": "[email protected]"
      }
    }
  ],
  "meta": {
    "total": 250,
    "per_page": 2,
    "current_page": 1,
    "last_page": 125,
    "has_more": true
  }
}

Create lead

POST/leads
Permission: leads:write

Creates a new lead.

Body parameters

namestringrequired
Lead name
pipeline_idintegerrequired
Target pipeline
stage_idintegerrequired
Target stage
phonestringoptional
Phone (E.164 recommended)
emailstringoptional
Email
valuenumberoptional
Deal value
sourcestringoptional
Source
tagsarray(string)optional
Tags
notesstringoptional
Notes
utm_source / utm_medium / utm_campaign / utm_term / utm_contentstringoptional
UTMs
assigned_tointegeroptional
Assignee user ID (from the same account)
custom_fieldsobjectoptional
Map field_name: value (see [Custom fields](/en/custom-fields))
i

If stage_id is a stage marked as won/lost, Syncro automatically creates the corresponding Sale (Sale) or Loss (LostSale).

i

Errors: 422 with limit_reached: true if the plan lead limit has been reached.

Request
curl -X POST "https://app.syncro.chat/api/v1/leads" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "João Silva",
    "phone": "+5511999887766",
    "email": "[email protected]",
    "value": 5000,
    "source": "site",
    "tags": [
      "vip"
    ],
    "pipeline_id": 1,
    "stage_id": 5,
    "assigned_to": 12,
    "custom_fields": {
      "tamanho_empresa": "100+"
    }
  }'
Response
{
  "success": true,
  "lead": {
    "id": 123,
    "name": "João Silva",
    "pipeline_id": 1,
    "stage_id": 5,
    "stage": {
      "id": 5,
      "name": "Proposta"
    },
    "pipeline": {
      "id": 1,
      "name": "Vendas"
    },
    "created_at": "2026-06-30T10:00:00Z",
    "custom_fields": {
      "tamanho_empresa": "100+"
    }
  }
}

Create or update lead (upsert)

POST/leads/upsert
Permission: leads:write

Creates a new lead or updates an existing one, matching by email and/or phone. Ideal for synchronization. Accepts the same fields as POST /leads, plus the field below.

Body parameters

match_bystringoptional
email, phone or email_or_phone (default email_or_phone)
i

You must send email or phone (it is the match key). On update, only the sent (non-empty) fields are changed.

Request
curl -X POST "https://app.syncro.chat/api/v1/leads/upsert" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "João Silva",
    "email": "[email protected]",
    "pipeline_id": 1,
    "stage_id": 5,
    "match_by": "email"
  }'
Response
{
  "success": true,
  "created": true,
  "lead": {
    "id": 123,
    "name": "João Silva",
    "stage_id": 5
  }
}

Fetch lead by ID

GET/leads/123
Permission: leads:read

Returns a lead. Accepts ?include= to load relations.

Request
curl "https://app.syncro.chat/api/v1/leads/123?include=owner%2Ctasks%2Cnotes" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Response
{
  "success": true,
  "lead": {
    "id": 123,
    "name": "João Silva",
    "stage_id": 5
  }
}

Move lead to another stage

PUT/leads/123/stage
Permission: leads:write

Moves the lead to another stage (and pipeline).

Body parameters

stage_idintegerrequired
New stage
pipeline_idintegerrequired
Stage pipeline
i

Errors: 422 with blocked: true and pending_tasks if the current stage has mandatory pending tasks.

Request
curl -X PUT "https://app.syncro.chat/api/v1/leads/123/stage" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "stage_id": 7,
    "pipeline_id": 1
  }'
Response
{
  "success": true,
  "lead_id": 123
}

Mark as won

PUT/leads/123/won
Permission: leads:write

Moves the lead to a won stage and records the sale.

Body parameters

stage_idintegerrequired
Won stage (must have is_won = true)
valuenumberoptional
Sale value (if omitted, uses the lead value)
i

Errors: 422 if the stage is not a won stage ("A etapa informada não é uma etapa de ganho.") or 422 blocked due to mandatory pending tasks.

Request
curl -X PUT "https://app.syncro.chat/api/v1/leads/123/won" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "stage_id": 10,
    "value": 7500
  }'
Response
{
  "success": true,
  "lead_id": 123
}

Mark as lost

PUT/leads/123/lost
Permission: leads:write

Moves the lead to a lost stage and records the reason.

Body parameters

stage_idintegerrequired
Lost stage (must have is_lost = true)
reason_idintegeroptional
Lost reason ID (see lost_reasons in [Pipelines](/en/pipelines))
i

Errors: 422 if the stage is not a lost stage; 422 blocked due to pending tasks.

Request
curl -X PUT "https://app.syncro.chat/api/v1/leads/123/lost" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "stage_id": 11,
    "reason_id": 3
  }'
Response
{
  "success": true,
  "lead_id": 123
}

Delete lead

DELETE/leads/123
Permission: leads:write

Removes the lead.

Request
curl -X DELETE "https://app.syncro.chat/api/v1/leads/123" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Response
{
  "success": true
}

Add tags

POST/leads/123/tags
Permission: leads:write

Adds tags to the lead (keeps the existing ones).

Body parameters

tagsarray(string)required
Tag names (min. 1)
Request
curl -X POST "https://app.syncro.chat/api/v1/leads/123/tags" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "tags": [
      "vip",
      "enterprise"
    ]
  }'
Response
{
  "success": true,
  "lead_id": 123,
  "tags": [
    "vip",
    "enterprise"
  ]
}

Remove a tag

DELETE/leads/123/tags/vip
Permission: leads:write

Removes a tag by name.

Request
curl -X DELETE "https://app.syncro.chat/api/v1/leads/123/tags/vip" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Response
{
  "success": true,
  "lead_id": 123,
  "tags": [
    "enterprise"
  ]
}

Enroll in nurture sequence

POST/leads/123/enroll-sequence
Permission: sequences:write

Enrolls the lead in an active sequence. See the list of sequences in Sequences.

Body parameters

sequence_idintegerrequired
Sequence ID (must be active)
Request
curl -X POST "https://app.syncro.chat/api/v1/leads/123/enroll-sequence" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "sequence_id": 1
  }'
Response
{
  "success": true,
  "lead_id": 123,
  "sequence_id": 1,
  "lead_sequence_id": 45,
  "status": "active",
  "next_step_at": "2026-07-01T10:00:00Z"
}

Remove from sequence

DELETE/leads/123/enroll-sequence/1
Permission: sequences:write

Removes the lead from a sequence.

Request
curl -X DELETE "https://app.syncro.chat/api/v1/leads/123/enroll-sequence/1" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI"
Response
{
  "success": true,
  "lead_id": 123,
  "sequence_id": 1,
  "status": "exited_manual"
}

Send WhatsApp (text or image)

POST/leads/123/send-whatsapp
Permission: whatsapp:write

Sends a text or image message to the lead phone. See connected numbers in WhatsApp.

Body parameters

typestringrequired
text or image
bodystringconditional
Message text (required if there is no media_url)
media_urlstring (URL)conditional
Image URL (required when type=image)
captionstringoptional
Image caption
instance_idintegeroptional
Number to use (if omitted, uses the main one)
i

Errors: 422 if the lead has no phone; 422 with skip_reason: "window_closed" on Official API numbers outside the 24h window (use a template); 502 on provider failure.

Request
curl -X POST "https://app.syncro.chat/api/v1/leads/123/send-whatsapp" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "text",
    "body": "Olá! Tudo bem?",
    "instance_id": 1
  }'
Response
{
  "success": true,
  "conversation_id": 99,
  "message_id": 456,
  "provider_msg_id": "wamid.xyz123"
}

Send template (HSM)

POST/leads/123/send-whatsapp-template
Permission: whatsapp:write

Sends an approved official template (required outside the 24h window on the Official API). See templates in WhatsApp.

Body parameters

template_idintegerrequired
Template ID (must be APPROVED)
variablesarray(string)optional
Body variables, in order
header_media_urlstring (URL)optional
Header media, when the template requires it
instance_idintegeroptional
Number to use
Request
curl -X POST "https://app.syncro.chat/api/v1/leads/123/send-whatsapp-template" \
  -H "X-API-Key: crm_SUA_CHAVE_AQUI" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": 1,
    "variables": [
      "João",
      "Proposta",
      "30/07"
    ],
    "instance_id": 2
  }'
Response
{
  "success": true,
  "conversation_id": 99,
  "message_id": 457,
  "provider_msg_id": "wamid.xyz456",
  "template_name": "lembrete_proposta"
}

Extra relations (`?include`)

On GET /leads and GET /leads/{id}, use ?include= with comma-separated names to load additional data. Unknown tokens are ignored.

include What it adds
owner assigned_to (int) + owner {id, name, email}
products products[] {id, product_id, product_name, quantity, unit_price, discount_percent, total}
contacts contacts[] {id, name, role, phone, email, is_primary}
notes notes_list[] {id, body, author, created_at}
sales sales[] {id, pipeline_id, value, closed_by, closed_at} + lost_sales[] {id, pipeline_id, reason_id, lost_at, lost_by}
tasks tasks[] {id, subject, type, status, priority, due_date, due_time, completed_at, assigned_to}
sequences active_sequence {id, name, current_step, total_steps, status} + sequences[] {id, sequence_id, name, status, next_step_at}
score score (int) + score_updated_at
siblings siblings[] (other deals from the same contact) + contact_totals
events events[] {id, event_type, description, performed_by, created_at}
conversation conversation {id, phone, status, last_message_at, unread_count, instance_id}

events, conversation and siblings are only available on GET /leads/{id} (not in the listing, for cost reasons).