docsCatalog.eyebrow

API reference

This is the public REST surface of the Gurulu Truth Layer during closed beta. Admin, internal ops, and platform observability endpoints are not listed here — they are scoped to operator credentials and are not part of the customer contract.

Two base URLs:

  • Data planehttps://ingest.gurulu.io. Anything that accepts events.
  • Control planehttps://api.gurulu.io. Everything else.

Authentication

Two credential types:

  • Bearer JWT. Issued to a logged-in user via magic link (primary) or OAuth (Google or GitHub, PKCE S256). Used for control-plane calls a human makes.
  • API key. Two flavors. pk_live_* is a public key — safe to ship in browser code, used by the browser SDK. sk_live_* is a secret key — never ships to the browser, used by the server SDK and by direct REST callers.

All responses are UTF-8 JSON. Errors follow RFC 7807 application/problem+json.

Auth endpoints

POST   /v1/auth/magic-link             Request a magic link email
POST   /v1/auth/magic-link/verify      Exchange a magic-link token for a session
GET    /v1/auth/oauth/:provider        Begin OAuth (Google or GitHub)
POST   /v1/auth/session/refresh        Refresh an access token
POST   /v1/auth/session/revoke         Revoke a session
POST   /v1/auth/api-keys               Mint a new API key

Ingest — sending events

The public data plane. Validation gate runs here.

POST   /v1/track                       Send a single event
POST   /v1/batch                       Send up to N events in a single call
POST   /v1/identify                    Bind an anonymous_id to a person_id
POST   /v1/alias                       Merge two identities
POST   /v1/webhook/:provider           Receive a vendor webhook

Every event in the body must pass the validation gate. Possible outcomes per event:

  • accept — registered, well-formed, well-known. Goes through.
  • warn — accepted with a non-fatal issue (unexpected property type, deprecated key).
  • quarantine — held for review. Does not reach downstream destinations.
  • reject — refused. Returned in the response with a reason.

Registry — the contract

The registry is the source of truth for event names and shapes. Event keys must match ^[a-z0-9_]+$.

GET    /v1/registry/events             List event contracts
POST   /v1/registry/events             Create a new event contract
GET    /v1/registry/events/:key        Read a single contract
POST   /v1/registry/validate           Validate a payload against the registry
GET    /v1/registry/code-gen           Get typed code-gen for an environment
GET    /v1/registry/packs              List industry seed packs

Code-gen returns typed bindings for TypeScript, Python, and Swift. The CLI (gurulu pull) wraps these endpoints and writes the result into your repo.

Identity — the spine

Seven-step resolve, three-level confidence, append-only merge ledger. Every merge is reversible.

POST   /v1/identity/resolve            Resolve an identifier set to a person_id
GET    /v1/identity/person/:id         Read a person record
GET    /v1/identity/person/:id/timeline   Get the timeline of events for a person
POST   /v1/identity/merge              Explicitly merge two records
GET    /v1/identity/merge-ledger       Read the append-only merge log

Health — quality signal

Event health: anomaly detection, dedup, coverage, CAPI mismatch.

GET    /v1/health/events               Health summary across the workspace
GET    /v1/health/events/:key          Per-event health
GET    /v1/health/anomalies            Detected anomalies (volume, schema, latency)
GET    /v1/health/coverage             Coverage score per surface
POST   /v1/health/dedup-check          Ask if two records look like duplicates

Attribution — credit and provenance

Customer-defined policy, multi-model (first, last, linear, time-decay, position, data-driven), and full provenance trace per outcome.

POST   /v1/attribution/policy                       Define / update the attribution policy
POST   /v1/attribution/compute                      Recompute attribution for a date range
GET    /v1/attribution/touchpoints/:personId        Touchpoints considered for a person
GET    /v1/attribution/explain/:outcomeId           Explanation trace for a specific outcome

The explain endpoint returns: which touchpoints were considered, which were excluded, which model was applied, and what alternative models would have credited.

Consent — GDPR, KVKK, CCPA

GCM v2 categories. DSR export and forget on a 60-second SLA queue.

POST   /v1/consent                     Record consent state for a person
GET    /v1/consent/:personId           Read current consent
POST   /v1/consent/dsr/export          Queue a data export request
POST   /v1/consent/dsr/forget          Queue a forget request

SDKs

Direct REST is fine. Most teams use the SDKs:

  • @gurulu/web — zero-dependency browser bundle (8.1 KB gzip). Five autocapture signals, identify, track, consent, replay opt-in.
  • @gurulu/node — server SDK for Node 20+, Bun, edge. Webhook verifiers for 23 vendors. Middleware for Hono, Express, Fastify.
  • @gurulu/cligurulu init / pull / push / validate / doctor. Wires the registry into your Git flow.
  • @gurulu/mcp-server — MCP for Cursor, Claude Code, Lovable. Tools: list_events, add_event, validate_event. Your AI editor stops guessing event names.

Errors

All errors are application/problem+json and carry:

  • type — a stable URL identifier for the error class.
  • title — short human description.
  • status — HTTP status code.
  • detail — what went wrong on this specific request.
  • instance — opaque request identifier you can quote when filing a bug.

The validation-gate rejection is type: "https://gurulu.io/errors/contract-violation". The response body lists which fields failed and why.

Status

The full endpoint surface is ~270 routes today; this page lists the customer-facing public subset. Operator and platform endpoints are not part of the customer contract and may change without notice. The list above is stable for closed beta.

For the conceptual model behind these endpoints, see How it works.