Skip to main content
v1 · public api

Codaiq API

Build with Codaiq projects, websites, and leads from your own backend. Every request is authenticated with a bearer-style API key. Read and write scopes are issued per key.


How to authenticate

Issue a key in your dashboard, then send it on every request:

Authorization: Bearer cdaq_live_<your-key>

List the projects your key can see:

curl https://codaiq.com/api/v1/projects \
  -H "Authorization: Bearer cdaq_live_..."

Capture a lead from a marketing site:

curl -X POST https://codaiq.com/api/v1/websites/<websiteId>/leads \
  -H "Authorization: Bearer cdaq_live_..." \
  -H "Content-Type: application/json" \
  -d '{"email":"hello@example.com","name":"Ada","message":"hi"}'

Keys are shown once at issue time. Store them in your secret manager — Codaiq cannot recover a lost key. The same is true for the webhookSecret returned alongside it. Revoke a key any time with DELETE /api/api-keys/<id>.

Scopes

Each key carries one or more scopes. Issue narrowly-scoped keys per integration — broader scopes are easier to misuse.

  • adminsuperuser on the key's scoped org (every other scope is implied).
  • projects:read, projects:write
  • websites:read, websites:write
  • leads:read, leads:write
  • generate:runcall POST /api/v1/generate.
  • read, writelegacy umbrella scopes (deprecated, kept for back-compat).

Webhook signing

When a lead is captured against a website that has metadata.webhookUrl configured, Codaiq POSTs a signed event to that URL. Verify the delivery before trusting it:

X-Codaiq-Timestamp: 1717420000000
X-Codaiq-Signature: t=1717420000000,v1=<hex(hmac-sha256(`${ts}.${rawBody}`, webhookSecret))>

Reject deliveries whose timestamp is more than ±5 minutes from your clock, then constant-time compare your re-computed HMAC against the v1= portion of the signature.

Response envelope

Every v1 response uses a stable JSON envelope:

// success
{
  "ok": true,
  "data": { ... },
  "meta": { "requestId": "req_...", "rateLimit": { "limit": 60, "remaining": 59, "resetMs": 60000 } }
}

// failure
{
  "ok": false,
  "error": { "code": "rate_limited", "message": "..." },
  "meta": { "requestId": "req_..." }
}

Standard rate-limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are also returned for convenience.

Endpoints

get/api/v1/projects
List projects owned by the calling key.
scope: projects:read
get/api/v1/projects/{id}
Get project detail.
scope: projects:read
get/api/v1/projects/{id}/websites
List websites under a project.
scope: websites:read
get/api/v1/websites/{id}
Get website detail.
scope: websites:read
get/api/v1/websites/{id}/leads
List leads for a website (paginated by `_id` cursor).
scope: leads:read
post/api/v1/websites/{id}/leads
Capture a lead from external code. When the website has `metadata.webhookUrl` set AND the API key has a `webhookSecret`, the new lead is signed and POSTed to the webhookUrl asynchronously (fire-and-forget). See the WebhookHeaders schema for the signature format.
scope: leads:write

Spec

The full OpenAPI 3.1 spec is served at /api/v1/openapi.json.

Command Palette

Search for a page or run an action.