SuperCoolDocs Get an API key

Reference

API reference

Every endpoint of the SuperCool API: parameters, request and response schemas, errors, and curl, Python and JavaScript samples.

View as Markdown

Base URL: https://api.supercool.com/v1. Authenticate with Authorization: Bearer sc_key_… (Authentication). Requests and responses are JSON; errors share one shape. Download the spec as OpenAPI JSON or YAML.

#Messages

Talk to your agent and follow the work it starts.

#Send a message

POST /v1/messages

Sends your agent a message, optionally with files. The call returns within about 30 seconds: either the finished answer, or status: "processing" when the agent started longer work. Follow a processing message with GET /messages/{message_id} (use ?wait= to long-poll), its events, or a webhook.

Returns 201 for a new message and 200 when an Idempotency-Key replays an existing one. Running out of credits is not an error: the message comes back with status: "blocked" and reason: "out_of_credits". Neither is the running-jobs cap: work the agent can't start because 5 jobs are already running comes back as a blocked job with reason: "too_many_running", and the message lists the running work.

Parameters

NameTypeDescription
Idempotency-Keystring headerAny string up to 128 characters, unique per logical request. Scoped to the API key and kept for 7 days: sending it again with the same body returns the same message (200) and never starts work twice; with a different body it's 409 idempotency_conflict.

Request body MessageCreate

FieldTypeDescription
messagestringWhat you want, in plain language. Up to 20,000 characters; send longer text as a file.
filesarray of InlineFileSmall files inline (up to 5, 10 MB each, 25 MB in total). Each has a url or base64. A file that can't be fetched doesn't fail the message: it's listed in the message's notes.
upload_idsarray of stringFinished uploads to attach (up to 10, 1 GB in total). See POST /uploads.
webhook_endpoint_idstring | nullSend this message's webhook events to this registered endpoint (whe_…) instead of the account's endpoints.

Responses

  • 200 An Idempotency-Key you already used with the same body. The same message, as it is now. Returns Message.
  • 201 The message was accepted. It is either final already or processing. Returns Message.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 409 The request conflicts with the current state.
  • 413 A file or upload is over the size limit.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 400 empty_message 400 too_long 400 too_many 401 unauthorized 404 not_found 409 idempotency_conflict 409 upload_not_ready 413 too_large 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/messages" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-8812-ad" \
  -d '{
    "message": "A 15 second vertical ad for my candle shop, warm and cozy"
  }'
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/messages",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}", "Idempotency-Key": "order-8812-ad"},
    json={
        "message": "A 15 second vertical ad for my candle shop, warm and cozy",
    },
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "order-8812-ad",
  },
  body: JSON.stringify({
    "message": "A 15 second vertical ad for my candle shop, warm and cozy"
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

#Get a message

GET /v1/messages/{message_id}

One message: its status, the agent's reply, the jobs it started and the files they made. With wait, the call holds for up to that many seconds and returns as soon as something changes (the status, the reply arriving, or a job's status) or the message is final.

Messages are kept for at least 14 days after their last job's deadline. After that this returns 404 not_found; read the work instead (GET /work/{work_id}).

Parameters

NameTypeDescription
message_id requiredstring pathThe message's id (msg_…).
waitinteger queryLong-poll for up to this many seconds (0 to 45). 0 returns immediately. Default 0.

Responses

  • 200 The message. Returns Message.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d?wait=30" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    params={"wait": 30},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d?wait=30", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
  "object": "message",
  "status": "completed",
  "reason": null,
  "question": null,
  "final": true,
  "reply": "On it. I'm making a 15 second vertical ad with warm candlelight shots.",
  "jobs": [
    {
      "job_id": "exe_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
      "kind": "execution",
      "role": "execution",
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "title": "Candle shop vertical ad",
      "status": "completed",
      "reason": null,
      "final": true,
      "queued": null,
      "resume_by": null,
      "link": "https://supercool.com/chat/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "started_at": "2026-09-30T14:02:11.402000Z",
      "settled_at": "2026-09-30T14:06:40.221000Z",
      "files": [
        {
          "file_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4",
          "name": "candle_ad.mp4",
          "content_type": "video/mp4",
          "kind": "video",
          "size": 4812345,
          "url": "https://api.supercool.sh/api/v1/files/s/eyJmIjoiNWQwYzNl...",
          "revision": "\"5b1c0e6f9d2a4b7c8e1f3a5d7c9b0e2f\"",
          "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
          "label": null
        }
      ]
    }
  ],
  "files": [
    {
      "file_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4",
      "name": "candle_ad.mp4",
      "content_type": "video/mp4",
      "kind": "video",
      "size": 4812345,
      "url": "https://api.supercool.sh/api/v1/files/s/eyJmIjoiNWQwYzNl...",
      "revision": "\"5b1c0e6f9d2a4b7c8e1f3a5d7c9b0e2f\"",
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "label": null
    }
  ],
  "notes": [],
  "credits_used": 42.5,
  "created_at": "2026-09-30T14:02:03.118000Z",
  "updated_at": "2026-09-30T14:02:12.950000Z"
}

#List a message's events

GET /v1/messages/{message_id}/events

The message's update log, oldest first: progress steps, late replies, each job's result with its files, and state changes. Only this message's entries: another message's progress in the same chat isn't included. Pass back the cursor from the previous page to get only what's new. With no cursor, the log starts where the message started. done is true once the message has nothing more to report.

The call waits at least one second, and up to wait seconds, for new entries. Only one wait per message runs at a time (409 poll_in_progress otherwise). Entries are kept for 7 days; a cursor older than that returns cursor_expired: true with a fresh cursor.

Parameters

NameTypeDescription
message_id requiredstring pathThe message's id (msg_…).
cursorstring queryThe cursor from the previous page. Opaque.
waitinteger queryWait up to this many seconds for new entries (0 to 45; at least 1 second is always waited). Default 0.

Responses

  • 200 A page of events. Returns EventList.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 409 The request conflicts with the current state.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 400 bad_cursor 401 unauthorized 404 not_found 409 poll_in_progress 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/events?wait=30" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/events",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    params={"wait": 30},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/events?wait=30", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "list",
  "data": [
    {
      "seq": 118,
      "type": "progress",
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "message_id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
      "at": "2026-09-30T14:03:02.000000Z",
      "step": "Rendering the video",
      "status": "started",
      "file_names": []
    },
    {
      "seq": 121,
      "type": "result",
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "message_id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
      "at": "2026-09-30T14:06:40.000000Z",
      "title": "Candle shop vertical ad",
      "text": "Your 15 second ad is ready.",
      "outcome": "completed",
      "files": []
    }
  ],
  "has_more": false,
  "done": true,
  "cursor": "eyJjIjoiYXBpOnU..."
}

#Recover a message's results

POST /v1/messages/{message_id}/recover

For work that outlived its watch (a job or message that expired): re-arms the watch so the result is looked up again and lands in the message, its events and your webhooks. It never resends the message or starts new work. One entry per piece of work: settled (already has its outcome), watching (still being watched), recovering (re-armed now) or exhausted (recovered too many times; read the work).

Parameters

NameTypeDescription
message_id requiredstring pathThe message's id (msg_…).

Responses

  • 200 What happened to each piece of work. Returns Recovery.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/recover" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/recover",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d/recover", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
  "object": "recovery",
  "work": [
    {
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "state": "recovering"
    }
  ]
}

#Uploads

Attach large files (up to 500 MB each) to a message.

#Start an upload

POST /v1/uploads

Starts a large upload (up to 500 MB). Returns a presigned POST: send a multipart/form-data POST to url with every entry of fields as form fields and the file last, as a field named file. The link is valid for 15 minutes. Then call POST /uploads/{upload_id}/complete and pass the upload_id in a message's upload_ids. Uploads never attached to a message are deleted after 24 hours.

Request body UploadCreate

FieldTypeDescription
filename requiredstring
size requiredintegerThe exact size in bytes (up to 500 MB). The upload is capped at this size.
content_typestring | nullThe MIME type. Guessed from the file name when omitted. The POST must send the same Content-Type field (it is in fields).

Responses

  • 201 The upload was created. POST the file to url next. Returns UploadCreated.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 413 A file or upload is over the size limit.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 400 bad_size 401 unauthorized 413 too_large 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/uploads" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "product-shoot.mov",
    "size": 157286400,
    "content_type": "video/quicktime"
  }'
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/uploads",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    json={
        "filename": "product-shoot.mov",
        "size": 157286400,
        "content_type": "video/quicktime",
    },
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/uploads", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "filename": "product-shoot.mov",
    "size": 157286400,
    "content_type": "video/quicktime"
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 201

json
{
  "object": "upload",
  "upload_id": "up_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "url": "https://supercool-uploads.s3.amazonaws.com/",
  "fields": {
    "key": "agent-uploads/incoming/.../product-shoot.mov",
    "Content-Type": "video/quicktime",
    "policy": "eyJleHBpcmF0aW9uIjoi...",
    "x-amz-signature": "3f1c..."
  },
  "expires_at": "2026-09-30T14:17:03.118000Z",
  "max_bytes": 157286400
}

#Complete an upload

POST /v1/uploads/{upload_id}/complete

Finalizes an upload after the file was POSTed to the presigned url. The file is checked (its real size, and executables are refused) and becomes ready to attach. Calling it again on a ready upload returns the same result.

Parameters

NameTypeDescription
upload_id requiredstring pathThe upload_id from POST /uploads (up_…).

Responses

  • 200 The upload is ready to attach. Returns Upload.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 409 The request conflicts with the current state.
  • 413 A file or upload is over the size limit.
  • 422 The uploaded file was refused (an executable).
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 409 not_pending 409 not_uploaded 409 changed 413 too_large 422 executable_refused 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/uploads/up_0a1b2c3d4e5f60718293a4b5c6d7e8f9/complete" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/uploads/up_0a1b2c3d4e5f60718293a4b5c6d7e8f9/complete",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/uploads/up_0a1b2c3d4e5f60718293a4b5c6d7e8f9/complete", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "upload",
  "upload_id": "up_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
  "status": "ready",
  "filename": "product-shoot.mov",
  "content_type": "video/quicktime",
  "size": 157286400
}

#Work

The chats your agent works in, the same ones you see in the app.

#List recent work

GET /v1/work

Your agent's recent work (chats), newest first: the same list you see in the app, whether the work was started over the API, in the app, by phone or anywhere else.

Parameters

NameTypeDescription
limitinteger queryHow many to return (1 to 50). Default 20.

Responses

  • 200 Recent work. Returns WorkList.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 401 unauthorized 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/work?limit=10" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/work",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    params={"limit": 10},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/work?limit=10", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "list",
  "data": [
    {
      "object": "work",
      "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
      "title": "Candle shop vertical ad",
      "preview": "Your 15 second ad is ready.",
      "link": "https://supercool.com/chat/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f"
    }
  ]
}

#Get a piece of work

GET /v1/work/{work_id}

One piece of work: whether it's running, the latest result text (paged with from_char / next_from_char) and its most recent files (up to 8), each with a fresh download link.

Parameters

NameTypeDescription
work_id requiredstring pathThe work_id from a job, an event or GET /work.
from_charinteger queryRead the text from this character on (use the previous next_from_char). Default 0.

Responses

  • 200 The work. Returns Work.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/work/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/work/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/work/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "work",
  "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
  "title": "Candle shop vertical ad",
  "status": "idle",
  "text": "Your 15 second ad is ready. I used warm, slow push-ins on the candles...",
  "next_from_char": null,
  "link": "https://supercool.com/chat/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
  "files": []
}

#Files

Download what the agent made.

#Get a file

GET /v1/files/{file_id}

A file's record with a fresh signed download link. Use it when a url has expired, or when a download answered 412 because the file changed since the link was made. File ids contain slashes (<work_id>/<path>); put them in the path as they are.

Parameters

NameTypeDescription
file_id requiredstring pathThe file_id from a message, job, event or work (<work_id>/<path>, slashes included).

Responses

  • 200 The file. Returns FileObject.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/files/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/files/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/files/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "file",
  "file_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f/candle_ad.mp4",
  "name": "candle_ad.mp4",
  "content_type": "video/mp4",
  "kind": "video",
  "size": 4812345,
  "url": "https://api.supercool.sh/api/v1/files/s/eyJmIjoiNWQwYzNl...",
  "revision": "\"5b1c0e6f9d2a4b7c8e1f3a5d7c9b0e2f\"",
  "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
  "label": null
}

#Account

Who the key belongs to, the plan, credits and limits.

#Get the account

GET /v1/me

The account the API key belongs to, its plan, available credits, the agent's name, the key itself and your limits.

Responses

  • 200 The account. Returns Account.
  • 401 The API key is missing, unknown or revoked.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/me" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/me",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/me", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "account",
  "user_id": "64f1c2a9e4b0a1b2c3d4e5f6",
  "email": "[email protected]",
  "name": "Sam Rivera",
  "plan": "pro",
  "credits": 1840,
  "agent": {
    "name": "Nova"
  },
  "key": {
    "id": "pat:6a1b2c3d4e5f",
    "name": "prod server"
  },
  "limits": {
    "running_jobs": 5,
    "requests_per_minute": 600
  }
}

#Webhooks

Get pushed events instead of polling.

#List webhook endpoints

GET /v1/webhooks

The account's webhook endpoints (up to 10).

Responses

  • 200 The endpoints. Returns WebhookEndpointList.
  • 401 The API key is missing, unknown or revoked.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/webhooks" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/webhooks",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "list",
  "data": [
    {
      "object": "webhook_endpoint",
      "id": "whe_4c1d2e3f4a5b6c7d8e9f",
      "url": "https://example.com/hooks/supercool",
      "events": [
        "*"
      ],
      "description": "prod",
      "created_at": "2026-09-30T13:40:00.000000Z",
      "disabled_at": null,
      "disabled_reason": null,
      "failing_since": null
    }
  ]
}

#Create a webhook endpoint

POST /v1/webhooks

Registers a public https URL (port 443 or 8443) to receive events. The response includes the endpoint's signing secret (whsec_…). It is shown only this once: store it now. Omit events (or pass ["*"]) to receive every event.

Request body WebhookCreate

FieldTypeDescription
url requiredstringA public https URL (port 443 or 8443, up to 2,000 characters).
eventsarray of string | nullEvents to receive, or ["*"] for all (the default).
descriptionstring | nullUp to 120 characters.

Responses

  • 201 The endpoint, with its secret (shown once). Returns WebhookEndpointWithSecret.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 409 The request conflicts with the current state.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 400 bad_url 400 bad_events 400 bad_request 401 unauthorized 409 too_many_endpoints 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/webhooks" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/supercool",
    "events": [
      "message.completed",
      "message.failed",
      "message.blocked"
    ],
    "description": "prod"
  }'
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/webhooks",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    json={
        "url": "https://example.com/hooks/supercool",
        "events": [
            "message.completed",
            "message.failed",
            "message.blocked",
        ],
        "description": "prod",
    },
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "url": "https://example.com/hooks/supercool",
    "events": [
      "message.completed",
      "message.failed",
      "message.blocked"
    ],
    "description": "prod"
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 201

json
{
  "object": "webhook_endpoint",
  "id": "whe_4c1d2e3f4a5b6c7d8e9f",
  "url": "https://example.com/hooks/supercool",
  "events": [
    "message.completed",
    "message.failed",
    "message.blocked"
  ],
  "description": "prod",
  "created_at": "2026-09-30T13:40:00.000000Z",
  "disabled_at": null,
  "disabled_reason": null,
  "failing_since": null,
  "secret": "whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw"
}

#Get a webhook endpoint

GET /v1/webhooks/{endpoint_id}

One endpoint and its 20 most recent deliveries.

Parameters

NameTypeDescription
endpoint_id requiredstring pathThe webhook endpoint's id (whe_…).

Responses

  • 200 The endpoint. Returns WebhookEndpointDetail.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.get(
    "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f", {
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "webhook_endpoint",
  "id": "whe_4c1d2e3f4a5b6c7d8e9f",
  "url": "https://example.com/hooks/supercool",
  "events": [
    "*"
  ],
  "description": "prod",
  "created_at": "2026-09-30T13:40:00.000000Z",
  "disabled_at": null,
  "disabled_reason": null,
  "failing_since": null,
  "recent_deliveries": [
    {
      "object": "webhook_delivery",
      "id": "evt_7d8e9f0a1b2c3d4e5f6a7b8c",
      "event": "message.completed",
      "status": "delivered",
      "attempts": 1,
      "last_status_code": 200,
      "last_error": null,
      "last_response": "ok",
      "last_ms": 184,
      "created_at": "2026-09-30T14:06:41.000000Z",
      "delivered_at": "2026-09-30T14:06:41.000000Z",
      "next_attempt_at": "2026-09-30T14:06:41.000000Z",
      "message_id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d"
    }
  ]
}

#Update a webhook endpoint

PATCH /v1/webhooks/{endpoint_id}

Changes an endpoint's URL, events or description, or turns it off and on. Send only the fields to change. "enabled": true turns a disabled endpoint back on (after you fixed it) and clears its failure state.

Parameters

NameTypeDescription
endpoint_id requiredstring pathThe webhook endpoint's id (whe_…).

Request body WebhookUpdate

FieldTypeDescription
urlstring | null
eventsarray of string | null
descriptionstring | null
enabledboolean | nulltrue turns the endpoint back on and clears its failure state; false turns it off.

Responses

  • 200 The updated endpoint. Returns WebhookEndpoint.
  • 400 The request can't be processed as sent. invalid_request (with problems) when it doesn't match the schema.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

400 invalid_request 400 bad_url 400 bad_events 400 bad_request 401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl -X PATCH "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true
  }'
Python
import os
import requests

resp = requests.patch(
    "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    json={
        "enabled": True,
    },
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "enabled": true
  }),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

#Delete a webhook endpoint

DELETE /v1/webhooks/{endpoint_id}

Deletes the endpoint. Deliveries still waiting to be sent to it are cancelled.

Parameters

NameTypeDescription
endpoint_id requiredstring pathThe webhook endpoint's id (whe_…).

Responses

  • 200 Deleted. Returns Deleted.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl -X DELETE "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.delete(
    "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f", {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "webhook_endpoint",
  "id": "whe_4c1d2e3f4a5b6c7d8e9f",
  "deleted": true
}

#Rotate a signing secret

POST /v1/webhooks/{endpoint_id}/rotate-secret

Replaces the endpoint's signing secret and returns the new one (shown once). Every delivery from now on is signed with the new secret, including retries of earlier events.

Parameters

NameTypeDescription
endpoint_id requiredstring pathThe webhook endpoint's id (whe_…).

Responses

  • 200 The new secret. Returns RotatedSecret.
  • 401 The API key is missing, unknown or revoked.
  • 404 Nothing with that id for this API key or account.
  • 429 A rate limit was hit. Wait Retry-After seconds.

Errors

401 unauthorized 404 not_found 429 rate_limited

Example request

curl
curl -X POST "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f/rotate-secret" \
  -H "Authorization: Bearer $SUPERCOOL_API_KEY"
Python
import os
import requests

resp = requests.post(
    "https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f/rotate-secret",
    headers={"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"},
    timeout=60,
)
resp.raise_for_status()
print(resp.json())
JavaScript
const res = await fetch("https://api.supercool.com/v1/webhooks/whe_4c1d2e3f4a5b6c7d8e9f/rotate-secret", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}`,
  },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error}: ${data.message} (${data.request_id})`);
console.log(data);

Example response 200

json
{
  "object": "webhook_endpoint",
  "id": "whe_4c1d2e3f4a5b6c7d8e9f",
  "secret": "whsec_Q2hhbmdlZC1zZWNyZXQtZXhhbXBsZTEy"
}

#Webhook events

What SuperCool POSTs to your endpoints. See Webhooks for signatures and retries.

#A job changed

Sent when one job (one piece of work) changes: job.completed, job.failed, job.blocked, job.resumed or job.expired. data is the job, with its message_id and files. Signed with the Standard Webhooks headers.

Headers

HeaderTypeDescription
webhook-id requiredstringThe delivery's id (evt_…). The same across retries of one event; use it to drop duplicates.
webhook-timestamp requiredstringUnix seconds when this attempt was signed.
webhook-signature requiredstringv1, + base64 HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{body}, keyed with the base64-decoded part of your whsec_ secret.

Payload

FieldTypeDescription
typestringOne of job.completed, job.failed, job.blocked, job.resumed, job.expired.
timestampstring
dataobject
object"job"
message_idstring
job_idstringexe_… for work that ran or is queued; ref_… for work refused before it was queued.
kindstringOne of execution, refusal.
rolestringfollow_up when the message joined work that was already running; its status follows that work. One of execution, follow_up.
work_idstring | nullThe chat the work runs in.
titlestring | null
statusstring JobStatusOne of running, completed, failed, cancelled, blocked, expired.
reasonstring | nullFor blocked, failed, cancelled and expired: out_of_credits, hosting_fees, too_many_running, execution_failed, stopped, queue_expired, watch_expired, result_unknown.
finalbooleanfalse while running, and for queued work waiting for credits (it can still run).
queuedboolean | nulltrue for work that is queued and waiting for credits; otherwise null.
resume_bystring | nullFor queued work waiting for credits, the deadline to add them (24 hours after it was queued).
linkstring | nullThe work in the SuperCool app.
started_atstring | null
settled_atstring | null
filesarray of File

Example payload

json
{
  "type": "job.completed",
  "timestamp": "2026-09-30T14:06:40.310000Z",
  "data": {
    "object": "job",
    "message_id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
    "job_id": "exe_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
    "kind": "execution",
    "role": "execution",
    "work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
    "title": "Candle shop vertical ad",
    "status": "completed",
    "reason": null,
    "final": true,
    "queued": null,
    "resume_by": null,
    "link": "https://supercool.com/chat/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
    "started_at": "2026-09-30T14:02:11.402000Z",
    "settled_at": "2026-09-30T14:06:40.221000Z",
    "files": []
  }
}

#A message reached a status

Sent once each time a message reaches a status other than processing: message.completed, message.partial, message.failed, message.needs_input, message.blocked or message.expired. data is the full message, exactly as GET /messages/{message_id} returns it.

Headers

HeaderTypeDescription
webhook-id requiredstringThe delivery's id (evt_…). The same across retries of one event; use it to drop duplicates.
webhook-timestamp requiredstringUnix seconds when this attempt was signed.
webhook-signature requiredstringv1, + base64 HMAC-SHA256 of {webhook-id}.{webhook-timestamp}.{body}, keyed with the base64-decoded part of your whsec_ secret.

Payload

FieldTypeDescription
typestringOne of message.completed, message.partial, message.failed, message.needs_input, message.blocked, message.expired.
timestampstring
dataMessageA message you sent and everything that came of it.

#Objects

#MessageCreate

A message to your agent. Send message, files, or both.

FieldTypeDescription
messagestringWhat you want, in plain language. Up to 20,000 characters; send longer text as a file.
filesarray of InlineFileSmall files inline (up to 5, 10 MB each, 25 MB in total). Each has a url or base64. A file that can't be fetched doesn't fail the message: it's listed in the message's notes.
upload_idsarray of stringFinished uploads to attach (up to 10, 1 GB in total). See POST /uploads.
webhook_endpoint_idstring | nullSend this message's webhook events to this registered endpoint (whe_…) instead of the account's endpoints.

#InlineFile

FieldTypeDescription
namestring | nullA file name for the agent to see.
urlstring | nullA public https URL to fetch the file from.
base64string | nullThe file's bytes, base64-encoded.
content_typestring | nullThe MIME type, for base64 files.

#Message

A message you sent and everything that came of it.

FieldTypeDescription
id requiredstringThe message id (msg_…), always generated by SuperCool.
object required"message"
status requiredstring MessageStatusOne of processing, needs_input, blocked, completed, partial, failed, expired.
reasonstring | nullWhy, for blocked, failed, partial and expired: out_of_credits, hosting_fees, too_many_running, queue_expired, watch_expired, result_unknown, execution_failed, stopped, agent_busy, turn_failed and others. See Getting results.
questionstring | nullFor needs_input, the agent's question. Answer by sending a new message.
final requiredbooleantrue when nothing about this message will change any more. Stop polling.
replystring | nullWhat the agent said, once it has answered.
jobs requiredarray of JobThe pieces of work this message started, each with its own status.
files requiredarray of FileEvery file the message produced (handed over in the reply, or made by its jobs).
notes requiredarray of stringProblems with attachments (a file that couldn't be fetched, files over the limit).
credits_used requirednumberCredits this message's jobs used so far.
created_at requiredstring
updated_at requiredstringWhen the agent's turn ended (or created_at while it's still going).
resume"add_credits"Present when queued work is waiting for credits: add credits before resume_by and it runs by itself. Don't resend the message.
resume_bystringThe earliest deadline among queued jobs waiting for credits (24 hours after they were queued).
retry_after_secondsintegerWith reason: "agent_busy": retry with the same Idempotency-Key after this many seconds.
runningarray of objectPresent when the agent tried to start work while 5 jobs were already running on the account (a job with reason: "too_many_running"): the work running now, and the message that started each.
job_idstringexe_…
message_idstring
work_idstring

#MessageStatus

The message's status, aggregated over its jobs.

string One of processing, needs_input, blocked, completed, partial, failed, expired.

#Job

One piece of work a message started (or was refused).

FieldTypeDescription
job_idstringexe_… for work that ran or is queued; ref_… for work refused before it was queued.
kindstringOne of execution, refusal.
rolestringfollow_up when the message joined work that was already running; its status follows that work. One of execution, follow_up.
work_idstring | nullThe chat the work runs in.
titlestring | null
statusstring JobStatusOne of running, completed, failed, cancelled, blocked, expired.
reasonstring | nullFor blocked, failed, cancelled and expired: out_of_credits, hosting_fees, too_many_running, execution_failed, stopped, queue_expired, watch_expired, result_unknown.
finalbooleanfalse while running, and for queued work waiting for credits (it can still run).
queuedboolean | nulltrue for work that is queued and waiting for credits; otherwise null.
resume_bystring | nullFor queued work waiting for credits, the deadline to add them (24 hours after it was queued).
linkstring | nullThe work in the SuperCool app.
started_atstring | null
settled_atstring | null
filesarray of File

#JobStatus

string One of running, completed, failed, cancelled, blocked, expired.

#File

A file the agent made or handed over.

FieldTypeDescription
file_idstring<work_id>/<path>. Use it with GET /files/{file_id} for a fresh link.
namestring
content_typestring | null
kindstringOne of image, video, audio, doc, site.
sizeinteger | nullBytes. null for a site.
urlstring | nullA signed download link. It expires, and it is pinned to revision; a download answers 412 if the file changed since.
revisionstring | nullThe file's version the link is pinned to. null for a site (its link always opens the live site).
work_idstring | null
labelstring | null

#FileObject

A file the agent made or handed over.

FieldTypeDescription
object"file"
file_idstring<work_id>/<path>. Use it with GET /files/{file_id} for a fresh link.
namestring
content_typestring | null
kindstringOne of image, video, audio, doc, site.
sizeinteger | nullBytes. null for a site.
urlstring | nullA signed download link. It expires, and it is pinned to revision; a download answers 412 if the file changed since.
revisionstring | nullThe file's version the link is pinned to. null for a site (its link always opens the live site).
work_idstring | null
labelstring | null

#EventList

FieldTypeDescription
object"list"
dataarray of Event
has_morebooleanMore entries are ready; call again with cursor right away.
donebooleanThe message has nothing more to report.
cursorstringPass this back as cursor for the next page.
cursor_expiredbooleanYour cursor pointed at entries older than 7 days. cursor restarts from now.

#Event

One entry in a message's update log. Fields beyond the common ones depend on type.

FieldTypeDescription
seqinteger
typestringresult (a job finished, with text and files), progress (a step started or a file landed), agent_reply (the agent's reply), state (resumed, stopped, expired, unknown), turn_failed, turn_busy. One of result, progress, agent_reply, state, turn_failed, turn_busy.
work_idstring | null
message_idstring | nullThe message the entry belongs to, when known.
atstring
job_idstringThe job (exe_…) the entry belongs to, when known.
titlestring | nullresult
textstring | nullresult, agent_reply, state, turn_failed, turn_busy
outcomestringresult One of completed, failed, stalled_credits.
filesarray of Fileresult, agent_reply
statestringstate
stepstring | nullprogress
statusstring | nullprogress
file_namesarray of stringprogress: names of files that just landed (download them from the result).
delivered_syncboolean | nullagent_reply: true when this reply was already in the POST /messages response.
reasonstring | nullturn_failed, turn_busy

#Recovery

FieldTypeDescription
idstring
object"recovery"
workarray of object
work_idstring
statestringOne of settled, watching, recovering, exhausted.
outcomestringFor settled, how it ended.

#UploadCreate

FieldTypeDescription
filename requiredstring
size requiredintegerThe exact size in bytes (up to 500 MB). The upload is capped at this size.
content_typestring | nullThe MIME type. Guessed from the file name when omitted. The POST must send the same Content-Type field (it is in fields).

#UploadCreated

FieldTypeDescription
object"upload"
upload_idstring
urlstringWhere to POST the file (multipart/form-data).
fieldsobjectForm fields to send with the file, exactly as given.
expires_atstringThe presigned POST works until then (15 minutes).
max_bytesinteger

#Upload

FieldTypeDescription
object"upload"
upload_idstring
statusstringOne of ready.
filenamestring
content_typestring
sizeinteger

#WorkList

FieldTypeDescription
object"list"
dataarray of WorkSummary

#WorkSummary

FieldTypeDescription
object"work"
work_idstring
titlestring | null
previewstring | null
linkstring

#Work

FieldTypeDescription
object"work"
work_idstring
titlestring | null
statusstringrunning, stalled_credits (stopped until credits are added), or idle. One of running, stalled_credits, idle.
textstringThe latest result text, from from_char.
next_from_charinteger | nullPass as from_char to read on; null when there's no more.
linkstring
filesarray of FileThe most recent files (up to 8).

#Account

FieldTypeDescription
object"account"
user_idstring
emailstring | null
namestring | null
planstring | null
creditsnumber | nullCredits available now.
agentobject
namestring
keyobject
idstring
namestring
limitsobject
running_jobsintegerRunning jobs allowed per account (5).
requests_per_minuteintegerRequests allowed per API key per minute (600).

#WebhookEventType

string One of job.completed, job.failed, job.blocked, job.resumed, job.expired, message.completed, message.partial, message.failed, message.needs_input, message.blocked, message.expired.

#WebhookCreate

FieldTypeDescription
url requiredstringA public https URL (port 443 or 8443, up to 2,000 characters).
eventsarray of string | nullEvents to receive, or ["*"] for all (the default).
descriptionstring | nullUp to 120 characters.

#WebhookUpdate

FieldTypeDescription
urlstring | null
eventsarray of string | null
descriptionstring | null
enabledboolean | nulltrue turns the endpoint back on and clears its failure state; false turns it off.

#WebhookEndpoint

FieldTypeDescription
object"webhook_endpoint"
idstringwhe_…
urlstring
eventsarray of string
descriptionstring | null
created_atstring
disabled_atstring | nullSet when the endpoint is off (by you, or after 3 days of failed deliveries).
disabled_reasonstring | null
failing_sincestring | nullWhen deliveries started failing. Cleared by the next success.

#WebhookEndpointWithSecret

FieldTypeDescription
object"webhook_endpoint"
idstringwhe_…
urlstring
eventsarray of string
descriptionstring | null
created_atstring
disabled_atstring | nullSet when the endpoint is off (by you, or after 3 days of failed deliveries).
disabled_reasonstring | null
failing_sincestring | nullWhen deliveries started failing. Cleared by the next success.
secretstringThe signing secret (whsec_…). Shown only in this response.

#WebhookEndpointDetail

FieldTypeDescription
object"webhook_endpoint"
idstringwhe_…
urlstring
eventsarray of string
descriptionstring | null
created_atstring
disabled_atstring | nullSet when the endpoint is off (by you, or after 3 days of failed deliveries).
disabled_reasonstring | null
failing_sincestring | nullWhen deliveries started failing. Cleared by the next success.
recent_deliveriesarray of WebhookDelivery

#WebhookEndpointList

FieldTypeDescription
object"list"
dataarray of WebhookEndpoint

#WebhookDelivery

FieldTypeDescription
object"webhook_delivery"
idstringThe delivery id (evt_…), sent as webhook-id.
eventstring WebhookEventTypeOne of job.completed, job.failed, job.blocked, job.resumed, job.expired, message.completed, message.partial, message.failed, message.needs_input, message.blocked, message.expired.
statusstringOne of pending, delivered, cancelled, dead.
attemptsinteger
last_status_codeinteger | null
last_errorstring | null
last_responsestring | nullThe first 4 KB of your endpoint's last response.
last_msinteger | null
created_atstring
delivered_atstring | null
next_attempt_atstring | null
message_idstring | null

#RotatedSecret

FieldTypeDescription
object"webhook_endpoint"
idstring
secretstring

#Deleted

FieldTypeDescription
object"webhook_endpoint"
idstring
deletedtrue

#JobEvent

FieldTypeDescription
typestringOne of job.completed, job.failed, job.blocked, job.resumed, job.expired.
timestampstring
dataobject
object"job"
message_idstring
job_idstringexe_… for work that ran or is queued; ref_… for work refused before it was queued.
kindstringOne of execution, refusal.
rolestringfollow_up when the message joined work that was already running; its status follows that work. One of execution, follow_up.
work_idstring | nullThe chat the work runs in.
titlestring | null
statusstring JobStatusOne of running, completed, failed, cancelled, blocked, expired.
reasonstring | nullFor blocked, failed, cancelled and expired: out_of_credits, hosting_fees, too_many_running, execution_failed, stopped, queue_expired, watch_expired, result_unknown.
finalbooleanfalse while running, and for queued work waiting for credits (it can still run).
queuedboolean | nulltrue for work that is queued and waiting for credits; otherwise null.
resume_bystring | nullFor queued work waiting for credits, the deadline to add them (24 hours after it was queued).
linkstring | nullThe work in the SuperCool app.
started_atstring | null
settled_atstring | null
filesarray of File

#MessageEvent

FieldTypeDescription
typestringOne of message.completed, message.partial, message.failed, message.needs_input, message.blocked, message.expired.
timestampstring
dataMessageA message you sent and everything that came of it.

#Error

Every API error has this shape.

FieldTypeDescription
error requiredstring ErrorCodeOne of bad_request, invalid_request, empty_message, too_long, bad_cursor, bad_url, bad_events, bad_size, too_many, unauthorized, not_found, idempotency_conflict, poll_in_progress, too_many_endpoints, not_pending, not_uploaded, changed, upload_not_ready, too_large, executable_refused, rate_limited, internal, unavailable.
message requiredstringWhat went wrong, for people.
request_id requiredstringThe request's id (req_…), also in the Request-Id header.
docs requiredstringA link to this error code's documentation.
problemsarray of objectWith invalid_request: what doesn't match, one entry per problem (up to 10).
fieldstring | nullThe dotted location of the field (like files.0.url or wait), or null for the body as a whole.
problemstring
cursorstringWith poll_in_progress: the cursor to use when you call again.

#ErrorCode

A stable, machine-readable error code. Each one is documented at https://supercool.com/docs/api/errors#<code>.

string One of bad_request, invalid_request, empty_message, too_long, bad_cursor, bad_url, bad_events, bad_size, too_many, unauthorized, not_found, idempotency_conflict, poll_in_progress, too_many_endpoints, not_pending, not_uploaded, changed, upload_not_ready, too_large, executable_refused, rate_limited, internal, unavailable.

Last updated