Docs · API reference
/v1/conversions
One endpoint covers every conversion type. Bearer-authenticated with your workspace site key. Idempotent on (workspace_id, external_id).
Authentication
All requests carry a Bearer token in the Authorization header. The token is your workspace site key, prefixed dcs_sk_. Find it in Settings → API keys.
Authorization: Bearer dcs_sk_live_…Site keys are workspace-scoped. Rotate from the same settings page; old keys stop authenticating within 60 seconds.
Endpoint
POST https://api.decisa.ai/v1/conversions
Content-Type: application/json
Authorization: Bearer dcs_sk_live_…Request body
{
"type": "signup",
"external_id": "user-1234",
"visitor_id": "v_abc123...",
"customer_email": "[email protected]",
"value_cents": 0,
"currency": "USD",
"occurred_at": "2026-05-25T18:14:22Z",
"metadata": {
"plan": "pro",
"trial": false
}
}| Field | Type | Description |
|---|---|---|
| type | string · required | One of: signup, trial_start, subscription_start, sale, lead, app_install, custom. |
| external_id | string · required | Your unique ID for the record. Used for dedupe. |
| visitor_id | string · recommended | Value of the dcs_vid first-party cookie. Without this the conversion can't be joined to a click. |
| customer_email | string · optional | SHA256-hashed before storage. Used for CAPI pushback. |
| value_cents | integer · optional | Revenue in minor units. Required for revenue-bearing types. |
| currency | string · optional | ISO 4217. Defaults to workspace currency. |
| occurred_at | ISO 8601 · optional | Server timestamp used if omitted. |
| metadata | object · optional | Free-form. Not used for attribution; surfaced in dashboards. |
Successful response (201)
{
"data": {
"id": "conv_01HZX...",
"type": "signup",
"external_id": "user-1234",
"attributed": true,
"attribution_model": "last-click",
"attribution_model_version": "1.0.0",
"matched_click_id": "clk_01HZX...",
"matched_campaign_id": null,
"occurred_at": "2026-05-25T18:14:22Z"
},
"meta": null,
"error": null
}attributed: false means we accepted the conversion but didn't find a qualifying click. The row is still queryable in the dashboard under Unattributed.
Error codes
| Field | Type | Description |
|---|---|---|
| 401 | unauthorized | Missing or invalid site key. |
| 403 | workspace_disabled | Workspace is paused for billing or compliance. |
| 422 | invalid_payload | Schema validation failed. See `error.fields` for details. |
| 429 | rate_limited | Workspace ingestion rate exceeded. Retry with backoff. |
| 500 | server_error | Transient. Safe to retry — endpoint is idempotent. |
Idempotency and retries
The endpoint is idempotent on (workspace_id, external_id). Replaying the same payload returns the original conversion row with HTTP 200 (not 201). Use this freely — webhook retries from Stripe, Shopify, and Kiwify never create duplicates.
Rate limits
Free tier: 60 requests / minute. Paid tiers: 600 / minute. Bursts up to 2× sustained rate are absorbed without 429s. Higher limits available on request.