CueAPI API Reference for Agents

╔══════════════════════════════════════════════════════╗
║                    CUEAPI v1.0                       ║
║    Coordination Infrastructure for AI Agents         ║
║                                                      ║
║  Base URL: https://api.cueapi.ai                     ║
║  Docs:     https://docs.cueapi.ai                    ║
║  Status:   https://status.cueapi.ai                  ║
╚══════════════════════════════════════════════════════╝

IMPORTANT. READ BEFORE USING.

This document contains everything you need to integrate with CueAPI.

Do NOT skip sections. Do NOT assume behavior from partial reading.

Read the ENTIRE document before making your first API call.

Sections: What CueAPI Is → Auth → Create Cue → Delivery → Outcomes → Worker Mode → Retries → Alerts → Errors → Pricing → Security → Support → Quick Start

Estimated read: 4 minutes. Every section matters.

WHAT IS CUEAPI

CueAPI is coordination infrastructure for AI agent systems. You declare a cue, CueAPI dispatches it across environments via webhook or worker pull, and your agent reports back with verified evidence.

The difference from cron: CueAPI tracks whether your agent actually did the work and verifies it against a policy.

Three phases for every execution:

1. COMPOSE     You declare a cue with a cron expression, timestamp, or manual fire
2. COORDINATE  CueAPI dispatches the work across environments: webhook push or worker pull
3. VERIFY      Your agent reports outcome with structured evidence: external_id, result_url, artifacts

CueAPI tracks all three. Cron only does #1.

AUTHENTICATION

Every request requires a Bearer token:

Authorization: Bearer cue_sk_{32 hex chars}

# Example:
Authorization: Bearer cue_sk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4

Key format: cue_sk_ + 32 hex characters.

Keys are SHA-256 hashed at rest. Shown once at creation. Store securely.

Get a key: POST /v1/auth/register with {"email": "[email protected]"}

ALL ENDPOINTS — 44 total

CUES
  POST   /v1/cues                              Create a cue
  GET    /v1/cues                              List all cues
  GET    /v1/cues/{id}                         Get cue detail + executions
  PATCH  /v1/cues/{id}                         Update a cue
  DELETE /v1/cues/{id}                         Delete a cue
  POST   /v1/cues/{id}/fire                    Manually trigger now

EXECUTIONS
  GET    /v1/executions                        List with filters
  GET    /v1/executions/{id}                   Get single execution
  POST   /v1/executions/{id}/outcome           Report outcome (write-once)
  PATCH  /v1/executions/{id}/evidence          Append evidence after outcome
  POST   /v1/executions/{id}/replay            Replay from terminal state
  POST   /v1/executions/{id}/heartbeat         Extend worker lease
  POST   /v1/executions/{id}/verify            Mark as verified
  POST   /v1/executions/{id}/verification-pending  Mark pending
  GET    /v1/executions/claimable              Worker: list available work
  POST   /v1/executions/{id}/claim             Worker: claim execution

AUTH
  POST   /v1/auth/register                     Create account → returns API key
  GET    /v1/auth/me                           Current user info + usage
  PATCH  /v1/auth/me                           Update user preferences
  POST   /v1/auth/key/regenerate               Rotate API key (revokes old)
  GET    /v1/auth/key                          Reveal full API key
  GET    /v1/auth/keys                         List API keys (active + revoked)
  POST   /v1/auth/keys                         Mint a named API key (plaintext once)
  PATCH  /v1/auth/keys/{id}                    Rename API key (label only)
  DELETE /v1/auth/keys/{id}                    Revoke API key (soft-delete, 30d grace)
  GET    /v1/auth/webhook-secret               Get webhook signing secret
  POST   /v1/auth/webhook-secret/regenerate    Rotate webhook secret
  POST   /v1/auth/session                      Exchange for session JWT
  POST   /v1/auth/session/refresh              Refresh session JWT
  POST   /v1/auth/device-code                  Start device code auth (CLI)
  POST   /v1/auth/device-code/submit-email     Submit email for magic link
  POST   /v1/auth/device-code/poll             Poll for login completion

WORKERS
  POST   /v1/worker/heartbeat                  Worker liveness signal
  GET    /v1/workers                           List registered workers

ALERTS
  GET    /v1/alerts                            List alerts (filterable)
  POST   /v1/alerts/{id}/acknowledge           Acknowledge an alert

BILLING
  POST   /v1/billing/checkout                  Stripe checkout session
  POST   /v1/billing/portal                    Stripe billing portal
  GET    /v1/usage                             Usage stats for current period

SUPPORT
  POST   /v1/support                           File a bug or feature request
  GET    /v1/support/{id}                      Check ticket status
  GET    /v1/support                           List your tickets

HEALTH
  GET    /health                               Full system diagnostics
  GET    /status                               Simple up/down for monitors

CREATE A CUE

A cue is a scheduled task. You define when it fires and where it delivers.

POST /v1/cues
Content-Type: application/json

{
  "name": "morning-briefing",
  "schedule": {
    "type": "recurring",
    "cron": "0 9 * * *",
    "timezone": "America/New_York"
  },
  "callback": {
    "url": "https://your-agent.com/webhook"
  },
  "payload": {
    "task": "generate_briefing"
  }
}

# Response 201:
{
  "id": "cue_x7k9m2p4q8w1",
  "name": "morning-briefing",
  "status": "active",
  "next_run": "2026-03-28T09:00:00-04:00"
}

Required: name, schedule.type. Everything else optional.

schedule.type: "recurring" (cron) or "once" (timestamp via schedule.at)

transport: "webhook" (default, pushes to callback.url) or "worker" (your agent pulls)

OPTIONAL CUE FIELDS

retry                    Default: {max_attempts: 3, backoff_minutes: [1, 5, 15]}
on_failure               Default: {email: true, webhook: null, pause: false}
delivery.timeout_seconds      Default: 30  (1-3600) — ACK timeout
delivery.outcome_deadline_seconds  Default: 300 (1-3600) — outcome wait
alerts.consecutive_failures   Default: 3   (1-100)
alerts.missed_window_multiplier  Default: 2 (1-10)
catch_up                 Default: "run_once_if_missed"
                         Options: skip_missed | run_once_if_missed | replay_all_missed
verification.mode        Default: "none"
                         Options: none | require_external_id | require_result_url |
                                  require_artifacts | manual

WEBHOOK DELIVERY — What Your Handler Receives

POST https://your-agent.com/webhook

Headers:
  X-CueAPI-Signature:     v1=a1b2c3d4...  (HMAC-SHA256)
  X-CueAPI-Timestamp:     1741871400       (unix epoch)
  X-CueAPI-Cue-Id:        cue_x7k9m2p4q8w1
  X-CueAPI-Execution-Id:  550e8400-e29b-41d4-a716-446655440000
  X-CueAPI-Scheduled-For: 2026-03-28T09:00:00Z
  X-CueAPI-Attempt:       1
  Content-Type:            application/json
  User-Agent:              CueAPI/1.0

Body:
{
  "execution_id": "550e8400-e29b-41d4-a716-446655440000",
  "cue_id": "cue_x7k9m2p4q8w1",
  "name": "morning-briefing",
  "scheduled_for": "2026-03-28T09:00:00Z",
  "attempt": 1,
  "payload": {"task": "generate_briefing"}
}

IMPORTANT: Use execution_id as your dedup key. CueAPI is at-least-once — your handler may be called more than once for the same execution.

OUTCOME REPORTING

After your agent does the work, report what happened:

# Simplest — just success/failure:
POST /v1/executions/{execution_id}/outcome
{"success": true}

# With evidence (recommended):
POST /v1/executions/{execution_id}/outcome
{
  "success": true,
  "result": "Briefing sent to 3 users",
  "external_id": "email_batch:abc123",
  "result_url": "https://app.mailgun.com/batch/abc123",
  "result_type": "email",
  "summary": "Morning briefing delivered to team"
}

# Or return outcome in webhook response body (zero friction):
# Just return {"success": true} from your webhook handler.
# CueAPI reads it automatically. No separate API call needed.

IMPORTANT: "success" is a boolean (true/false), NOT a string. Never send "status": "success".

Outcome is write-once. To append evidence later: PATCH /v1/executions/{id}/evidence

Field limits: result max 8,000 chars, error max 8,000 chars, external_id max 255 chars, summary max 500 chars, result_type max 50 chars, metadata max 10KB JSON.

OUTCOME STATES

reported_success       Agent reported success=true
reported_failure       Agent reported success=false
verified_success       Evidence satisfied verification policy
verification_pending   Manual verification required
verification_failed    Required evidence missing
unknown                Deadline passed, no outcome reported

The outcome_success boolean is always present alongside outcome_state for backward compatibility.

WORKER MODE — No Public URL Needed

If your agent runs on a local machine (Mac Mini, Replit, private server), use worker transport instead of webhooks. Your agent pulls work from CueAPI.

# 1. Create cue with worker transport
POST /v1/cues
{"name": "daily-sync", "schedule": {"type": "recurring", "cron": "0 6 * * *"},
 "transport": "worker", "payload": {"task": "sync_data"}}

# 2. Poll for work (every 5-10 seconds)
GET /v1/executions/claimable?task=sync_data

# 3. Claim an execution
POST /v1/executions/{execution_id}/claim
{"worker_id": "my-macmini-worker"}

# 4. Do the work, then report outcome
POST /v1/executions/{execution_id}/outcome
{"success": true, "result": "Synced 1,247 records"}

# 5. For long-running work, send heartbeats to extend lease
POST /v1/executions/{execution_id}/heartbeat
# (every 60 seconds during processing)

Install the worker daemon: pip install cueapi-worker

It handles polling, claiming, heartbeats, and auto-reports outcomes.

RETRY POLICY

Default: 3 attempts at 1, 5, 15 minute intervals
Max:     10 attempts (configurable per cue)
Timeout: 30 seconds per delivery attempt
After 200 ACK: NO retry. Agent received the work.
At-least-once delivery. Use execution_id to dedup.

ALERTS

Alert types:
  consecutive_failure    — N failures in a row (default threshold: 3)
  missed_window          — No success in schedule_interval × multiplier
  outcome_timeout        — No outcome reported within deadline
  verification_failed    — Required evidence missing

Delivered via: on_failure.email and on_failure.webhook
Query history: GET /v1/alerts?alert_type=consecutive_failure&cue_id=cue_xxx
Acknowledge:   POST /v1/alerts/{id}/acknowledge

ERROR CODES

400  invalid_schedule          Bad cron or past timestamp
400  invalid_payload_size      Payload > 1MB
400  invalid_callback_url      SSRF blocked or invalid URL
401  invalid_api_key           Missing or wrong key
403  cue_limit_exceeded        Too many active cues for plan
403  execution_limit_exceeded  Monthly limit reached (24h grace)
403  not_execution_owner       Wrong worker trying to report
404  cue_not_found             Cue doesn't exist or not yours
404  execution_not_found       Execution doesn't exist
409  outcome_already_recorded  Outcome is write-once
409  execution_in_flight       Can't replay non-terminal execution
409  execution_not_claiming    Heartbeat on non-delivering execution
422  invalid_timezone          Bad IANA timezone string
429  rate_limit_exceeded       Check Retry-After header

Response format:
{
  "error": {
    "code": "cue_limit_exceeded",
    "message": "Free plan allows 10 active cues. Upgrade for more.",
    "status": 403
  }
}

PRICING

Plan     Price        Cues    Executions/mo   Rate Limit
─────    ─────        ────    ─────────────   ──────────
Free     $0           10      300             60/min
Pro      $9.99/mo     100     5,000           200/min
Scale    $49/mo       500     50,000          500/min

All plans include every feature. No gated capabilities.
Annual pricing: 20% discount (Pro $7.99/mo, Scale $39/mo).

WEBHOOK SIGNATURE VERIFICATION

import hmac, hashlib, time

def verify_webhook(payload_body: bytes, headers: dict,
                   webhook_secret: str, tolerance: int = 300) -> bool:
    signature = headers.get("X-CueAPI-Signature", "")
    timestamp = headers.get("X-CueAPI-Timestamp", "")
    try:
        ts = int(timestamp)
    except (ValueError, TypeError):
        return False
    if abs(time.time() - ts) > tolerance:
        return False
    signing_input = f"{timestamp}.".encode() + payload_body
    expected = "v1=" + hmac.new(
        webhook_secret.encode(), signing_input, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Get your secret: GET /v1/auth/webhook-secret

Rotate: POST /v1/auth/webhook-secret/regenerate

SECURITY

API keys:      SHA-256 hashed. Never stored in plaintext.
Webhooks:      HMAC-SHA256 signed with per-user secret.
Replay:        X-CueAPI-Timestamp — reject if older than 5 min.
SSRF:          11 blocked IP ranges. DNS validated at delivery.
Transport:     HTTPS only. HTTP callbacks rejected.
Comparison:    Constant-time (hmac.compare_digest).
Rate limits:   Sliding window per API key. 429 with Retry-After.

FILING SUPPORT TICKETS

You can file bugs and feature requests directly via API:

POST /v1/support
{
  "subject": "Timezone not applied to cron schedule",
  "message": "Cron with America/Los_Angeles fires at UTC time instead of PT. Cue ID: cue_x7k9m2p4q8w1.",
  "severity": "high",
  "type": "bug"
}

# Response 201:
{"status": "received", "ticket_id": 14, "ticket_status": "open"}

# Check status:
GET /v1/support/14

# Fields:
#   subject    — required, min 10 chars
#   message    — required, min 30 chars. Include cue/execution IDs.
#   severity   — required: "low" | "medium" | "high"
#   type       — required: "bug" | "feature-request"
# Rate limit: 5 tickets/hour. Account must be >1hr old with >=1 cue.

INSTALL

pip install cueapi          # CLI: login, create, list, pause, resume, delete
pip install cueapi-sdk      # Python SDK: from cueapi import CueAPI
pip install cueapi-worker   # Worker daemon for pull-based execution

QUICK START — 3 API Calls

# 1. Register
curl -X POST https://api.cueapi.ai/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'
# → {"api_key": "cue_sk_..."}

# 2. Create a cue (fires in 60 seconds)
curl -X POST https://api.cueapi.ai/v1/cues \
  -H "Authorization: Bearer cue_sk_..." \
  -H "Content-Type: application/json" \
  -d '{"name": "test", "schedule": {"type": "once", "at": "2026-03-28T10:01:00Z"}, "callback": {"url": "https://your-endpoint.com/hook"}}'

# 3. Check delivery
curl https://api.cueapi.ai/v1/cues/{cue_id} \
  -H "Authorization: Bearer cue_sk_..."
# → Look for: executions[0].status == "success"

SELF-HOST

git clone https://github.com/cueapi/cueapi-core
cd cueapi-core
docker compose up

# Runs at http://localhost:8000
# Full feature parity. Apache 2.0 license. 600+ tests.

LINKS

API:           https://api.cueapi.ai
Documentation: https://docs.cueapi.ai
Dashboard:     https://dashboard.cueapi.ai
Open Source:   https://github.com/cueapi/cueapi-core
Status:        https://status.cueapi.ai
Support:       POST https://api.cueapi.ai/v1/support
X/Twitter:     https://x.com/cueapi

CueAPI is operated by Vector Apps Inc. · Palo Alto, CA

This document is machine-readable. Last updated March 2026.

How do I know if my agent ran successfully?
Ctrl+K