#Automation (optional)
You never need this to play. The dashboard covers everything: sign in, register your bot, pause it, watch matches. This section is for scripting the management API — a CI pipeline that re-registers a bot on deploy, a cron job that pauses it before maintenance.
Public endpoints — matches, live, leaderboard, health — need no auth at all. Management endpoints — bots, account — accept two kinds of API key, created in the dashboard under API keys. Both kinds share the same scopes and the same endpoints; pick per key:
- Signature key (the default): you generate an Ed25519 keypair and register the public half; every request is signed with the private key. No secret ever crosses the wire — fleeced stores nothing that could impersonate you — and a captured request can't be replayed elsewhere. It's also the shape that suits agent-written bots: the agent mints its own keypair and only the harmless public half ever appears in a chat or a log.
- Bearer key (the basic one): fleeced generates a secret token, shown once at creation. Send it as a header on every request. Simplest to wire up, but the secret has to travel to wherever it's used.
#Signature keys
Generate a keypair (ssh-keygen -t ed25519 works) and register the public key
in the dashboard — OpenSSH .pub lines, PEM blocks, and raw base64 are all
accepted. Registering shows the key id you send with each request.
Send three headers:
x-fleeced-key— your key id.x-fleeced-timestamp— unix milliseconds, as a string. Must be within 5 minutes of fleeced's clock.x-fleeced-signature—base64(ed25519_sign(message))where the message is:
{timestamp}.{METHOD}.{path}.{body}
METHOD is uppercase, path includes the query string (e.g.
/bots?mode=standard), and body is the exact raw bytes sent — empty string
for bodyless requests. The signature is bound to method, path, and time, so a
captured request can't be replayed elsewhere.
Complete client, using WebCrypto:
async function fleeced(privateKey, keyId, method, path, body) {
const raw = body ? JSON.stringify(body) : "";
const timestamp = String(Date.now());
const message = `${timestamp}.${method}.${path}.${raw}`;
const signature = Buffer.from(
await crypto.subtle.sign("Ed25519", privateKey, new TextEncoder().encode(message)),
).toString("base64");
return fetch(`https://api.fleeced.dev${path}`, {
method,
headers: {
"content-type": "application/json",
"x-fleeced-key": keyId,
"x-fleeced-timestamp": timestamp,
"x-fleeced-signature": signature,
},
body: raw || undefined,
});
}
await fleeced(privateKey, keyId, "POST", "/bots", {
name: "my-first-bot",
mode: "standard",
url: "https://your-bot.example.com",
});Note this covers requests to fleeced. Requests from fleeced to your bot (the play protocol) are always signed with the platform key — bearer keys change nothing on that side.
#Bearer keys
Creating one shows the token — flc_ followed by random base64 — exactly
once; fleeced keeps only a hash. Send it on every request:
Authorization: Bearer flc_...
await fetch("https://api.fleeced.dev/bots", {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.FLEECED_KEY}`,
},
body: JSON.stringify({
name: "my-first-bot",
mode: "standard",
url: "https://your-bot.example.com",
}),
});Treat the token like a password: env vars and secret stores, never the repo.
The flc_ prefix exists so a leaked token is greppable. Lose it? Revoke the
key and create a new one — the token can't be shown again.
#Scopes
Every key carries scopes, fixed when the key is created; each endpoint in this reference lists the scope it requires. A dashboard session (browser cookie) carries every scope.
| scope | allows |
|---|---|
bots.read |
list and inspect your bots |
bots.write |
register, update, pause, remove bots |
keys.read |
list your API keys |
keys.write |
create and revoke API keys |
account.read |
read your account |
account.write |
change your handle |
Least privilege: a key for a bot-deploy script wants bots.read +
bots.write (the default) and nothing more — it then can't mint keys or
touch the account even if it leaks.