api-reference

1. Create an API Token or Website Key

Create a workspace API token from the API Tokens page when you need programmatic access across every website in your workspace, including MCP and OpenClaw integrations. Workspace tokens use the flow_ws_ prefix. For server-to-server tracking for one website, create a website API key from that website's Settings > API page; website keys use the flow_ prefix. Copy new tokens immediately because the secret is shown only once.

2. Authenticate Your Requests

Every API call must include the Authorization header using the Bearer scheme. Use a flow_ws_ workspace token for multi-website API access, or a flow_ website key for a single website.

Authorization Header
Authorization: Bearer YOUR_API_KEY

3. Start Making Requests

The base URL for all v1 endpoints is: https://analytics.flowsery.com/analytics/api/v1/. With a workspace token, call GET /websites first, then pass websiteId or domain to endpoint requests. Website keys are already scoped to one website and do not need a selector.

Choose a workspace

Every call runs in one workspace. Without the optional X-Workspace-Id header it lands in your default workspace. An OAuth sign-in, such as the Claude or ChatGPT connector, can reach every workspace its member belongs to, across organizations: call GET /workspaces to list them, then send the id you want in X-Workspace-Id on each request. An API key belongs to one workspace, so send its own id or leave the header out.

Workspace header
X-Workspace-Id: cm8ws1a2b3

A workspace the caller cannot reach answers 403 Forbidden with the code workspace_access_denied. An API key or website key sent with another workspace's id gets the same error.

Workspace access error
{
  "statusCode": 403,
  "error": "Forbidden",
  "code": "workspace_access_denied",
  "workspaceId": "cm8ws4c5d6",
  "message": "You have no access to workspace cm8ws4c5d6. Call GET /workspaces to list the workspaces you can use, and send one of those ids in the X-Workspace-Id header."
}

Response Format

Successful responses return a 200 OK status with a body structured as:

Success Response
{
  "status": "success",
  "data": { ... }
}

Errors use the normal NestJS HTTP error response shape.

Error Response
{
  "message": "Unauthorized",
  "statusCode": 401
}

Standard Error Codes

<strong>400 Bad Request</strong> -- The input is invalid or required parameters are missing, such as a workspace token without websiteId or domain. A website key calling GET /workspaces also gets 400.<br /><strong>401 Unauthorized</strong> -- The API token is missing, invalid or revoked. The code token_issuer_lost_access means the member who created the key lost access to the workspace; create a new key.<br /><strong>403 Forbidden</strong> -- workspace_access_denied: the X-Workspace-Id header names a workspace this credential cannot reach. subscription_required: the plan no longer includes API access. permission_denied: your workspace role lacks the flowsery.write permission, which Admins and Editors hold. On a free trial, AI-detected issues beyond the first 10 answer "Upgrade to view this issue".<br /><strong>404 Not Found</strong> -- The requested resource does not exist.<br /><strong>429 Too Many Requests</strong> -- More than 600 requests in a minute for this key. Wait the number of seconds in Retry-After. Every response carries RateLimit-Policy, RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset.<br /><strong>500 Internal Server Error</strong> -- An unexpected issue occurred on the server.
Example Request (Curl)
curl --request GET \
  --url https://analytics.flowsery.com/analytics/api/v1/websites \
  --header 'Authorization: Bearer <workspace-api-token>'
200
{
  "status": "success",
  "data": [
    {
      "id": "cm8abc123",
      "domain": "example.com",
      "timezone": "America/New_York",
      "currency": "USD",
      "trackingId": "flid_abc123"
    }
  ]
}