Conversions API
Every real outcome (a booking, a visit, a qualified lead, a won deal, a payment) is one event with a key that never changes. Read them, and record the ones only your systems know.
GET /v1/conversions → POST /v1/conversions → POST /v1/contacts/:id/touchesScopes conversions:readconversions:write3 endpointsShow
How conversions work
Conversions is off for every workspace until NuTalk switches it on for yours. While it is off nothing is recorded, these endpoints answer 403 with details.reason conversions_off, and no conversion webhook is sent.
Bookings, visits, calls, goals and won pipeline cards record themselves from their own records, whichever way they were made: by an agent, in the dashboard, with the API or through MCP. Record with POST /v1/conversions only what NuTalk can't see: a qualified lead, a won deal, a payment from your POS or your Stripe, or an outcome of your own.
- Each event has a
keythat never changes, unique in the workspace. Ad platforms receive it as their event id, so a retry or a pixel with the same id counts once. An event you record is keyed by your Idempotency-Key:api:sale-1001. - Each event says who recorded it (
source), the record that makes it true (proof) and where the person came from, first and last (touch). - Keys need
conversions:readto list them andconversions:writeto record them. Only owners and admins give a key either one, as only they see conversions in NuTalk; reseller keys never hold them.
curl -X POST https://www.nutalk.ai/v1/conversions \
-H "Authorization: Bearer $NUTALK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: sale-1001" \
-d '{
"name": "payment.received",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"value": 650,
"currency": "MXN"
}'Where people came from
NuTalk records where people came from by itself: a WhatsApp, Instagram or Messenger ad, a lead form, a call. When your own systems know more (a landing page's form that kept the gclid, your CRM), send it with POST /v1/contacts/:id/touches: the contact's later conversions take it as their first or last touch, and its click ids let the ad platforms match them. Only the listed click ids, ad ids and UTMs are kept.
The Idempotency-Key is required there too, so a retry records one touch. Recording conversions and touches counts against the workspace's API limits, and against an allowance of its own: 600 an hour and 60 a minute.
/v1/conversionsList conversions
The workspace's conversions, the most recently recorded first: bookings, visits, calls, goals and won deals NuTalk recorded itself, and what the API recorded. Each event has a key that never changes, who recorded it, its proof and where the person came from.
conversions:readFields: id, name, key, occurred_at, recorded_at, value, contact_id, source, proof, touch, test, verification, retracted_at, and currency, updated_at, retracted_reason.
Only the workspace's owners and admins give a key conversions:read, as only they read conversions in NuTalk.
Query parameters
limitinteger · 1–100Results per page. Default: 20.
offsetinteger · at least 0Results to skip. Default: 0.
namelead.new | lead.qualified | appointment.booked | appointment.confirmed | appointment.attended | appointment.no_show | appointment.cancelled | call.connected | call.transferred | goal.reached | deal.won | payment.received | outcome.customOnly events of this name.
contact_iduuidOnly this contact's events.
keystring · up to 200The event with this key (an API event's is api:<Idempotency-Key>).
retractedbooleanfalse: only live events; true: only events taken back. Both without it.
testbooleanfalse: no test events; true: only them. Both without it.
recorded_afterdatetimeOnly events recorded at or after this time.
recorded_beforedatetimeOnly events recorded before this time.
Show 5 more fields
Errors
400validation_errorA query parameter is invalid (details.errors lists each one).403forbiddenConversions is off for the workspace (details.reason conversions_off): NuTalk switches it on per workspace during the beta.Plus the errors every request can return (401, 403, 429, 500): Errors.
curl "https://www.nutalk.ai/v1/conversions?name=payment.received&retracted=false" \ -H "Authorization: Bearer $NUTALK_API_KEY"
{
"success": true,
"data": [
{
"id": "6e2a9c4f-1b7d-4e3a-8c5f-0d9b7a6e4c21",
"name": "payment.received",
"key": "api:sale-1001",
"occurred_at": "2026-10-25T23:42:10+00:00",
"recorded_at": "2026-10-25T23:42:11.204+00:00",
"updated_at": "2026-10-25T23:42:11.204+00:00",
"value": 650,
"currency": "MXN",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"source": {
"kind": "api",
"agent_version_id": null,
"user_id": null,
"api_key_id": "7b7a0ce4-0000-4000-8000-000000000001",
"channel_id": null,
"conversation_id": null,
"call_id": null
},
"proof": {
"type": "api",
"id": "7b7a0ce4-0000-4000-8000-000000000001"
},
"touch": {
"first": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
},
"last": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
}
},
"test": false,
"verification": "verified",
"retracted_at": null,
"retracted_reason": null
},
{
"id": "7f3b0d5a-2c8e-4f4b-9d6a-1e0c8b7f5d32",
"name": "appointment.booked",
"key": "clinic_appointment:6b1d2c3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e:booked",
"occurred_at": "2026-10-25T23:42:10+00:00",
"recorded_at": "2026-10-25T23:42:11.204+00:00",
"updated_at": "2026-10-25T23:42:11.204+00:00",
"value": null,
"currency": null,
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"source": {
"kind": "ai_agent",
"agent_version_id": "2ea87934-6e03-4db7-80f2-ac753b724c82",
"user_id": null,
"api_key_id": null,
"channel_id": "9f19ef32-eaef-452c-bebc-14d9759cdb64",
"conversation_id": "5f0c2b1e-8d3a-4c6e-9b7f-2a4d6e8c0b13",
"call_id": null
},
"proof": {
"appointment_id": "6b1d2c3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
"status": "scheduled",
"type": "clinic_appointment",
"id": "6b1d2c3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e"
},
"touch": {
"first": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
},
"last": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
}
},
"test": false,
"verification": "verified",
"retracted_at": null,
"retracted_reason": null
}
],
"pagination": {
"total": 2,
"limit": 20,
"offset": 0,
"has_more": false
}
}/v1/conversions/:idGet a conversion
One of the workspace's conversions, as it is now (taken back or not).
conversions:readPath parameters
iduuidrequiredThe conversion id.
Errors
404not_foundNo conversion with this id in your workspace (ids of other workspaces answer the same).403forbiddenConversions is off for the workspace (details.reason conversions_off): NuTalk switches it on per workspace during the beta.Plus the errors every request can return (401, 403, 429, 500): Errors.
curl https://www.nutalk.ai/v1/conversions/6e2a9c4f-1b7d-4e3a-8c5f-0d9b7a6e4c21 \ -H "Authorization: Bearer $NUTALK_API_KEY"
{
"success": true,
"data": {
"id": "6e2a9c4f-1b7d-4e3a-8c5f-0d9b7a6e4c21",
"name": "payment.received",
"key": "api:sale-1001",
"occurred_at": "2026-10-25T23:42:10+00:00",
"recorded_at": "2026-10-25T23:42:11.204+00:00",
"updated_at": "2026-10-25T23:42:11.204+00:00",
"value": 650,
"currency": "MXN",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"source": {
"kind": "api",
"agent_version_id": null,
"user_id": null,
"api_key_id": "7b7a0ce4-0000-4000-8000-000000000001",
"channel_id": null,
"conversation_id": null,
"call_id": null
},
"proof": {
"type": "api",
"id": "7b7a0ce4-0000-4000-8000-000000000001"
},
"touch": {
"first": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
},
"last": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
}
},
"test": false,
"verification": "verified",
"retracted_at": null,
"retracted_reason": null
}
}/v1/conversionsRecord a conversion
Records an outcome NuTalk can't see by itself: a qualified lead, a won deal, a payment received (from your POS or your Stripe) or a custom outcome of your own, about one of the workspace's contacts. Bookings, visits, calls and goals record themselves, also when the API books or marks them.
conversions:writeTakes an Idempotency-KeyThe Idempotency-Key is required, and it becomes the event's key api:<Idempotency-Key>, the id ad platforms will receive (Meta's event_id, Google's transactionId, TikTok's event_id), so use your own id for it: the payment's, the deal's. It answers the same event forever, not only for 24 hours: a retry with the same details gets 200 with the event as it is (retracted too: the API never brings back what a teammate took back), other details get 409. Don't put personal data in it.
A recorded event is sent to the endpoints that name conversion.recorded (and, later, to the ad platforms the workspace connects), unless it is a test.
Request body
namelead.qualified | deal.won | payment.received | outcome.customrequiredWhat happened.
contact_iduuidrequiredThe contact it is about (find or create them with the contacts endpoints).
occurred_atdatetimeWhen it happened (now when left out): at most 365 days ago, never in the future.
valuenumber · 0–999,999,999,999.99Its value, at most 2 decimals, with currency. Required for payment.received.
currencystring · 3–3 charactersISO 4217 code of value (MXN, USD), with it.
outcomestring · up to 64For outcome.custom only, and required there: your own name for it, in snake_case (quote_sent), up to 64 characters.
conversation_iduuidThe conversation it happened in, if any: its channel and touch go with the event.
call_iduuidThe call it happened in, if any.
testbooleanRecord it as a test: it shows in this list and is never sent. An outcome of a test chat or a test call is a test anyway. Default: false.
Show 5 more fields
Errors
400validation_errorThe body is not JSON, or a field is missing or invalid (details.errors lists each field).400validation_errorThe Idempotency-Key header is missing, or isn't 1 to 150 letters, digits and . _ : - (details.reason idempotency_key_required).404not_foundNo contact (or conversation, or call) with this id in your workspace (ids of other workspaces answer the same).409conflictThe Idempotency-Key already recorded a conversion with other details (details.reason idempotency_key_reused, details.fields, details.conversion_id).403forbiddenConversions is off for the workspace (details.reason conversions_off): NuTalk switches it on per workspace during the beta.429rate_limitedThe workspace recorded 600 conversions and touches through the API in the last hour, or 60 in the last minute (on top of its general limit).Plus the errors every request can return (401, 403, 429, 500): Errors.
curl -X POST https://www.nutalk.ai/v1/conversions \
-H "Authorization: Bearer $NUTALK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "payment.received",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"occurred_at": "2026-10-25T17:42:10-06:00",
"value": 650,
"currency": "MXN"
}'{
"success": true,
"data": {
"id": "6e2a9c4f-1b7d-4e3a-8c5f-0d9b7a6e4c21",
"name": "payment.received",
"key": "api:sale-1001",
"occurred_at": "2026-10-25T23:42:10+00:00",
"recorded_at": "2026-10-25T23:42:11.204+00:00",
"updated_at": "2026-10-25T23:42:11.204+00:00",
"value": 650,
"currency": "MXN",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"source": {
"kind": "api",
"agent_version_id": null,
"user_id": null,
"api_key_id": "7b7a0ce4-0000-4000-8000-000000000001",
"channel_id": null,
"conversation_id": null,
"call_id": null
},
"proof": {
"type": "api",
"id": "7b7a0ce4-0000-4000-8000-000000000001"
},
"touch": {
"first": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
},
"last": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
}
},
"test": false,
"verification": "verified",
"retracted_at": null,
"retracted_reason": null
}
}{
"success": true,
"data": {
"id": "6e2a9c4f-1b7d-4e3a-8c5f-0d9b7a6e4c21",
"name": "payment.received",
"key": "api:sale-1001",
"occurred_at": "2026-10-25T23:42:10+00:00",
"recorded_at": "2026-10-25T23:42:11.204+00:00",
"updated_at": "2026-10-25T23:42:11.204+00:00",
"value": 650,
"currency": "MXN",
"contact_id": "9595b646-ab97-4485-b1b8-e8b58dfcdd19",
"source": {
"kind": "api",
"agent_version_id": null,
"user_id": null,
"api_key_id": "7b7a0ce4-0000-4000-8000-000000000001",
"channel_id": null,
"conversation_id": null,
"call_id": null
},
"proof": {
"type": "api",
"id": "7b7a0ce4-0000-4000-8000-000000000001"
},
"touch": {
"first": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
},
"last": {
"id": "8a4c1e6b-3d9f-4a5c-8e7b-2f1d9c8a6e43",
"at": "2026-10-23T23:17:02+00:00",
"channel": "whatsapp_api",
"platform": "meta",
"kind": "ad",
"ad": {
"id": "120211000000000001",
"headline": "Primera consulta"
},
"click_ids": {
"ctwa_clid": "example-click-id"
}
}
},
"test": false,
"verification": "verified",
"retracted_at": null,
"retracted_reason": null
}
}Events
| Event | When it is recorded |
|---|---|
lead.new | A person writes or calls the business for the first time. Recorded by NuTalk; imports and campaign lists never count. |
lead.qualified | The person meets the workspace's own definition of qualified. Recorded by the API. |
appointment.booked | A clinic appointment, a business meeting or a restaurant reservation is created, by any path (the AI, the dashboard, the API, MCP). A rolled-back booking never counts. |
appointment.confirmed | The customer confirmed it (a reminder reply, a call, the dashboard). |
appointment.attended | The customer showed up (seated, for a restaurant), marked by a teammate or the API, never by the hourly job that completes elapsed bookings. |
appointment.no_show | Marked no-show, by a teammate or the API. |
appointment.cancelled | The appointment is cancelled (never a rolled-back booking). |
call.connected | An answered call lasted 60 seconds or more. Test calls never count. |
call.transferred | The agent handed the call to a person or an extension. |
goal.reached | One of the agent's goals was met, by the goal evaluator. |
deal.won | A conversation's card enters a Won stage of a manual pipeline, a HubSpot deal closes won (with its amount), or the API records one. |
payment.received | A customer paid: recorded by the API with the business's own id, with its value. |
outcome.custom | An outcome of the workspace's own, recorded by the API with its name. |
An event that stops being true is taken back, never deleted: it keeps its row with retracted_at and retracted_reason, and comes back under the same key if it happens again.
Webhooks
Name conversion.recorded and conversion.retracted in a webhook endpoint's events (a key with webhooks:write and conversions:read), and each event arrives signed when it goes live and when it is taken back, with the event as the list shows it. Test events are never sent, and an outcome the AI made is sent once it passes its checks.
HubSpot deals
With HubSpot connected, a deal that closes won records deal.won with its amount and currency, once per deal, for the contact NuTalk has linked to it. A deal that leaves its won stage takes it back. HubSpot tells NuTalk through the connection's webhook: its subscriptions must include the deal stage property change.