Developers

CONVIRTOS API

The CONVIRTOS ingest API lets external tools (Make, Zapier, landing pages, custom integrations) read and write a workspace's CRM data — leads, clients and tasks — with dynamic, per-workspace fields (each workspace's own statuses, sources, board columns and custom fields), and subscribe to instant event webhooks.

Base URL

All endpoints are relative to:

https://api.convirtos.com/api

All requests and responses are JSON. Every response carries a success boolean.

Authentication

Two mutually-exclusive methods identify the workspace. Sending both is rejected with 400. The workspace is always resolved server-side — it is never read from the request body.

1. OAuth 2.0 (recommended)

Authorization Code flow (confidential client). Send the access token as a Bearer header. Scopes: workspace:read, entities:read, records:read, records:write, webhooks:manage.

Authorization: Bearer <access_token>

# Endpoints
GET  https://api.convirtos.com/api/oauth/authorize   ?client_id&redirect_uri&response_type=code&scope&state
POST https://api.convirtos.com/api/oauth/token       (authorization_code | refresh_token)
POST https://api.convirtos.com/api/oauth/revoke      (RFC 7009)
GET  https://api.convirtos.com/api/oauth/me          -> { userId, workspaceId, workspaceName, scopes }

2. Workspace API key

A per-workspace key created in CONVIRTOS → Settings → API. Send it as a header. Full ingest access (not scope-limited); intended for landing pages, webhooks and server-to-server calls.

X-Workspace-Key: wsk_xxxxxxxxxxxxxxxx

Entities & dynamic fields

Three entities are supported: lead, client and task. Rather than a fixed schema, the field list is discovered live per workspace — so a custom field, status or board column added in CONVIRTOS appears immediately.

GET/ingest/metascope: entities:read
Handshake: returns the workspace name and the list of entities it can receive.
GET/ingest/meta/fields?entity=leadscope: entities:read
The live create/update field list for an entity — base fields plus the workspace's own statuses, sources, board columns and custom fields (custom_<key>), each typed with select options where relevant.
GET/ingest/meta/filters?entity=leadscope: entities:read
The live search-filter list for an entity (a subset of fields plus date ranges).

Create a record

POST/ingest/recordsscope: records:write
Creates a lead, client or task. Field names are the internal names advertised by /ingest/meta/fields, plus custom_<key> for custom fields. For a lead, a phone or email is required, and deduplication + routing rules run automatically (a matched lead returns matched: true and fires no lead.created event).
POST https://api.convirtos.com/api/ingest/records
Content-Type: application/json

{
  "entity": "lead",
  "contactName": "Dana Levi",
  "phone": "+972501234567",
  "email": "dana@example.com",
  "statusId": "<status id from /ingest/meta/fields>",
  "isHot": true,
  "custom_budget_range": "high"
}

# 201
{ "success": true, "leadId": "abc123", "matched": false }

Get & update a record

GET/ingest/records/:id?entity=leadscope: records:read
Fetch a single record by id. Returns 404 when the id is not in the workspace.
PATCH/ingest/records/:idscope: records:write
Update a record. The body carries entity plus the fields to change (and custom_<key>). A lead status change runs the full CRM side-effects (history, follow-up reminder, won→client conversion). Deals: a lead moved to a won status through the API closes its open deal along with it (the deal's monthly lines become the client's retainers). A lead with no deal is still converted here — unlike the CRM, where closing a lead without a deal is refused (409) — so add the deal in the CRM afterwards if the sale has a price. dealValue on a lead is read-only from the deal lines.
PATCH https://api.convirtos.com/api/ingest/records/abc123
Content-Type: application/json

{ "entity": "lead", "statusId": "<won status id>", "notes": "Signed" }

# 200
{ "success": true, "entity": "lead", "record": { "id": "abc123", "statusName": "Won", ... } }

Instant webhooks

Subscribe to events pushed the moment they happen: lead.created and lead.status_changed. Each delivery is signed with an HMAC-SHA256 signature over {timestamp}.{body} using the secret returned at creation.

POST/ingest/webhooksscope: webhooks:manage
Register a subscriber. Returns the signing secret once. Body: { "url": "https://…", "events": ["lead.created"] }.
GET/ingest/webhooksscope: webhooks:manage
List active subscribers (without secrets).
DELETE/ingest/webhooks/:idscope: webhooks:manage
Remove a subscriber.
# Delivery headers
X-Convirtos-Event: lead.created
X-Convirtos-Delivery-Id: <id>
X-Convirtos-Timestamp: <unix seconds>
X-Convirtos-Signature: sha256=<hex hmac_sha256(secret, "{timestamp}.{rawBody}")>

Errors & rate limits

Errors return a JSON body { "success": false, "error": "<message>" } with the matching HTTP status:

  • 400Invalid request (bad JSON, unknown entity, missing required field, both auth methods sent).
  • 403Invalid/expired credentials, missing scope, or an inactive workspace.
  • 404Record not found in this workspace.
  • 429Rate limit exceeded (60 requests/minute per workspace). Honour Retry-After.
Need access?

Create a workspace API key or an OAuth connection in CONVIRTOS → Settings → API, or reach us at info@convirtos.com.