Conversions API
A conversion is an ordered list of steps. The first step decides who enters the funnel; the last step is the conversion. This API manages the definition and reads the same numbers the dashboard shows.
| Method | Path | Scope |
|---|---|---|
| GET | /v2/property/conversions/schema | conversions:read |
| GET | /v2/property/conversions | conversions:read |
| POST | /v2/property/conversions | conversions:write |
| GET | /v2/property/conversions/{conversion} | conversions:read |
| POST | /v2/property/conversions/{conversion} | conversions:write |
| POST | /v2/property/conversions/{conversion}/steps | conversions:write |
| POST | /v2/property/conversions/{conversion}/publish | conversions:write |
| POST | /v2/property/conversions/{conversion}/toggle | conversions:write |
| DELETE | /v2/property/conversions/{conversion} | conversions:write |
| POST | /v2/property/conversions/{conversion}/summary | conversions:read |
| POST | /v2/property/conversions/{conversion}/segments | conversions:read |
| POST | /v2/property/conversions/{conversion}/cycles | conversions:read |
| POST | /v2/property/conversions/{conversion}/sessions | conversions:read |
A {conversion} id from another property returns 404 with conversion not found.
Schema
Section titled “Schema”GET /v2/property/conversions/schema
Call this first. It returns every valid value for the fields below, so nothing has to be hardcoded.
{ "code": 200, "status": "OK", "data": { "conversion_types": [ { "value": "lead", "label": "Lead", "color": "primary", "icon": "conversion-lead", "description": "Contact form, inquiry, or lead capture" }, { "value": "sale", "label": "Sale", "...": "..." } ], "trigger_types": [ { "value": "page_view", "label": "Page Visit", "description": "Visitor reaches a specific page", "config": { "kind": "path", "defaults": { "type": "page", "field": "path", "match": "contains", "value": "" }, "fieldOptions": [], "matchOptions": [] } } ], "cycle_intervals": ["day", "week", "month"], "segment_dimensions": [{ "value": "channel_category", "label": "Channel" }], "page_match_modes": [{ "id": "contains", "name": "Contains" }], "event_value_match_modes": [{ "id": "exists", "name": "Exists" }] }}The current values:
| Catalog | Values |
|---|---|
conversion_types | lead, sale, signup, activation, download, custom |
trigger_types | entry_page, page_view, event, form_submit, short_link, all_traffic, acquisition |
cycle_intervals | day, week, month |
segment_dimensions | channel_category, source_id, utm_medium, utm_campaign, utm_content, utm_term, request_country, request_device, entry_path, short_link_id |
page_match_modes | contains, exact, starts_with, regex |
event_value_match_modes | exists, equals, gte, lte, gt, lt |
Shapes
Section titled “Shapes”Summary shape (list rows):
| Field | Notes |
|---|---|
id, name, description | |
type | One of conversion_types |
state | draft, active, paused |
conversion_value | Fixed value per conversion in whole currency units (not cents), or null |
value_from_event | boolean. When true the value is read from the conversion step’s event value or acquisition value instead |
steps_count | integer |
starting_from | ISO 8601 or null. Analytics never look before this date |
default_period, default_cycle | Dashboard defaults |
Full shape = summary shape plus steps[], each { id, name, order, trigger_type, trigger_config, is_required }.
Steps and trigger config
Section titled “Steps and trigger config”Every step has name, trigger_type, trigger_config (object) and optional is_required (boolean, default true). The contents of trigger_config depend on the trigger type. The API enforces these keys; the rest of the object follows the defaults published by the schema endpoint.
trigger_type | Required in trigger_config | Full default config |
|---|---|---|
page_view | value (string, max 500) | { "type": "page", "field": "path" or "url", "match": "contains", "value": "/pricing" } |
entry_page | value (string, max 500) | { "type": "entryPage", "field": "entry_path" or "entry_url", "match": "contains", "value": "/pricing" } |
event | name (string, max 255) | { "type": "event", "name": "purchase", "value": "", "valueMatch": "exists" } |
short_link | scope (link or group), value (the link or group id) | { "type": "shortLink", "scope": "link", "value": "..." } |
form_submit | snipFormId (string) | { "type": "formSubmit", "snipFormId": "..." } |
all_traffic | nothing | { "type": "allTraffic" } |
acquisition | nothing enforced | { "type": "acquisition", "field": "value", "match": "exists", "value": "" }. field is value, cost or currency_code; numeric matches are exists, equals, gte, lte, gt, lt; currency_code takes exists or equals |
Validation errors point at the step index: steps.1.trigger_config.name.
Create
Section titled “Create”POST /v2/property/conversions
| Field | Rules |
|---|---|
name | required, string, max 255 |
description | string, max 500 |
type | required, one of conversion_types |
conversion_value | numeric, min 0 |
value_from_event | boolean |
starting_from | date |
default_period | string |
default_cycle | day, week, month |
steps | array of steps (see above) |
publish | boolean. Publishes immediately if at least one step is supplied |
curl -X POST https://api.snipform.io/v2/property/conversions \ -H "Authorization: Bearer $SNIPFORM_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Pricing to signup", "type": "signup", "publish": true, "steps": [ { "name": "Saw pricing", "trigger_type": "page_view", "trigger_config": { "type": "page", "field": "path", "match": "starts_with", "value": "/pricing" } }, { "name": "Signed up", "trigger_type": "event", "trigger_config": { "type": "event", "name": "signup", "value": "", "valueMatch": "exists" } } ] }'{ "code": 200, "status": "OK", "data": { "conversion": { "id": "66c4e0a1b2c3d4e5f6a7b8c9", "name": "Pricing to signup", "description": "", "type": "signup", "state": "active", "conversion_value": null, "value_from_event": false, "steps_count": 2, "starting_from": null, "default_period": null, "default_cycle": null, "steps": [ { "id": "66c4e0a1b2c3d4e5f6a7b8d0", "name": "Saw pricing", "order": 0, "trigger_type": "page_view", "trigger_config": { "type": "page", "field": "path", "match": "starts_with", "value": "/pricing" }, "is_required": true }, { "id": "66c4e0a1b2c3d4e5f6a7b8d1", "name": "Signed up", "order": 1, "trigger_type": "event", "trigger_config": { "type": "event", "name": "signup", "value": "", "valueMatch": "exists" }, "is_required": true } ] } }}Read the definition
Section titled “Read the definition”GET /v2/property/conversionsreturns{ "conversions": [summary shape, ...] }.GET /v2/property/conversions/{conversion}returns{ "conversion": full shape }.
Update settings
Section titled “Update settings”POST /v2/property/conversions/{conversion}
Same fields as create minus steps and publish; all optional. Does not touch steps.
curl -X POST https://api.snipform.io/v2/property/conversions/66c4e0a1b2c3d4e5f6a7b8c9 \ -H "Authorization: Bearer $SNIPFORM_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "conversion_value": 49, "default_cycle": "week" }'Replace steps
Section titled “Replace steps”POST /v2/property/conversions/{conversion}/steps with { "steps": [...] } (required, at least one). Replaces the whole list; order is the array order. Returns the full shape.
Publish, toggle, delete
Section titled “Publish, toggle, delete”| Call | Effect | Errors |
|---|---|---|
POST .../publish | draft becomes active. No-op when already published | 422 Add at least one funnel step before publishing |
POST .../toggle | active becomes paused, paused becomes active | |
DELETE ... | Removes the conversion and its steps. Returns { "deleted": true } |
Analytics window and filter
Section titled “Analytics window and filter”The four read endpoints below share two inputs:
| Field | Rules | Notes |
|---|---|---|
from, to | integer unix seconds | Default: the last 7 days ending now. from is clamped to starting_from when set |
filter | object | Equality filters, { "field": "value" } or { "field": ["a", "b"] }. Keys are the alias names country, country_code, continent, region, city, lang, timezone, device, device_brand, device_model, browser, browser_family, os, os_version, entry_path, entry_subdomain, entry_title, exit_path, exit_subdomain, referrer_domain, utm_source, utm_medium, utm_campaign, channel_category, channel_name, source_name |
Only real-user sessions are counted; bots are excluded.
Summary and funnel
Section titled “Summary and funnel”POST /v2/property/conversions/{conversion}/summary
{ "code": 200, "status": "OK", "data": { "window": { "from": 1755177600, "to": 1755782400 }, "summary": { "conversions": 42, "sessions": 1180, "rate": 3.6, "value": 205800, "value_currency": "USD", "value_formatted": "$2,058.00", "value_usd": 205800 }, "funnel": [ { "step_id": "66c4e0a1b2c3d4e5f6a7b8d0", "name": "Saw pricing", "order": 0, "trigger_label": "Page Visit", "trigger_summary": "Path starts with /pricing", "count": 1180, "drop_off": 0, "drop_off_count": 0, "conversion_rate": 100, "is_conversion": false }, { "step_id": "66c4e0a1b2c3d4e5f6a7b8d1", "name": "Signed up", "order": 1, "trigger_label": "Event Fired", "trigger_summary": "signup", "count": 42, "drop_off": 96.4, "drop_off_count": 1138, "conversion_rate": 3.6, "is_conversion": true } ] }}rateandconversion_rateare percentages (0 to 100) rounded to one decimal.drop_offis the percentage lost against the previous step.valueis in minor units when the conversion has a currency (value_currencyset); with no currency it is the plain fixed-value sum with no USD side (value_usd: null).funnelis empty for a single-step conversion.
Segments
Section titled “Segments”POST /v2/property/conversions/{conversion}/segments
| Field | Rules |
|---|---|
dimension | one of segment_dimensions, max 64 |
tag_key | string, max 64. Segments by the values of that session tag |
from, to, filter | as above |
One of dimension or tag_key is required; otherwise 422 dimension or tag_key required. Up to 50 segments, sorted by converted descending.
curl -X POST https://api.snipform.io/v2/property/conversions/66c4e0a1b2c3d4e5f6a7b8c9/segments \ -H "Authorization: Bearer $SNIPFORM_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "dimension": "channel_category" }'{ "code": 200, "status": "OK", "data": { "window": { "from": 1755177600, "to": 1755782400 }, "dimension": "channel_category", "tag_key": null, "segments": [ { "value": "paid_search", "label": "Paid Search", "icon": "channel-paid-search", "sessions": 410, "converted": 22, "rate": 5.4, "sessions_label": "Paid Search - Sessions", "converted_label": "Paid Search - Converted", "browse": { "clauses": [{ "id": "channel", "op": "equals", "value": "paid_search" }] } } ] }}browse.clauses is ready to paste into the Signals sessions endpoint to list exactly those sessions. It is null for values that cannot be expressed as a clause (empty or (none)).
Cycles
Section titled “Cycles”POST /v2/property/conversions/{conversion}/cycles
The same funnel recomputed per calendar bucket, newest first.
| Field | Rules |
|---|---|
interval | required: day, week, month |
page | integer, min 0, default 0 |
per_page | integer, 1 to 24, default 6 |
filter | as above |
{ "code": 200, "status": "OK", "data": { "cycles": [ { "id": "w-0", "label": "This week", "from_ts": 1755475200, "to_ts": 1755782400, "date_from": "2026-08-18", "date_to": "2026-08-21", "is_current": true, "conversions": 9, "sessions": 240, "rate": 3.8, "value": 44100, "value_currency": "USD", "delta": 0.4 } ], "has_more": true, "page": 0, "interval": "week" }}id is stable (w-3 is the fourth weekly bucket back). delta is the change in rate against the next older cycle in percentage points, or null when there is no older cycle. Buckets never start before starting_from.
Sessions
Section titled “Sessions”POST /v2/property/conversions/{conversion}/sessions
Sessions that reached a given step in the window.
| Field | Rules |
|---|---|
step_id | a step id. Omit for sessions that reached the final step (converted) |
page | integer, min 1, default 1 |
per_page | integer, 1 to 100, default 25 |
from, to, filter | as above |
The response is a paginator spread at the root (data, current_page, last_page, total, next_page_url, …) plus window and step_id. Each row:
{ "id": "9f1c2c1e-7b1a-4f0e-9f2b-1d2c3b4a5e6f", "sid": "3a0c...", "entry_ts": 1755780000, "last_ts": 1755780420, "entry_url": "https://acme.com/pricing", "views": 3, "channel_category": "paid_search", "channel_name": "Google Ads", "source_name": "google.com", "utm": { "source": "google", "medium": "cpc", "campaign": "brand", "content": null, "term": null }, "country": "South Africa", "device": "desktop"}