Flowtag Docs

API Reference

REST API reference for Flowtag services.

The Flowtag REST API gives you direct HTTP access to Flowtag services. Use it to integrate with any language or runtime that can make HTTP requests.

Services

ServiceBase URLAuthentication
Flowtag APIhttps://api.flowtag.devAPI key, sent as a bearer token
Variables APIhttps://variables.flowtagservices.comVariable token, sent as a query parameter

The Flowtag API currently covers data subjects only — listing them, reading what is stored about one, and erasing it. Management endpoints for trackers, monitors, and status pages are not exposed yet; use the Dashboard for those in the meantime.

Versioning

Every Flowtag API path carries a version, then the service it belongs to:

https://api.flowtag.dev/v1/{service}/...

Resources below that are nested normally, so a data subject on a tracker is /v1/analytics/trackers/{trackerId}/subjects/{subjectId}. Breaking changes ship under a new version prefix; /v1 keeps its shape.

Authentication

Send your API key as a bearer token:

curl https://api.flowtag.dev/v1/analytics/trackers/trk_123/subjects \
  -H "Authorization: Bearer ft_yourPublicKey.yourSecret"

Each endpoint lists the scope it requires. Grant scopes when you create the key under Settings -> API Keys — a key can only do what its scopes allow, so issue one key per integration with the narrowest set that works.

Response format

Successful responses wrap their payload in data, alongside a meta object:

{
  "data": { },
  "meta": {
    "requestId": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "timestamp": "2026-08-07T12:34:56.789Z"
  }
}

Failures use the same envelope shape with an error object instead:

{
  "error": {
    "code": "forbidden",
    "message": "API key is missing the required scope \"analytics:delete-data\""
  },
  "meta": {
    "requestId": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "timestamp": "2026-08-07T12:34:56.789Z"
  }
}

error.details is present only when a failure has something per-field to report — in practice validation_error. It is omitted entirely otherwise, so check for it rather than expecting an empty array:

{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed",
    "details": [{ "field": "limit", "message": "Too big: expected number to be <=200" }]
  },
  "meta": {
    "requestId": "0f8fad5b-d9cb-469f-a165-70867728950e",
    "timestamp": "2026-08-07T12:34:56.789Z"
  }
}

meta.requestId is also returned as the X-Request-Id header. Log it — quoting it makes support requests much faster to resolve. If you send your own X-Request-Id, Flowtag uses that value instead.

Rate limits

Requests are limited per API key, with a separate per-IP limit in front of authentication:

LimitApplies toBudget
Per IP addressAll requests60 per minute
Per API keyAll requests120 per minute
Per API keyErasure requests only60 per hour

Responses from these endpoints carry the current budget, including error responses:

HeaderMeaning
X-RateLimit-LimitRequests allowed in the window.
X-RateLimit-RemainingRequests left in the window.
X-RateLimit-ResetUnix timestamp (seconds) when the window resets.
Retry-AfterSeconds to wait. Sent on 429 responses only.

Treat the headers as advisory rather than guaranteed — they are absent from unmetered endpoints such as the OpenAPI document, and briefly absent if our rate limiter itself is unavailable.

Exceeding a limit returns 429 with the rate_limited error code. Back off for the number of seconds in Retry-After before retrying — retrying sooner just consumes more budget.

Erasure has its own hourly budget because it is irreversible. If you process deletion requests in batches, spread them across the hour rather than firing them all at once. Erasure is idempotent, so a retry after a timeout or 429 is safe: a subject that holds no data returns zero counts and alreadyErased: true.

Error codes

CodeStatusMeaning
invalid_request400The request could not be processed as sent.
unauthorized401The API key is missing, malformed, revoked, or expired.
forbidden403The key is valid but lacks the scope the endpoint requires.
not_found404The resource does not exist, or the key's organisation cannot see it.
validation_error422A parameter failed validation; see error.details.
rate_limited429A rate limit was exceeded; see Retry-After.
internal_error500Something went wrong on our side. Retry, then contact support with the request id.

A resource belonging to another organisation returns not_found, not forbidden — a 403 would confirm that the id exists.

Data retention

Analytics data is not kept indefinitely. Sessions and events past your plan's retention window are deleted automatically, so results from this API shrink over time: a data subject that returned data last month can return not_found today, and sessions and events counts fall as older activity ages out. Aggregated data that carries no visitor link is not affected.

Retention windows depend on your plan — see the Analytics Data Retention Policy. If you need a point-in-time record of what was stored, read the subject and keep the response; do not assume you can re-read it later.

On this page