DOCS · API

REST API reference

A small, predictable JSON API over your inbox: streams, cues, and connectors. Everything is scoped to the bearer token you send.

Base URL & authentication

All endpoints live under https://api.attentioncue.com. Authenticate with a bearer token minted in Settings → API tokens (the app itself uses a session cookie; both resolve to the same user).

HEADER
Authorization: Bearer cue_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Bodies are JSON. Successful mutations return the affected resource; deletes and sign-out return 204. Validation and not-found failures return the matching status with a { "message": string } body; an authentication failure (401) returns { "error": "unauthorized" }.

Endpoints

SESSION
GET/v1/session
PATCH/v1/session
DELETE/v1/session
TOKENS
GET/v1/tokens
POST/v1/tokens
DELETE/v1/tokens/:id
STREAMS
GET/v1/streams
GET/v1/streams/:id
POST/v1/streams
PATCH/v1/streams/:id
DELETE/v1/streams/:id
CUES
GET/v1/cues
GET/v1/cues/:id
POST/v1/cues/:id/clear
POST/v1/cues/:id/snooze
POST/v1/cues/:id/decide
CONNECTORS
GET/v1/connectors
POST/v1/connectors
POST/v1/connectors/:id/secret
DELETE/v1/connectors/:id

Streams

A stream is an inbox lane. GET /v1/streams returns a bare array of streams, each carrying live counts. Connectors and cues reference a stream by id.

StreamWithCounts
{
  "id": "stream_b7c1d4e2-3a5f-4e80-9c12-6d8a0f3b21e7",
  "name": "web-app",
  "slug": "web-app",
  "icon": "github",
  "kind": "service",        // "service" | "agent" | "custom"
  "color": null,
  "createdAt": "2026-06-01T09:00:00.000Z",
  "archivedAt": null,
  "open": 4,
  "needsYou": 1,
  "cleared": 12
}
CREATE
POST /v1/streams
Authorization: Bearer cue_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{
  "name": "Billing",
  "icon": "credit-card",   // optional
  "kind": "service",       // optional
  "color": null            // optional
}

Cues

A cue is one item in a stream. A notification is a quiet row; an agent_request is a blocking decision card with needsYou: true until it is decided. List results are paginated: pass the returned nextCursor back as cursor for the next page.

Cue
{
  "id": "cue_9f2a7c80-1b34-4e6d-a5f9-0c8e1d2b3a46",
  "streamId": "stream_b7c1d4e2-3a5f-4e80-9c12-6d8a0f3b21e7",
  "kind": "agent_request",  // "notification" | "agent_request"
  "title": "Delete 4 stale branches?",
  "body": null,
  "source": "web-app",
  "sourceDetail": null,
  "state": "open",          // "open" | "cleared" | "snoozed"
  "severity": "needs_you",  // "quiet" | "normal" | "needs_you"
  "needsYou": true,         // true for an undecided agent_request or a needs_you cue
  "createdAt": "2026-06-08T14:02:00.000Z",
  "clearedAt": null,
  "snoozedUntil": null,
  "expiresAt": "2026-06-09T14:02:00.000Z",
  "metadata": {
    "requestId": "req_5d6e7f80-9a1b-4c2d-8e3f-0a1b2c3d4e5f",
    "context": "Found 4 branches with no commits in 3 weeks.",
    "affected": [
      { "label": "feature/old-onboarding", "meta": "no PR · 3 weeks ago" }
    ],
    "decision": null,
    "decidedAt": null
  }
}
LIST
GET /v1/cues?streamId=stream_b7c1d4e2-3a5f-4e80-9c12-6d8a0f3b21e7&state=open&needsYou=true&limit=50

{
  "cues": [ /* Cue[] */ ],
  "nextCursor": "2026-06-08T13:40:00.000Z"  // or null
}

POST /v1/cues/:id/clear clears a cue and POST /v1/cues/:id/snooze takes { "until": iso8601 }. To resolve an agent request - the same thing the Approve / Decline buttons do - call decide:

DECIDE
POST /v1/cues/cue_9f2a7c80-1b34-4e6d-a5f9-0c8e1d2b3a46/decide
Content-Type: application/json

{ "decision": "approve" }   // "approve" | "decline"

→ 200 the settled Cue (state "cleared", needsYou false,
  metadata.decision set). The blocked agent unblocks at once.

Connectors

A connector is the source that feeds cues into a stream - it is not the stream itself. Create one against a streamId with a type and a human label. The type is one of 24 services across the dev, payments, signups, deploys, and errors pillars, plus a generic webhook - the full list and how each authenticates is in the connector guide.

A stored signing secret is never returned afterward - only a secretHint (its last four characters). The one exception: when Cue generates the secret for you, the create response includes a one-time secret field, shown once and never again.

Connector
{
  "id": "connector_4c5b6a70-8d2e-4f19-9a3b-7c1e2d4f6a80",
  "streamId": "stream_b7c1d4e2-3a5f-4e80-9c12-6d8a0f3b21e7",
  "type": "github",   // one of 24 connector types - see the connector catalog
  "label": "web-app repo",
  "secretHint": "…ab12",
  "eventMapping": {
    "push": { "title": "New push", "cueKind": "notification" }
  },
  "createdAt": "2026-06-01T09:05:00.000Z"
}

Errors

  • 400 - invalid body (fails schema validation).
  • 401 - missing or invalid token.
  • 404 - resource not found or not yours.
  • 409 - cue is not an open agent request (cannot be decided).

For the agent side of decisions - letting an AI agent raise and block on a request - see the MCP setup guide.