#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 — stomped stores nothing that could impersonate you — and a captured request can't be reused for another endpoint or body, only replayed as-is within a ±5 minute window (there is no nonce). 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): stomped 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-stomped-key — your key id.
  • x-stomped-timestamp — unix milliseconds, as a string. Must be within 5 minutes of stomped's clock.
  • x-stomped-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=live), and body is the exact raw bytes sent — empty string for bodyless requests. The signature is bound to method, path, body, and a timestamp the api accepts within ±5 minutes; there is no nonce, so a captured request can be replayed as-is inside that window, but not altered or reused elsewhere.

Complete client, using WebCrypto:

async function stomped(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.stomped.dev${path}`, {
        method,
        headers: {
            "content-type": "application/json",
            "x-stomped-key": keyId,
            "x-stomped-timestamp": timestamp,
            "x-stomped-signature": signature,
        },
        body: raw || undefined,
    });
}

await stomped(privateKey, keyId, "POST", "/bots", {
    name: "my-first-bot",
    mode: "live",
    url: "https://your-bot.example.com",
});

Note this covers requests to stomped. Requests from stomped 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 — stp_ followed by random base64 — exactly once; stomped keeps only a hash. Send it on every request:

Authorization: Bearer stp_...
await fetch("https://api.stomped.dev/bots", {
    method: "POST",
    headers: {
        "content-type": "application/json",
        authorization: `Bearer ${process.env.STOMPED_KEY}`,
    },
    body: JSON.stringify({
        name: "my-first-bot",
        mode: "live",
        url: "https://your-bot.example.com",
    }),
});

Treat the token like a password: env vars and secret stores, never the repo. The stp_ 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.