Requests, errors and limits

A few rules apply to every request. Follow them and your program will behave well, even when something goes wrong.

Signing every request

Send your key in the Authorization header as a bearer token. Send JSON with Content-Type: application/json.

Headers
Authorization: Bearer tfy_your_key_here
Content-Type: application/json

Ids

:guildId can be your Discord server id or Technified’s own id (it starts with gld_). Discord and Roblox accounts are always plain numbers, sent as strings. Everything Technified makes has an id with a short prefix that says what it is: pun_ for a punishment, tkt_ for a ticket, sub_ for a submission.

The easiest is the Discord server id: in Discord, switch on Developer Mode (User Settings → Advanced), then right-click your server and choose Copy Server ID.

Careful

Use either id exactly as it is. Do not put gld_ in front of the Discord server id: gld_123456789012345678 names no server, and every request answers 404.

Errors

A refusal comes back with an HTTP status and a JSON body with a stable code. Check the code, never the wording, which may change.

A refusal
{
  "type": "https://docs.technified.dev/errors/missing_permission",
  "title": "Missing permission",
  "status": 403,
  "code": "missing_permission",
  "detail": "This needs the moderation.write permission."
}
StatusWhat it means
400Something about the request is wrong, for example a missing header. The detail says what.
401No key, or a key that is wrong, expired or revoked.
403The key may not do this (missing_permission), the endpoint is for people only, or the server is blocked.
404It does not exist, or this key cannot see it.
409It cannot happen right now, for example already decided or already lifted. The code says why.
412Somebody changed it since you read it (stale_write). Read it again.
422A field is wrong. errors lists every field and what was wrong with it.
429Too many requests. Wait retryAfter seconds.

Retrying safely

Networks fail. To retry a write without doing it twice, send an Idempotency-Key header with a random value, and the same value on every retry of that one action. Technified answers the retry with the first answer instead of, say, banning somebody twice.

Header
Idempotency-Key: 3f1c9a52-8b0e-4d1f-9a77-2c5e6d8b1f40

Lists and pages

Lists come a page at a time. Ask with limit (and often order=desc); the answer has items and a nextCursor. To get the next page, send that value as cursor. When nextCursor is null, you have everything.

Response
{
  "items": [ ... ],
  "nextCursor": "pun_01J9Z4T7C2Q8M3N5V6W7X8Y9Z0"
}

Rate limits

Each key has its own budget per minute. Every answer tells you where you stand:

Response headers
x-ratelimit-limit: 300
x-ratelimit-remaining: 287
x-ratelimit-reset: 1791651660
Kind of requestPer minute
Reading300
Changing something60
Ban check (moderation/status)1200
Sending to every game server at once5

Over the limit you get 429 with retryAfter in seconds. Wait that long, then try again.

Changing settings

Settings carry a version so two people cannot overwrite each other. Read the server with GET /guilds/:guildId, and send the settingsVersion you got back as an If-Match header on PATCH /guilds/:guildId/settings. If somebody changed them in between, you get 412; read them again and try once more.

Still stuck? Get help from the Technified team.