Base URL and authentication
Authorization: Bearer <YOUR_API_KEY>. Create a key under Settings → API keys (details). Reads need stats:read; changes need config:write, and creating and deleting need more than that. Each section below says which.
A site your key does not cover returns 404, not 403, so a key cannot be used to discover which sites exist.
How sites are identified
A site has two identifiers, and which one you see depends on the credential you used. On this page, and on events, sources, sessions, revenue, goals and funnels, an API key only ever sees the snippet key:ttid_ followed by 22 characters, the value your install snippet carries as data-site. It is what id holds in every response below, and it is what you pass back in any later call to those endpoints.
A few endpoints take the site’s internal UUID instead of the snippet key: the data deletion and
access endpoints, plus
POST /v1/ingest/conversions and POST /v1/consortium/fingerprints. No API endpoint returns that UUID, so read it from the dashboard URL
once and keep it. See which site identifier those endpoints
take.snippet_key is also returned as its own field, and it always holds that same ttid_ value.
GET /v1/sites
List the properties on your account, newest first.
Query parameters
Sites you have scheduled for deletion are excluded by default. Pass
include_deleted=true to see them; each one carries a non-null deleted_at and deletion_effective_at.
Response fields
GET /v1/sites/{siteId}
Fetch one site. siteId is the snippet key.
sites array).
A site inside its deletion window returns 404 here. Use GET /v1/sites?include_deleted=true if you need to see it.
Note that a site in its deletion window keeps collecting nothing new but keeps its data: ingestion is suspended when you schedule the deletion, while the read endpoints keep serving what is already there so you can export it during the 30 days. That is why this endpoint 404s a site the sources and events endpoints still answer for.
About region
region is the region you chose for the site, and we return it so you can read back what is on file. It does not yet control where data is stored: all event data currently lands in one region whichever value you pick. If you have GDPR obligations that require EU storage, read Data residency before relying on this field.
POST /v1/sites
Create a property. The response includes an API key for it, shown once.
cookie_apex_domain comes back null here, because nothing is applied automatically. suggested_cookie_apex_domain carries what domain derives to; render it as a pre-filled, unconfirmed suggestion, and PATCH /v1/sites/{siteId} with it to actually scope the snippet’s identity cookies across subdomains as data-cookie-domain. Broadening cookies to an apex is a real security tradeoff, not a free upgrade: two sites that happen to resolve to the same registrable domain (including two different accounts, on a platform domain not on the Public Suffix List) can otherwise collide on one visitor identity, which is why this is confirm-not-derive. suggested_cookie_apex_domain is null when the domain has no registrable apex (localhost, an IP address). See Subdomains and cross-domain.
This endpoint needs three permissions: credentials:write, stats:read and ingest:write. It hands you a credential carrying the last two, and a key can never mint a key more capable than itself. If yours is missing one, you get 403 and required_scope names it. See minting credentials with a key.
It also requires that the person who created your key is still an account-wide admin, and it refuses a key scoped to a single site. See who is behind a key.
A domain another account tracks is not a conflict. Two accounts pointing at the same hostname collect entirely separate data.
PATCH /v1/sites/{siteId}
Change a site’s settings. Send only the fields you are changing. Needs config:write.
GET /v1/sites/{siteId}.
At least one field is required.
Setting
currency explicitly also stops a later Stripe or Shopify connection from overriding it, including when you set it to USD.
Unlike creating and deleting, this is not admin-only. Any member can change settings.
A site inside its deletion window returns 404. Restore it first.
DELETE /v1/sites/{siteId}
Schedule a site for deletion, 30 days out. Needs config:write and an account-wide admin behind the key.
POST /v1/sites/{siteId}/restore cancels the whole thing. After effective_at the erasure runs and is not reversible.
What happens straight away:
- Collection stops. The snippet is still on your pages, but we no longer accept its events.
- The site disappears from
GET /v1/sitesunless you passinclude_deleted=true. - It stops counting against your plan’s site cap.
confirm_domain must match the site’s own domain, case-insensitively. It is the domain rather than a fixed phrase because on a multi-site account the mistake that actually happens is deleting the wrong property, and a constant phrase cannot catch that.
Re-issuing on a site that is already scheduled reports the existing effective_at and does not push the deadline out.
POST /v1/sites/{siteId}/restore
Cancel a scheduled deletion and resume collection. Needs config:write and an account-wide admin.
200 no-op.
Next
- Recent events to confirm a site is receiving traffic
- Traffic sources for the numbers behind the dashboard

