Python SDK

Official Python SDK for CueAPI: install, client init, cues, executions, outcomes, webhook verification, and typed errors.

The official Python SDK for CueAPI. Schedule cues, report execution outcomes with evidence, and verify webhook signatures.

Install

bash
pip install cueapi-sdk

Requires Python 3.9+. Source: github.com/cueapi/cueapi-python.

Quick start

python
from cueapi import CueAPI
 
client = CueAPI("cue_sk_your_key")
 
cue = client.cues.create(
    name="daily-report",
    cron="0 9 * * *",
    callback="https://my-app.com/webhook",
)
 
print(cue.id, cue.next_run_at)

The client implements the context-manager protocol, so the underlying HTTP connection cleans up automatically:

python
with CueAPI("cue_sk_your_key") as client:
    for cue in client.cues.list().cues:
        print(cue.name)

Client

CueAPI(api_key, *, base_url=..., timeout=...)

ArgumentDefaultDescription
api_key— (required)Your API key (starts with cue_sk_).
base_urlhttps://api.cueapi.aiOverride for self-hosted or staging environments.
timeout30.0Request timeout in seconds.

Methods: client.close() to release the HTTP pool. Resources: client.cues, client.executions.

client.cues

create(name, *, cron=None, at=None, ...)

Create a recurring or one-time cue. Provide either cron or at (not both).

python
# Recurring
cue = client.cues.create(
    name="daily-sync",
    cron="0 9 * * *",
    timezone="America/Los_Angeles",
    callback="https://api.example.com/sync",
)
 
# One-time
cue = client.cues.create(
    name="reminder",
    at="2026-05-01T14:00:00Z",
    callback="https://api.example.com/notify",
)
 
# Worker transport (no callback URL needed)
cue = client.cues.create(
    name="agent-task",
    cron="0 * * * *",
    transport="worker",
    payload={"task": "summarize-inbox"},
)
 
# With on-failure escalation
cue = client.cues.create(
    name="critical-job",
    cron="*/5 * * * *",
    callback="https://api.example.com/run",
    on_failure={"after_attempts": 3, "notify": "[email protected]"},
)
KwargTypeDescription
namestrRequired. Cue name.
cronstrCron expression (use this or at).
atstr | datetimeISO timestamp for one-time cues.
timezonestrIANA timezone. Default "UTC".
callbackstrWebhook URL. Omit for worker transport.
callback_methodstrHTTP method. Default "POST".
callback_headersdictExtra headers for webhook delivery.
transportstr"webhook" (default) or "worker".
payloaddictJSON delivered with each execution.
descriptionstrOptional description.
retrydict{max_attempts, backoff_minutes}.
on_failuredictEscalation config (e.g. {after_attempts, notify}).

list(*, limit=20, offset=0, status=None) -> CueList

Paginated listing. status filters to "active" or "paused".

get(cue_id) -> Cue

Fetch a single cue.

update(cue_id, *, name=None, cron=None, at=None, callback=None, payload=None, status=None, retry=None, on_failure=None, timezone=None, description=None) -> Cue

Patch a cue. Only provided fields are updated.

pause(cue_id) -> Cue / resume(cue_id) -> Cue

Convenience wrappers for update(cue_id, status=...).

delete(cue_id) -> None

Permanently delete a cue.

client.executions

report_outcome(execution_id, *, success, ...)

Write-once outcome report for an execution. Reporting twice raises an error server-side.

python
client.executions.report_outcome(
    execution_id="exec_a1b2c3",
    success=True,
    summary="Generated 47 leads",
    external_id="lead-batch-2026-04-19",  # link to your system
    result_ref="batch-id:7842",            # short opaque reference
    result_url="https://my-app.com/batches/7842",
    result_type="lead-batch",
    artifacts=[{"name": "leads.csv", "url": "https://..."}],
    metadata={"agent": "lead-finder-v3"},
)
KwargTypeDescription
execution_idstrRequired. The execution to report on.
successboolRequired. Was the execution successful?
resultstrFree-form result text (truncated to 2000 chars when used via handle()).
errorstrFree-form error text on failure.
summarystrShort human-readable summary.
external_idstrID in your system for linking.
result_refstrShort opaque reference (added in SDK 0.1.4).
result_urlstrURL where the artifact lives.
result_typestrTag for the result type ("report", "lead-batch", etc.).
artifactslist[dict]Attached artifacts ([{name, url, ...}]).
metadatadictFree-form metadata blob.

The fields external_id, result_url, result_ref, result_type, summary, and artifacts together form the evidence surface used by verification modes.

handle(execution_id, payload=None) -> ExecutionContext

Context manager that auto-reports outcome based on whether the block exits cleanly.

python
with client.executions.handle(exec_id) as ctx:
    result = do_work(ctx.payload)
    ctx.result = f"Processed {result.count} records"
    ctx.evidence = {"external_id": result.batch_id, "result_url": result.url}
# Clean exit -> POST success=True with result + evidence
# Exception  -> POST success=False with stringified exception

The ctx.evidence dict is unpacked into report_outcome() kwargs on success.

list(*, cue_id=None, status=None, outcome_state=None, triggered_by=None, limit=20, offset=0) -> dict

List executions with optional filters.

get(execution_id) -> dict

Fetch a single execution.

heartbeat(execution_id) -> dict

Extend the worker's claim lease on a long-running execution. Worker transport only.

mark_verification_pending(execution_id) -> dict

Mark the outcome as pending verification (used when verification is async).

mark_verified(execution_id, *, valid=True, reason=None) -> dict

Complete verification on a previously-reported outcome.

Webhook signature verification

python
from cueapi import verify_webhook
 
# In your webhook handler
is_valid = verify_webhook(
    payload=request.body,
    signature=request.headers["X-CueAPI-Signature"],
    timestamp=request.headers["X-CueAPI-Timestamp"],
    secret="whsec_your_secret",  # from /v1/auth/webhook-secret
    tolerance=300,  # max age in seconds
)
 
if not is_valid:
    return Response(status=401)

verify_webhook accepts the payload as bytes, str, or dict. It re-serializes JSON with sorted keys before comparing the HMAC-SHA256 digest, matching the server's signing convention.

Exceptions

All exceptions inherit from CueAPIError.

ExceptionStatusWhen
AuthenticationError401Invalid API key.
CueLimitExceededError403Plan limit hit (cues or executions).
CueNotFoundError404Cue or execution doesn't exist.
RateLimitError429Sliding-window rate limit exceeded. Has retry_after attr.
InvalidScheduleError400 / 422Validation error (typically schedule).
CueAPIServerError5xxServer-side error.
CueAPIErrorotherCatch-all.
python
from cueapi import CueAPI
from cueapi.exceptions import RateLimitError, CueNotFoundError
 
client = CueAPI("cue_sk_your_key")
 
try:
    client.cues.get("cue_does_not_exist")
except CueNotFoundError:
    print("not found")
except RateLimitError as e:
    print(f"slow down — retry after {e.retry_after}s")

Source

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