Get started
Quickstart
Get an API key, send your SuperCool agent a message, wait for the work to finish and download the files, with curl, Python or JavaScript.
This takes about five minutes, plus however long the agent takes to make what you asked for. You need a SuperCool account. Any plan works.
#1. Get an API key
Open the API dashboard (Dashboard → API) and create a key. Give it a nickname, like "prod server" or "my laptop". The full key (sc_key_…) is shown once, so copy it now.
Put it in an environment variable. Never commit it or ship it to a browser.
export SUPERCOOL_API_KEY="sc_key_..."Check that it works:
curl https://api.supercool.com/v1/me -H "Authorization: Bearer $SUPERCOOL_API_KEY"You should see your account, your plan, your available credits and your agent's name.
#2. Send a message
Tell the agent what you want in plain language. The Idempotency-Key header makes the request safe to retry: if the connection drops and you send it again with the same key, you get the same message back instead of starting the work twice.
curl https://api.supercool.com/v1/messages \
-H "Authorization: Bearer $SUPERCOOL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"message": "A 15 second vertical ad for my candle shop, warm and cozy"}'import os
import uuid
import requests
API = "https://api.supercool.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['SUPERCOOL_API_KEY']}"}
resp = requests.post(
f"{API}/messages",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"message": "A 15 second vertical ad for my candle shop, warm and cozy"},
timeout=60,
)
resp.raise_for_status()
msg = resp.json()
print(msg["id"], msg["status"], msg["reply"])// Node 18+ (save as quickstart.mjs)
import { randomUUID } from "node:crypto";
const API = "https://api.supercool.com/v1";
const headers = { Authorization: `Bearer ${process.env.SUPERCOOL_API_KEY}` };
const res = await fetch(`${API}/messages`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": randomUUID() },
body: JSON.stringify({ message: "A 15 second vertical ad for my candle shop, warm and cozy" }),
});
const msg = await res.json();
console.log(msg.id, msg.status, msg.reply);The call returns within about 30 seconds. For a video, the agent replies and starts the work, so the message comes back as processing with one running job:
{
"id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
"object": "message",
"status": "processing",
"final": false,
"reply": "On it. I'm making a 15 second vertical ad with warm candlelight shots.",
"jobs": [
{
"job_id": "exe_9b2c4d6e8f0a1b3c5d7e9f1a2b4c6d8e",
"work_id": "5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
"title": "Candle shop vertical ad",
"status": "running",
"link": "https://supercool.com/chat/5d0c3e2a-8f1b-4c6d-9e7f-1a2b3c4d5e6f",
"files": []
}
],
"files": [],
"credits_used": 0
}A simple question ("what's a good tagline for a candle shop?") comes back completed right away, with the answer in reply.
#3. Wait for the result
Call GET /v1/messages/{id} with ?wait=30. The call holds for up to 30 seconds and returns as soon as something changes. Repeat until final is true.
curl "https://api.supercool.com/v1/messages/msg_3f9a1c2e7b8d4e5f6a7b8c9d?wait=30" \
-H "Authorization: Bearer $SUPERCOOL_API_KEY"while not msg["final"]:
if msg.get("resume") == "add_credits":
print("Out of credits: add some before", msg["resume_by"], "and the work resumes by itself.")
break
resp = requests.get(f"{API}/messages/{msg['id']}", headers=HEADERS, params={"wait": 30}, timeout=60)
resp.raise_for_status()
msg = resp.json()
for job in msg["jobs"]:
print(f" {job['title']}: {job['status']}")
print("Finished:", msg["status"], msg["reason"] or "")let current = msg;
while (!current.final && current.resume !== "add_credits") {
const r = await fetch(`${API}/messages/${current.id}?wait=30`, { headers });
current = await r.json();
for (const job of current.jobs) console.log(` ${job.title}: ${job.status}`);
}
console.log("Finished:", current.status, current.reason ?? "");When the video is done, the message is completed, final is true, and files lists what the agent made:
{
"id": "msg_3f9a1c2e7b8d4e5f6a7b8c9d",
"status": "completed",
"final": true,
"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..."
}
],
"credits_used": 42.5
}Other outcomes, like needs_input (the agent has a question), blocked (out of credits) or partial, are explained in Getting results.
#4. Download the files
Each file's url is a signed link, so you don't need to send your API key with it. Download it like any URL:
curl -L -o candle_ad.mp4 "https://api.supercool.sh/api/v1/files/s/eyJmIjoiNWQwYzNl..."for f in msg["files"]:
with requests.get(f["url"], stream=True, timeout=300) as r:
r.raise_for_status()
with open(f["name"], "wb") as out:
for chunk in r.iter_content(chunk_size=1 << 20):
out.write(chunk)
print("Saved", f["name"])import { writeFile } from "node:fs/promises";
for (const f of current.files) {
const r = await fetch(f.url);
if (!r.ok) throw new Error(`download failed: ${r.status}`);
await writeFile(f.name, Buffer.from(await r.arrayBuffer()));
console.log("Saved", f.name);
}Links expire. If one has, or if the download answers 412 because the file changed since the link was made, get a fresh one from GET /v1/files/{file_id}.
#Next steps
- Skip polling: register a webhook and get a signed POST when the message is done.
- Send files: attach images, PDFs or footage to a message. See Files & uploads.
- Follow up: send another message like "make it 9:16 and add captions" and the agent continues the same work. See Sending messages.
- Handle every outcome: read Getting results and Rate limits & errors.
- Watch it in the app: every job's
linkopens its chat in SuperCool.