Spoar

Overview

Base URL, conventions, shared parameters and errors.

Every route lives under /v2, for example https://api.analytics.remcostoeten.nl/v2/health. The live OpenAPI document is served at /v2/openapi/json, with interactive docs at /v2/openapi; the API reference on this site is generated from the same document.

Conventions

  • Lists answer { data, nextCursor }; single resources answer { data }.
  • Timestamps are ISO 8601 in UTC.
  • Every response carries x-request-id.
  • Aggregate reads of a public project are cached for 60 seconds (Cache-Control: public, s-maxage=60); everything else is private, no-store.
  • Every list and breakdown also answers format=csv|json|sql (or Accept: text/csv) with the whole list as one download, up to 1 million rows.

Shared query parameters

ParameterValuesDefault
from, toISO 8601 timestampslast 30 days
period24h, 7d, 30d, 90d, 12mo, all; ignored when from and to are set30d
traffichuman (bot score under 50, no internal or localhost), bots (bot score 50 or more), internal (visitors marked internal), allhuman
environmentproduction (no preview deployments), preview (preview deployments only), all; applies on top of trafficproduction
filter[<dimension>]a value, or !value to exclude; repeatable across dimensionsnone
limit, cursorup to 100; opaque cursor from the previous page20

An unknown dimension answers 400 VALIDATION_FAILED, in breakdown/:dimension and in filter[<dimension>] alike.

Events the server client sends without a visitor or session share the id server. They count in pageviews, events and every breakdown of events, but never as a visitor or a session: visitors, sessions, bounce rate, session duration, pages per session, conversion rate, paths, retention, lifecycle, stickiness, the map's visitors, and the visitor, session and people lists leave them out.

Errors

Every error uses one envelope:

{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "The request does not match the schema",
    "details": { "fields": [{ "path": "/period", "message": "Expected union value" }] },
    "requestId": "req_01J8Z3",
    "docs": "https://api.analytics.remcostoeten.nl/v2/openapi#errors/VALIDATION_FAILED"
  }
}
StatusCodeWhen
400VALIDATION_FAILEDBody, query or path fails the schema; details lists each field
401UNAUTHORIZEDNo or invalid session, token or key
401AUTH_REQUIREDThe dev widget bootstrap was called without a session cookie
403FORBIDDEN_ORIGINPublic key used from an origin not in the project's list
403ORIGIN_NOT_ALLOWEDThe dev widget bootstrap's origin is in no project's allowed origins
403FORBIDDENThe caller's role or token scope does not allow the action
403WIDGET_REPORTS_DISABLEDClient reports sent to a project with widgetReports off
404NOT_FOUNDUnknown route or resource, or a private project without access
409CONFLICTCreating something that exists
413PAYLOAD_TOO_LARGEIngest body over 60 KB or more than 50 events, or a client report body over 16 KB
429RATE_LIMITEDA rate limit was hit; Retry-After says when to try again
500INTERNALUnexpected failure; the message never includes internals
503UNAVAILABLEThe database or a configured service is unreachable, or a job is not configured

On this page