twelvebitDocsllms.txtSign in
View as Markdown

API reference

Read analytics, push the tracking plan (analytics.yaml), and send server-side events.

Authentication#

Send a key in the Authorization header:

sh
curl -sS https://twelvebit.app/api/v1/overview -H "Authorization: Bearer $TWELVEBIT_API_KEY"
CredentialPrefixScope
Site keytbk_One site. The site parameter is ignored. Create it in the site settings, or let twelvebit init create it.
Account tokentbt_Every site you can open. Pass ?site=<id, public id or domain> (or site_id in the payments body). Create it on your account page.
Sessioncookie or Bearer session tokenThe dashboard session, and the token that twelvebit init gets through the device login. Works like an account token.

Keys are secrets. Use them on servers and in terminals only, never in browser code. Viewers can read; writing (events, identify, payments, tracking plan, annotations, bots) needs a site key or the owner or member role.

Responses#

Success: { "data": …, "meta": { … } }. meta names the site and, for analytics, the time range (range.label, range.from, range.to, range.tz) and the attribution model (last touch: the visit before the payment).

Error: { "error": { "code": "site_required", "message": "…" } } with a matching HTTP status (400, 401, 403, 404, 422, 429, 500). Messages say what to do next.

Rate limit#

120 requests per minute per key. Above that the API answers 429 with a Retry-After header in seconds. Wait that long, then try again.

Common query parameters#

ParameterValuesNotes
periodtoday, yesterday, 24h, 7d, 30d, 90d, 12m, wtd, mtd, ytd, all, customDefault 30d. Days are in the site's time zone.
from, toYYYY-MM-DDBoth together make a custom range. to is included.
f_<dim>any valueFilter, for example f_country=DE, f_channel=Organic Search, f_page=/pricing, f_goal=signup. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal. Filters combine with AND.
siteid, public id or domainNeeded for account tokens and sessions when you have more than one site.

Revenue in breakdowns is attributed with the model last touch: the visit before the payment.

Endpoints#

MethodPathSummary
GET/api/v1/sitesList sites
GET/api/v1/sites/{siteId}Get a site
GET/api/v1/overviewKPIs for a range
GET/api/v1/timeseriesVisitors and revenue over time
GET/api/v1/breakdownTop values of one dimension
GET/api/v1/realtimeWho is on the site now
GET/api/v1/goalsGoals and their completions
GET/api/v1/funnelsCompute a funnel
GET/api/v1/peopleList visitors
GET/api/v1/people/{visitorId}One visitor's journey
GET/api/v1/tracking-planGet the tracking plan
PUT/api/v1/tracking-planReplace the tracking plan
GET/api/v1/install-checkInstall check and drift
GET/api/v1/annotationsList annotations
POST/api/v1/annotationsAdd an annotation
POST/api/v1/eventsSend a goal from your server
POST/api/v1/identifyIdentify a visitor from your server
POST/api/v1/paymentsRecord a payment
GET/api/v1/botsCrawler traffic
POST/api/v1/botsRecord a crawler hit
POST/api/v1/cli/bootstrapFind or create a site and mint a key (CLI)
GET/api/v1/openapi.jsonThis document

GET /api/v1/sites#

List sites.

Every site the key can read. A site key returns only its own site.

sh
curl -sS "https://twelvebit.app/api/v1/sites" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 401 Missing or invalid key · 429 Rate limited (see Retry-After).

GET /api/v1/sites/{siteId}#

Get a site.

One site by id, public id or domain, with its script tag.

ParameterInTypeRequiredDescription
siteIdpathstringyesSite id, public id (tb_…) or domain.
sh
curl -sS "https://twelvebit.app/api/v1/sites/tb_YOUR_SITE_ID" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/overview#

KPIs for a range.

Visitors, visits, page views, bounce rate, time on site, revenue, customers and conversion, for the range and the previous range of the same length, plus the number of people online now.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
f_<dim>querystringnoFilter by one value. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal.
sh
curl -sS "https://twelvebit.app/api/v1/overview?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/timeseries#

Visitors and revenue over time.

One point per hour, day, week or month in the site's time zone.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
gqueryhour | day | week | monthnoBucket size. Default depends on the range length.
f_<dim>querystringnoFilter by one value. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal.
sh
curl -sS "https://twelvebit.app/api/v1/timeseries?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/breakdown#

Top values of one dimension.

Visitors and attributed revenue (last touch: the visit before the payment) per value, sorted by visitors. dim=goal adds completions; dim=referrer adds the channel; dim=region and dim=city add the country.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
dimquerychannel | referrer | campaign | keyword | source | hostname | entry | exit | country | region | city | browser | os | device | page | goal | outboundno
limitqueryintegerno
f_<dim>querystringnoFilter by one value. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal.
sh
curl -sS "https://twelvebit.app/api/v1/breakdown?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/realtime#

Who is on the site now.

People active in the last 5 minutes (with page, source, place and goals), visitors per minute for the last 30 minutes (oldest first), and the last 30 minutes of events and payments.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
sh
curl -sS "https://twelvebit.app/api/v1/realtime" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/goals#

Goals and their completions.

Visitors, completions and revenue of those visitors per goal. declared says whether the goal is in the tracking plan; undeclared and not_seen show drift.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
f_<dim>querystringnoFilter by one value. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal.
sh
curl -sS "https://twelvebit.app/api/v1/goals?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/funnels#

Compute a funnel.

With steps, computes that funnel: each step counts visitors who reached it after the step before. Without steps, computes every funnel saved in the dashboard and every funnel in the tracking plan (name picks one).

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
stepsquerystringno2 to 8 comma-separated steps: page:/path (use * as a wildcard) or goal:name (a bare name is a goal).
namequerystringnoName of a saved or planned funnel.
f_<dim>querystringnoFilter by one value. Dimensions: channel, referrer, campaign, keyword, source, hostname, entry, exit, country, region, city, browser, os, device, page, goal.
sh
curl -sS "https://twelvebit.app/api/v1/funnels?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/people#

List visitors.

Visitors seen in the range, newest first or by revenue. Anonymous visitors get a stable friendly name like amber-fox-4821.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
filterqueryall | customers | identifiedno
qquerystringnoSearch email or name (contains), or an exact visitor id or user id.
sortqueryrecent | revenueno
limitqueryintegerno
offsetqueryintegerno
sh
curl -sS "https://twelvebit.app/api/v1/people?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/people/{visitorId}#

One visitor's journey.

Profile, attribution (first touch and the credited visit: last touch: the visit before the payment), every visit with its events, and payments.

ParameterInTypeRequiredDescription
visitorIdpathstringyesVisitor id (_tb_vid) or the user_id from identify.
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
sh
curl -sS "https://twelvebit.app/api/v1/people/VISITOR_ID" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/tracking-plan#

Get the tracking plan.

The stored plan as JSON and YAML. Send Accept: text/yaml (or ?format=yaml) to get only the YAML text. The YAML is rebuilt from the stored plan, so comments are not kept.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
formatqueryjson | yamlno
sh
curl -sS "https://twelvebit.app/api/v1/tracking-plan" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

PUT /api/v1/tracking-plan#

Replace the tracking plan.

Send analytics.yaml as the body (Content-Type: text/yaml), or the same plan as JSON. The schema is strict: unknown keys are errors. The response lists added, removed and changed events. ?dry_run=1 validates without saving.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
dry_runquerybooleanno

Request body:

yaml
version: 1
project: example.com
events:
  signup:
    description: A visitor creates an account
    props:
      plan: { type: string, enum: [free, pro] }
sh
curl -sS -X PUT "https://twelvebit.app/api/v1/tracking-plan" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: text/yaml" --data-binary @analytics.yaml

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 422 Invalid tracking plan · 429 Rate limited (see Retry-After).

GET /api/v1/install-check#

Install check and drift.

What the site has sent: first and last event, the last 10 events, counts by type in the last 24 hours, host names seen, and for each event in the tracking plan whether it has been seen in the last 30 days. undeclared lists goals that were sent but are not in the plan. next_steps says what to fix.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
sh
curl -sS "https://twelvebit.app/api/v1/install-check" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/annotations#

List annotations.

Notes shown on the time charts in the range.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
sh
curl -sS "https://twelvebit.app/api/v1/annotations?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/annotations#

Add an annotation.

Mark a launch, a deploy or a price change on the charts. ts defaults to now.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.

Request body:

json
{
  "label": "Launched on Product Hunt",
  "ts": "2026-10-01T09:00:00Z",
  "url": "https://www.producthunt.com/posts/example"
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/annotations" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"label":"Launched on Product Hunt","ts":"2026-10-01T09:00:00Z","url":"https://www.producthunt.com/posts/example"}'

Responses: 201 Created · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/events#

Send a goal from your server.

Records a goal for a visitor that the browser script has already seen. Pass visitor_id (the _tb_vid cookie) or user_id (sent earlier with identify). The goal joins the visitor's latest visit. Names are lowercased; use snake_case.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.

Request body:

json
{
  "name": "subscription_started",
  "user_id": "user_123",
  "props": {
    "plan": "pro"
  }
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/events" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"subscription_started","user_id":"user_123","props":{"plan":"pro"}}'

Responses: 202 Recorded · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/identify#

Identify a visitor from your server.

Attaches your user id, email, name, avatar and traits to a visitor. Later server-side events can then use user_id.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.

Request body:

json
{
  "visitor_id": "k3j5h2g7f9d1s8a4q6w0e2r5",
  "user_id": "user_123",
  "email": "ada@example.com",
  "name": "Ada",
  "traits": {
    "plan": "pro"
  }
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/identify" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"visitor_id":"k3j5h2g7f9d1s8a4q6w0e2r5","user_id":"user_123","email":"ada@example.com","name":"Ada","traits":{"plan":"pro"}}'

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/payments#

Record a payment.

For payment providers without a built-in connection. Safe to repeat: transaction_id makes it idempotent. The payment is credited to a visit (last touch: the visit before the payment) through visitor_id/session_id, or through the email or customer id of an identified visitor. An amount of 0 is a free trial and is not counted. Account tokens pass site_id in the body.

Request body:

json
{
  "amount": 49,
  "currency": "USD",
  "transaction_id": "inv_1042",
  "visitor_id": "k3j5h2g7f9d1s8a4q6w0e2r5",
  "email": "ada@example.com",
  "plan": "Pro"
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/payments" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":49,"currency":"USD","transaction_id":"inv_1042","visitor_id":"k3j5h2g7f9d1s8a4q6w0e2r5","email":"ada@example.com","plan":"Pro"}'

Responses: 200 Already recorded (duplicate transaction_id), or a free trial · 201 Recorded · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 429 Rate limited (see Retry-After).

GET /api/v1/bots#

Crawler traffic.

Hits from AI and search crawlers in the range, by kind (ai_answer, indexing, training) and by bot.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.
periodquerytoday | yesterday | 24h | 7d | 30d | 90d | 6m | 12m | wtd | mtd | ytd | all | customno
fromquerystringnoFirst day (YYYY-MM-DD, site time zone). Use with to.
toquerystringnoLast day, inclusive.
sh
curl -sS "https://twelvebit.app/api/v1/bots?period=7d" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/bots#

Record a crawler hit.

Crawlers do not run JavaScript, so your server reports them. Send the user agent and path of a request; known crawlers are stored as ai_answer (an assistant fetches the page for a person now), indexing (search engines) or training (model training). Unknown user agents are ignored. Fire and forget: do not make the page wait.

ParameterInTypeRequiredDescription
sitequerystringnoSite id, public id (tb_…) or domain. Needed for account tokens with more than one site; site keys ignore it.

Request body:

json
{
  "user_agent": "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot",
  "path": "/pricing"
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/bots" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"user_agent":"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; ChatGPT-User/1.0; +https://openai.com/bot","path":"/pricing"}'

Responses: 202 Accepted · 400 Invalid input · 401 Missing or invalid key · 403 Not allowed for this key · 404 Not found · 429 Rate limited (see Retry-After).

POST /api/v1/cli/bootstrap#

Find or create a site and mint a key (CLI).

Used by twelvebit init after the device sign-in. Needs a session (the device flow's access token as a Bearer). Finds the user's site for the domain, or creates it, and returns a new site key named after the machine.

Request body:

json
{
  "domain": "example.com",
  "timezone": "Europe/Berlin",
  "hostname": "ada-mbp"
}
sh
curl -sS -X POST "https://twelvebit.app/api/v1/cli/bootstrap" -H "Authorization: Bearer $TWELVEBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.com","timezone":"Europe/Berlin","hostname":"ada-mbp"}'

Responses: 200 OK · 400 Invalid input · 401 Missing or invalid key · 429 Rate limited (see Retry-After).

GET /api/v1/openapi.json#

This document.

sh
curl -sS "https://twelvebit.app/api/v1/openapi.json" -H "Authorization: Bearer $TWELVEBIT_API_KEY"

Responses: 200 OpenAPI 3.1 document.