API reference

Every public endpoint lives under https://accessiflowfiji.com/v1. All endpoints require authentication except /v1/manifest and /v1/heartbeat, which are public by design (the widget calls them from end users’ browsers).

Authentication

Create a token from Settings → API tokens. The token is shown once on creation, prefixed af_, and hashed server-side.

curl https://accessiflowfiji.com/v1/sites \
  -H "Authorization: Bearer af_xxxx…"

Tokens can be revoked anytime; requests fail immediately once revoked.

Public endpoints

GET /v1/manifest?site=SITE_KEY

Returns a signed JSON payload describing the site’s widget configuration and domain allowlist. Called by the widget on every page load (cached per visitor for 1 hour). Signature is HMAC-SHA256 over the JSON body.

Cache-Control defaults to public, max-age=3600, stale-while-revalidate=300 in production and no-store in development, so local config changes are visible on the next reload.

POST /v1/heartbeat

One fire-and-forget beacon per widget session (plus one per feature toggle). Used to populate the analytics dashboard. Body:

{
  "siteKey": "string",
  "eventType": "load" | "feature",
  "featureName": "string | null",
  "session": "string",
  "ts": number
}

Session ID is hashed (SHA-256) before storage. IP is never stored — country is read from Vercel / Cloudflare edge headers.

Authenticated endpoints

The v1 authenticated API is scoped to the token owner’s org. Sites, domains, and analytics all operate within that scope.

Sites

  • GET /v1/sites — list sites
  • POST /v1/sites — create site
  • PATCH /v1/sites/:id — update config
  • DELETE /v1/sites/:id — soft-delete
  • GET /v1/sites/:id/analytics?range=7|30|90 — daily loads + top features

Phase 5 note: the authenticated endpoints ship with the Phase 6 admin work; the widget-side public endpoints are already live. The dashboard UI already calls the same underlying code.

Webhooks

POST /v1/webhooks/paddle

Receives billing events from Paddle. Signature-verified using PADDLE_WEBHOOK_SECRET, idempotent via the paddle_webhook_events table (insert-or-skip on event id). Handles subscription.*, transaction.completed/paid, and transaction.payment_failed. Returns 200 after signature passes so Paddle never retries — processing errors are recorded on the event row for manual replay.

Rate limits

  • Writes: 60/min per user, 600/min per IP global
  • Manifest reads: no hard cap, CDN-cached for 1h
  • Heartbeat: no hard cap, validated per-site-key

OpenAPI spec

A machine-readable OpenAPI 3.1 document ships with the Phase 6 admin work at /v1/openapi.json.