Developers
Set your API contextPick a region and space ID once. Every sample fills in your base URL.
Where do I find these?

In Coevera: open your space's API application and choose Show Access. It shows the space ID and the base URL, whose host starts with your region.

From the API: if you know the space ID, the discovery endpoint GET /api/discovery/spaces/{space_id} returns its region and base URLs, without credentials.

Only the region and space ID are kept, in this browser. Never paste a key or password here.

More in the quickstart

REST APILeads and opportunitiesLeads

Potential deals before they are qualified. A lead moves through the steps of a lead process and becomes an opportunity when it is qualified.

Qualifying a lead is a GraphQL action; REST has no action routes. A qualified lead becomes an opportunity with the same id.

What the API requires

A create needs a sales unit as well as name: send owner_id, and the lead takes the owner's unit, or unit_id alone, and the lead waits unassigned in that unit. Without either the API answers HTTP 422, although the spec marks only name as required (docs sandbox, 2026-10-15).

MethodPathOperation
GET/entities/LeadsList leads
POST/entities/LeadsCreate a lead
GET/entities/Leads/{id}Get a lead
PATCH/entities/Leads/{id}Update a lead
DEL/entities/Leads/{id}Delete a lead
POST/entities/Leads/batch-modifyCreate or update leads in a batch
POST/entities/Leads/batch-deleteDelete leads in a batch
POST/entities/Leads/batch-restoreRestore deleted leads

GET List leads

Returns the leads the API application can read, one page at a time.

Query parameters

NameTypeDescription
include-deletedbooleanInclude soft-deleted records. Lists only; get-by-id refuses it.
firstintegerPage size. Default 30, maximum 100; a larger value is refused with HTTP 400, code 117.
lastintegerReturn the last N records of the result; together with first, the last N of the first M. Maximum 100.
beforestringCursor from page_info.start_cursor, to page backwards. URL-encode it.
afterstringCursor from page_info.end_cursor of the previous page. URL-encode it: cursors are base64, and a raw + becomes a space.
expandstringRelated records to return inline instead of their URIs, comma-separated; dots reach nested relations, as in account_relations.account.
order-bystringFields to sort by, comma-separated. A leading - sorts descending, as in -modified; dotted paths sort by related fields.
filterobjectfilter[field]=value. Separate several values with a raw comma (OR), as in filter[name]=north,south. Encode a comma that belongs to a value as %2C. URLSearchParams and Python requests encode every comma, so build the filter part of the query string yourself. Dotted paths filter on related records, as in filter[owner.email]. Encode a + in a value as %2B: query values are form-decoded, so a raw + becomes a space.
filter-opobjectfilter-op[field]=operator, one per field: eq (the default), ieq, not-eq, not-ieq, contains, icontains, starts, istarts, ends, iends, gt, gte, lt, lte, between, null, not-null, empty and not-empty. null, not-null, empty and not-empty take no filter value; gt, gte, lt and lte take exactly one.
load-onlystringFields to return, comma-separated (raw or encoded commas both work here); dots select nested fields, as in owner.id. All fields are returned without it. Lists only: get-by-id refuses it with HTTP 400, code 118.

Responses

200 Page of Lead records.: success, total, page_info, data 400 Bad request 401 Not authenticated 429 Rate limited 500 Server error

GET /entities/Leads
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads?first=10&filter%5Bname%5D=north&filter-op%5Bname%5D=icontains' \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET"
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads?first=10&filter%5Bname%5D=north&filter-op%5Bname%5D=icontains', {
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`)
  }
})
import os

import requests

response = requests.get(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads",
    params={
      "first": "10",
      "filter[name]": "north",
      "filter-op[name]": "icontains"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"])
)

POST Create a lead

Creates one lead and answers 201 with the record. name is required, and a sales unit through owner_id or unit_id.

Query parameters

NameTypeDescription
validation-levelintegerBit mask that relaxes validation on this write. 0 (the default) validates everything. Bits: 2 skip unchanged fields, 4 skip admin-defined validations, 8 allow read-only fields, 16 skip relation checks, 32 skip value checks, 64 skip invalid recalculations, 128 skip step-checklist gates, 256 add conditional field requirements, 512 skip uniqueness checks. Add bits together (20 = 4 + 16); member names and comma lists such as 4,16 work too. A value with an internal-only bit is refused with HTTP 400, code 117.

Request body

The new record's fields. Relations are set by id. Schema createLeadInput; the fields are in Lead fields. Required: name.

Responses

201 The created Lead record.: success, data 400 Bad request 401 Not authenticated 422 Validation failed 429 Rate limited 500 Server error

POST /entities/Leads
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads' \
  --request POST \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Northwind Analytics - CRM rollout",
  "owner_id": "37000000-0000-4000-a000-000000000001",
  "quick_account_name": "Northwind Analytics",
  "quick_email": "northwind@example.com"
}'
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads', {
  method: 'POST',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Northwind Analytics - CRM rollout',
    owner_id: '37000000-0000-4000-a000-000000000001',
    quick_account_name: 'Northwind Analytics',
    quick_email: 'northwind@example.com'
  })
})
import os

import requests

response = requests.post(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads",
    headers={
      "Content-Type": "application/json"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"]),
    json={
      "name": "Northwind Analytics - CRM rollout",
      "owner_id": "37000000-0000-4000-a000-000000000001",
      "quick_account_name": "Northwind Analytics",
      "quick_email": "northwind@example.com"
    }
)

GET Get a lead

Returns one lead by id.

Path parameters

NameTypeDescription
idstring (uuid)Id of the Lead record to retrieve. Required

Query parameters

NameTypeDescription
expandstringRelated records to return inline instead of their URIs, comma-separated; dots reach nested relations. The only parameter this call accepts.

Responses

200 The Lead record.: success, data 400 Bad request 401 Not authenticated 404 Not found 429 Rate limited 500 Server error

GET /entities/Leads/{id}
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001?expand=owner' \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET"
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001?expand=owner', {
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`)
  }
})
import os

import requests

response = requests.get(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001",
    params={
      "expand": "owner"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"])
)

PATCH Update a lead

Changes the fields you send and leaves the rest as they are. Qualifying a lead is a GraphQL action, not an update.

Path parameters

NameTypeDescription
idstring (uuid)Id of the Lead record to update. Required

Query parameters

NameTypeDescription
validation-levelintegerBit mask that relaxes validation on this write. 0 (the default) validates everything. Bits: 2 skip unchanged fields, 4 skip admin-defined validations, 8 allow read-only fields, 16 skip relation checks, 32 skip value checks, 64 skip invalid recalculations, 128 skip step-checklist gates, 256 add conditional field requirements, 512 skip uniqueness checks. Add bits together (20 = 4 + 16); member names and comma lists such as 4,16 work too. A value with an internal-only bit is refused with HTTP 400, code 117.

Request body

The fields to change. Schema updateLeadInput; the fields are in Lead fields.

Responses

200 The changed Lead record.: success, data 400 Bad request 401 Not authenticated 404 Not found 422 Validation failed 429 Rate limited 500 Server error

PATCH /entities/Leads/{id}
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001' \
  --request PATCH \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Northwind lead (renamed)"
}'
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001', {
  method: 'PATCH',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Northwind lead (renamed)'
  })
})
import os

import requests

response = requests.patch(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001",
    headers={
      "Content-Type": "application/json"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"]),
    json={
      "name": "Northwind lead (renamed)"
    }
)

DEL Delete a lead

Soft-deletes one lead and answers with its id.

Path parameters

NameTypeDescription
idstring (uuid)Id of the Lead record to delete. Required

Responses

200 Deletion confirmation.: success, data 400 Bad request 401 Not authenticated 404 Not found 429 Rate limited 500 Server error

DEL /entities/Leads/{id}
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001' \
  --request DELETE \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET"
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001', {
  method: 'DELETE',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`)
  }
})
import os

import requests

response = requests.delete(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/74000000-0000-4000-a000-000000000001",
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"])
)

POST Create or update leads in a batch

An item with an id updates that lead; an item without one creates a lead. By default one invalid item fails the whole call with HTTP 422.

Query parameters

NameTypeDescription
validation-levelintegerBit mask that relaxes validation on this write. 0 (the default) validates everything. Bits: 2 skip unchanged fields, 4 skip admin-defined validations, 8 allow read-only fields, 16 skip relation checks, 32 skip value checks, 64 skip invalid recalculations, 128 skip step-checklist gates, 256 add conditional field requirements, 512 skip uniqueness checks. Add bits together (20 = 4 + 16); member names and comma lists such as 4,16 work too. A value with an internal-only bit is refused with HTTP 400, code 117.
rollback-methodinteger0, the default: one failed item fails the whole batch (HTTP 422, or 404 for an unknown id) and nothing is written. 1: the valid items are written and the call answers 200 with success false and one result per item, an id or an error, in input order. Check every item.

Request body

A JSON array of records: an item with an id updates, an item without one creates. Schema batchLeadInput; the fields are in Lead fields. Required: name.

Responses

200 Result per item, in request order: the id of the created or updated record, or the error.: success, data 400 Bad request 401 Not authenticated 422 Validation failed 429 Rate limited 500 Server error

POST /entities/Leads/batch-modify
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-modify' \
  --request POST \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  --header 'Content-Type: application/json' \
  --data '[
  {
    "name": "Northwind lead"
  },
  {
    "id": "74000000-0000-4000-a000-000000000001",
    "name": "Northwind lead (renamed)"
  }
]'
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-modify', {
  method: 'POST',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify([
    {
      name: 'Northwind lead'
    },
    {
      id: '74000000-0000-4000-a000-000000000001',
      name: 'Northwind lead (renamed)'
    }
  ])
})
import os

import requests

response = requests.post(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-modify",
    headers={
      "Content-Type": "application/json"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"]),
    json=[
      {
        "name": "Northwind lead"
      },
      {
        "id": "74000000-0000-4000-a000-000000000001",
        "name": "Northwind lead (renamed)"
      }
    ]
)

POST Delete leads in a batch

Soft-deletes the leads whose ids are in the body, a JSON array.

Query parameters

NameTypeDescription
rollback-methodinteger0, the default: one failed item fails the whole batch (HTTP 422, or 404 for an unknown id) and nothing is written. 1: the valid items are written and the call answers 200 with success false and one result per item, an id or an error, in input order. Check every item.

Request body

A JSON array of ids.

Responses

200 Result per id, in request order: the id of the deleted record, or the error.: success, data 400 Bad request 401 Not authenticated 404 Not found 422 Validation failed 429 Rate limited 500 Server error

POST /entities/Leads/batch-delete
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-delete' \
  --request POST \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  --header 'Content-Type: application/json' \
  --data '[
  "74000000-0000-4000-a000-000000000001",
  "74000000-0000-4000-a000-000000000002"
]'
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-delete', {
  method: 'POST',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(['74000000-0000-4000-a000-000000000001', '74000000-0000-4000-a000-000000000002'])
})
import os

import requests

response = requests.post(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-delete",
    headers={
      "Content-Type": "application/json"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"]),
    json=[
      "74000000-0000-4000-a000-000000000001",
      "74000000-0000-4000-a000-000000000002"
    ]
)

POST Restore deleted leads

Restores the soft-deleted leads whose ids are in the body, a JSON array.

Query parameters

NameTypeDescription
rollback-methodinteger0, the default: one failed item fails the whole batch (HTTP 422, or 404 for an unknown id) and nothing is written. 1: the valid items are written and the call answers 200 with success false and one result per item, an id or an error, in input order. Check every item.

Request body

A JSON array of ids.

Responses

200 Result per id, in request order: the id of the restored record, or the error.: success, data 400 Bad request 401 Not authenticated 404 Not found 422 Validation failed 429 Rate limited 500 Server error

POST /entities/Leads/batch-restore
curl 'https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-restore' \
  --request POST \
  --user "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  --header 'Content-Type: application/json' \
  --data '[
  "74000000-0000-4000-a000-000000000001",
  "74000000-0000-4000-a000-000000000002"
]'
fetch('https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-restore', {
  method: 'POST',
  headers: {
    Authorization: "Basic " + btoa(`${process.env.COEVERA_API_KEY}:${process.env.COEVERA_API_SECRET}`),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(['74000000-0000-4000-a000-000000000001', '74000000-0000-4000-a000-000000000002'])
})
import os

import requests

response = requests.post(
    "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}/entities/Leads/batch-restore",
    headers={
      "Content-Type": "application/json"
    },
    auth=(os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"]),
    json=[
      "74000000-0000-4000-a000-000000000001",
      "74000000-0000-4000-a000-000000000002"
    ]
)

Lead fields

FieldTypeNotes
iduuidRead-only Unique identifier of entity.
namestringRequired on create Name of the entity and its default text representation.
createddate-timeCreation time.
currency_exchange_rates_list_iduuid → CurrencyExchangeRatesListsId of the currency exchange rate list applied to this lead.
descriptionstringFree-form description of the lead.
is_archivedbooleanTrue when the lead has been archived (lost).
label_flagstringUser-set colored flag used to highlight the lead in lists and reports.1 · 2 · 4
last_ai_buying_center_applieddate-timeTime when an AI-suggested buying center was last applied to this lead.
lead_source_iduuid → DataId of the lead source recording how the lead originated (e.g.
lead_type_iduuid → LeadTypesId of the lead type that classifies the lead and drives which form, fields and lead process apply.
owner_iduuid → ClientsId of the lead owner; a create needs owner_id or unit_id.
quick_account_emailstringFree-text company email captured at lead creation when no Account record has been linked yet.
quick_account_namestringFree-text company name captured at lead creation when no Account record has been linked yet.
quick_account_phonestringFree-text company phone captured at lead creation when no Account record has been linked yet.
quick_contact_namestringFree-text contact name captured at lead creation when no Contact record has been linked yet.
Show all 52 fields
FieldTypeNotes
quick_emailstringFree-text contact email captured at lead creation when no Contact record has been linked yet.
quick_phonestringFree-text contact phone captured at lead creation when no Contact record has been linked yet.
rankingintegerQualitative ranking score (1-10) the user assigns to indicate the strength of the lead.
reason_of_close_descriptionstringFree-form note explaining why the lead was archived (lost).
reason_of_close_iduuid → DataId of the reason recorded when the lead is archived (lost), or empty when none was given.
share_modeintegerSharing model applied on top of the owner/unit visibility (e.g.0 Standard · 1 Private · 2 AllView · 3 AllEdit
step_iduuid → StepsId of the lead process step.
unit_iduuid → SalesUnitsId of the sales unit; a create needs owner_id or unit_id.
revisionintegerRevision when entity was lastly changed.
contact_relationsarray of uri → LeadOpptyContactRelationsContacts linked to this lead, including their roles and org-chart positions.
account_relationsarray of uri → LeadOpptyAccountRelationsAccounts linked to this lead, including the primary-account flag.
sharing_unitsarray of uri → LeadOpptySharingSalesUnitRelationsSales units that have been granted shared access to this lead.
sharing_clientsarray of uri → LeadOpptySharingClientRelationsUsers that have been granted shared access to this lead.
documentsarray of uri → CloudObjectRelationsDocuments linked to this lead.
tagsarray of uri → TagRelationsTag labels applied to this lead.
static_profilesarray of uri → ProfileRelationsSaved view profiles this lead currently matches.
lost_datedate-timeTimestamp of when the lead was archived (lost).
is_delete_protectedbooleanRead-only True when the record is protected against deletion because it must always exist in the space.
is_deletedbooleanRead-only Specifies if the entity is considered deleted.
modifieddate-timeRead-only Last modification time.
currency_exchange_rates_listuri → CurrencyExchangeRatesListsRead-only Currency exchange rate list used to convert monetary fields linked to this lead.
lead_sourceuri → DataRead-only How the lead originated (e.g.
lead_typeuri → LeadTypesRead-only Lead type that classifies this lead.
owneruri → ClientsRead-only Sales user who owns this lead.
reason_of_closeuri → DataRead-only Configurable reason recorded when the lead is archived (lost).
stepuri → StepsRead-only Step in the lead process the lead is currently in.
unituri → SalesUnitsRead-only Sales unit this lead is assigned to.
table_namestringRead-only Discriminator identifying the concrete record type — always "lead" for Lead records.
primary_contacturi → ContactsRead-only Primary contact of this lead.
primary_accounturi → AccountsRead-only Primary account of this lead.
statusintegerRead-only Current status of the lead (Open, Lost, Qualified).1 Open · 2 Lost
qualify_datedate-timeRead-only Timestamp of when the lead was qualified, taken from the matching KPI event.
days_in_stepintegerRead-only Number of days the lead has been sitting in its current pipeline step.
is_favoritebooleanRead-only True when the current authenticated user has marked this lead as favorite.
formatted_namestringRead-only Display version of the lead name, used in lists and references.
scoringobjectRead-only Lead scoring summary, combining the percentile and current scoring state.
modified_by_userdate-timeRead-only Timestamp of the most recent modification made by an end user (excluding system changes).

Custom fields appear in your space's live spec: fetch it with your credentials.

Errors

Every error body has success: false, http_status, code, name and message. Branch on code: the status alone does not tell a missing permission from a bad parameter. All codes: error codes; how to handle them: Errors.

HTTPWhen
400Bad request: a bad or unknown parameter (codes 117, 118), a missing permission (code 50), conflicting data (code 2002) or any other API error. The REST API answers 400 where others answer 403 or 409; check code.
401Not authenticated: missing or wrong credentials, a credential of another space, or an expired token (code 401, ERROR_UNAUTHORIZED).
404No such record or entity (code 143 ERROR_NO_ENTITY, or 2006 ERROR_UNKNOWN_TYPE).
422Validation failed (code 40000, with the failing fields) or a required parameter is missing (code 119). By default one failed item fails a whole batch and nothing is written.
429Too many requests (code 182). Wait for the seconds in Retry-After, then retry.
500Unexpected server error (code 1000, ERROR_UNKNOWN).

Webhook events for leads

Lead.BackToLead Lead.Create Lead.Delete Lead.DocumentLinked Lead.Lost Lead.OwnerChanged Lead.Update See payloads

Subscribe with Create a webhook.