Rate-limited per key
Each key gets its own budget: up to 600 requests a minute. Go over and you get a 429 with the time the window resets, not a silent drop.
Developer API
vodka ships a REST API at /api/v1. Issue and revoke license keys, read per-script stats, look keys up by player, redeem, reset a device binding and manage the Discord integration, with as many scoped keys as you need and the same cryptography that protects the rest of the platform.
Create as many API keys as you need under Settings → Developer API. Name each one, scope it, and revoke or rotate it any time. The full key is shown once, at creation; vodka stores only an HMAC-SHA256 of it, never the key itself.
Authentication
Create one or more keys in Settings → Developer API. Give each a name and its own scopes, and copy it once. Each carries the prefix stf_sk_ and is never stored in readable form; only an HMAC-SHA256 of it is kept, so even a database read can't recover a working key. Send it as a bearer token. Rotate whenever you like: issue a new key, move your integration across, then revoke the old one. The account a key belongs to is resolved from the key itself, never from a URL or body parameter, so a key can only ever read or change its own account's data.
Authorization: Bearer stf_sk_xxxxxxxxxxxxxxxxxxxxxxxxScopes
Every key is minted with an explicit set of scopes. A call without the right scope is refused with a 403 before it reaches your data.
keys:readList a script's keys and look keys up by prefix, note or linked player.
keys:writeIssue new license keys and revoke existing ones.
hwid:writeReset a key's device (HWID) binding so it can bind to a new machine.
users:readRead reported player records tied to your scripts.
stats:readRead per-script rollups: executions, unique players and active keys.
discord:manageRedeem on a player's behalf and manage the Discord integration.
webhooks:manageManage webhook subscriptions for your account.
Endpoints
The same actions you take in the dashboard, exposed as plain REST. Each endpoint checks a single scope.
/api/v1/scripts/{id}/keysIssue one or more license keys for a script.
keys:write/api/v1/scripts/{id}/keysList a script's keys, filtered by query or status.
keys:read/api/v1/scripts/{id}/keys/{keyId}/revokeRevoke a single key.
keys:write/api/v1/scripts/{id}/keys/{keyId}/hwid/resetClear a key's device binding.
hwid:write/api/v1/scripts/{id}/statsPer-script executions, players and active keys for a range.
stats:read/api/v1/scripts/lookupResolve a public script by name.
keys:read/api/v1/redeemValidate a key and link it to a player's Discord id.
discord:manage/api/v1/usersRead reported player records.
users:readExamples
curl -X POST https://use.vodka/api/v1/scripts/$SCRIPT_ID/keys \
-H "Authorization: Bearer $VODKA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "count": 1, "expiresInDays": 30, "note": "launch batch" }'curl https://use.vodka/api/v1/scripts/$SCRIPT_ID/stats?range=7d \
-H "Authorization: Bearer $VODKA_API_KEY"Limits & responses
Each key gets its own budget: up to 600 requests a minute. Go over and you get a 429 with the time the window resets, not a silent drop.
Every response uses the same envelope, and errors carry a stable code (unauthorized, forbidden, rate_limited, not_found or bad_request) next to a human-readable message.
The plaintext key is shown once at creation. Only its HMAC-SHA256 hash is stored, so even a database read can't recover a working key.
The tenant is taken from the key, never from a parameter, so a scoped key can only ever touch its own account.
Start building
Developer API keys live in Settings → Developer API. Create as many as you need (name each key, pick its scopes, copy it once), and you're issuing licenses from your own code.