Skip to content

API

Everything the dashboard shows for a property is readable over HTTPS, and the things your backend knows (an order, a signup, a campaign) are writable back onto the sessions that produced them. One token, one property, JSON in and out.

Terminal window
curl https://api.snipform.io/v2/property/overview \
-H "Authorization: Bearer YOUR_TOKEN"
{
"code": 200,
"status": "OK",
"data": {
"id": "64f1c2a9e4b0a1b2c3d4e5f6",
"name": "acme.com",
"domain": "acme.com",
"has_signals": true,
"state": "active",
"state_name": "Active",
"counts": { "sessions": 48211, "forms": 3, "pages": 1 }
}
}

All authenticated endpoints live under:

https://api.snipform.io/v2

The token identifies the property, so no property id appears in any path. Every route is /v2/property/....

Send a property API token as a bearer token on every request:

Authorization: Bearer YOUR_TOKEN

Tokens are created per property in the dashboard, carry a set of scopes, and are shown once. See Authentication & Tokens for creation, expiry, revocation and the difference between API and MCP tokens.

  • Send JSON bodies with Content-Type: application/json. GET endpoints take query-string parameters.
  • The Accept header is forced to application/json server-side; you always get JSON back.
  • Money is always an integer in minor units (cents). Timestamps ending in _ts are unix seconds, UTC.
  • Dates in request bodies are YYYY-MM-DD and are interpreted in UTC.

Every response, success or error, is wrapped the same way:

{
"code": 200,
"status": "OK",
"data": { }
}
KeyMeaning
codeThe HTTP status code, repeated in the body
statusThe HTTP reason phrase (OK, Forbidden, Not Found, …)
dataThe endpoint’s payload. On errors, the error object described below

All response shapes documented in this section are the contents of data.

Errors carry a human-readable message and a stable error_code you can branch on:

{
"code": 403,
"status": "Forbidden",
"data": {
"message": "Missing scope: signals:read",
"error_code": "forbidden"
}
}
HTTPerror_codeWhen
401unauthenticatedNo token, an invalid token, or a revoked/expired token
403forbiddenThe token lacks a required scope (Missing scope: ...), or is not bound to a property
404not_foundThe record is not on this property, the token’s property was deleted, or the property has no data yet
410errorThe record was deleted and cannot be changed (contacts)
422validation_failedA request field failed validation. errors maps field names to messages
500server_errorSomething broke on our side

Validation failures use Laravel’s field map:

{
"code": 422,
"status": "Unprocessable Content",
"data": {
"message": "The name field is required.",
"errors": {
"name": ["The name field is required."]
}
}
}

Analytics endpoints return 404 with This property has no data until the tracker has recorded its first session.

Two shapes, depending on the endpoint:

Page-numbered (sessions, links, clicks, contacts, conversion sessions): Laravel’s paginator. Pass ?page=N; the size key is per_page on GET endpoints and limit on POST /v2/property/signals/sessions.

{
"data": [ ],
"current_page": 1,
"last_page": 12,
"per_page": 25,
"total": 289,
"from": 1,
"to": 25,
"next_page_url": "https://api.snipform.io/v2/property/links?page=2",
"prev_page_url": null
}

Cursor (a contact’s sessions): newest first, keyed on the session entry time.

{
"sessions": [ ],
"paging": { "per_page": 25, "has_more": true, "next_cursor": 1755700000 }
}

A token carries the scopes you picked when you created it. Each endpoint names the scope it checks; a token without it gets 403 Missing scope: <scope>.

ScopeGrants
signals:readAnalytics, sessions feed, attribution preview and presets
signals:writeRecord events and acquisition data on sessions
conversions:readConversion definitions, summaries, funnels, segments, cycles
conversions:writeCreate, update, publish, pause and delete conversions
shortlinks:readLink groups, links and clicks
shortlinks:writeCreate, update and delete groups and links
contacts:readIdentified contacts and their sessions
contacts:writeIdentify, update and delete contacts
forms:readDeclared for forward compatibility. No endpoint consumes it yet
mcp:useMCP tokens only. Grants the MCP server, never these REST endpoints

GET /v2/property/overview needs no scope at all, which makes it a cheap connectivity check for any token.

The authenticated REST API has no published per-token limit today. The MCP server is throttled to 60 requests per minute per client and the public tracker endpoints to 120 per minute per IP. Analytics endpoints run Elasticsearch aggregations on every call; cache on your side rather than polling.

  • Property - one call that confirms the token works and names the property it belongs to.
  • Signals analytics - metrics, time series, live view and the paginated sessions feed, all filterable.
  • Query language - the clause format every analytics endpoint accepts.
  • Field catalog - every filterable session field, the operators it takes, periods and metrics.
  • Session actions - record events and revenue on a session from your backend.
  • Contacts - identify people, read their sessions, update or delete them.
  • Conversions - define funnels and read their results.
  • Short links - groups, links with UTMs, and click logs.
  • Attribution - preview how a URL will be classified before you ship it.
  • Public endpoints - what the tracker and form libraries call. No token, signed requests.

/v2 is the current and only supported version. The older /core/* form endpoints still answer for existing embeds but are not for new integrations. Additive changes (new fields, new endpoints) ship without a version bump; anything that would break a documented shape gets a new prefix.