REST API
Read everything the dashboard shows, from a script, with an API key.
Get a key
Site settings → API keys. The secret is shown once, at creation, and never again: Zowar stores only a SHA-256 hash of it, so it cannot be recovered. If you lose one, revoke it and make another.
Keys belong to your account, not to a single site, and carry the same permissions you have. They are read-only unless you tick Allow writes — an agent reading analytics has no reason to be able to change a lead’s status.
A read-only key is refused by every endpoint with a side effect, including the one that creates keys — so a leaked read-only key cannot mint a wider one.
Authenticating
curl -H "Authorization: Bearer pulse_sk_..." \
"https://pulse.ninee.studio/api/analytics/dashboard?site_id=1&days=30"A request carrying a bearer token is never treated as a browser request, so a stale session cookie in the same client cannot answer for a revoked key.
Date ranges
Every reporting endpoint takes either a relative window or explicit dates. Explicit dates win when both are given, and both ends are inclusive whole days in UTC.
- days=30
- The last 30 days, ending today. The default.
- start=2026-03-03&end=2026-03-03
- One specific day, in full.
- start=2026-03-01&end=2026-03-31
- An explicit span.
- start=2026-03-01
- That day onwards, to today.
Endpoints
Site-scoped endpoints take site_id; reporting endpoints also accept a date range. Site listing does not require a site ID.
| Endpoint | Returns |
|---|---|
GET /api/sites | Sites this key can read |
GET /api/analytics/dashboard | Sessions, pageviews, leads, conversion rate, daily traffic, top pages and channels |
GET /api/analytics/funnel | The funnel stages; takes channel |
GET /api/analytics/events | Every event type with counts and sessions |
GET /api/analytics/geo | Visits by country and city (optional Google reporting) |
GET /api/analytics/realtime | The last half hour |
GET /api/visitors | Individual visits; takes channel, limit, offset |
GET /api/visitors/{session_id} | One visit's full timeline |
GET /api/visitors/paths | The journey map: columns, links and exits |
GET /api/leads | Leads with their attribution |
PATCH /api/leads/{id} | Change status or note — needs a write key |
GET /api/search-console/overview | Impressions, clicks, CTR, position, top queries |
GET /api/google-ads/spend | Cost, clicks and impressions per campaign |
GET /api/google-ads/keywords | Keywords, search terms and networks with cost and conversions |
GET /api/google-analytics/overview | GA4 figures, reported separately |
The full schema, with every parameter and response shape, is served as OpenAPI at /api/openapi.json and browsable at /api/docs.
CRM configuration and writes
GET /api/crm/config?site_id=1 reads forms and stages. POST /api/crm/forms and PATCH /api/crm/forms/FORM_ID edit form definitions. PUT /api/crm/stages stores stage labels and order. POST /api/crm/leads creates manual leads; POST /api/crm/leads/LEAD_ID/move stores a stage and position. All write operations require write access. See /docs/crm for request examples.
GET /api/features returns the effective google_reporting flag. Google report endpoints above are optional and unavailable while that flag is false; first-party analytics remains available.
Errors
- 401
- No key, or the key was revoked.
- 403
- The key is read-only, or the site belongs to another account.
- 404
- No such site, visit or lead.
- 422
- A malformed range — reversed dates, a bad format, or an absurd span.
- 503
- An optional reporting integration is disabled or unavailable.
- 429
- Rate limited. Applies to the public collector, not to key-authenticated reads.