API keys

A workspace holds credentials pointing in two directions: keys you issue for your own servers to call Rostack with, and the Roblox key Rostack calls out with. Both live on the API keys page, which is why that page cannot be switched off.

Two directions

Confusing these is the expensive mistake, so Rostack keeps them visibly apart. Both appear on the same page precisely so that the difference is stated once rather than discovered later.

InboundOutbound
What it isA Rostack key, starting rsk_live_A Roblox Open Cloud key
Who issues itRostack, on the API keys pageYou, in Roblox's Creator Dashboard
Who holds itYour game servers, bots and automationsRostack, encrypted
What it doesLets your service call RostackLets Rostack write ranks to your group
How manyAs many as you like, one per serviceOne per workspace

Issuing a key

  • 1

    Open API keys

    In your workspace sidebar. The section is always present: it cannot be removed, because issued keys keep working whether or not the page is on, and removing the page would take away the only way to revoke one.
  • 2

    Name it after the thing that will hold it

    Main game server or Discord bot, not key 2. When you need to revoke one in a hurry, the name is what tells you which service you are about to break.
  • 3

    Set the rank ceiling

    The highest rank this key may assign, minus one. Keep it as low as the job allows.
  • 4

    Copy it now

    Only a SHA-256 hash is stored, so the plaintext is shown exactly once and is unrecoverable afterwards. A database leak yields nothing callable.
  • Using a key

    Send it as a bearer token. One key authenticates every endpoint, so a service that reports activity and also changes ranks needs one key, not two.

    any endpoint

    # The same key authenticates every endpoint.
    curl -X POST https://rostack.app/api/v1/rank \
      -H "Authorization: Bearer rsk_live_..." \
      -H "Content-Type: application/json" \
      -d '{"robloxUserId": 1234567, "rank": 50, "reason": "Reached 100 points"}'
    EndpointMethodWhat it does
    /api/v1/rankPOSTChange one member's rank
    /api/v1/activityPOSTReport play sessions from a game server
    /api/v1/eventsPOSTForward chat and admin commands to Discord
    /api/v1/moderationGETPoll the ban list your servers enforce

    The gate

    Every request authenticated by an API key passes through one piece of code. The header is parsed one way, the key is resolved through one cache, and every failure returns one indistinguishable answer. An endpoint does not get to authenticate slightly differently, because the gate is how a handler receives its key at all.

    That last point is the security argument rather than a tidiness one. Every authentication failure answers identically, whether the key never existed, was revoked an hour ago, or was mistyped:

    401, for every failure

    {
      "error": "unauthorized",
      "message": "Invalid or revoked API key."
    }

    Distinguishing them would let somebody probe which keys once existed. Rejections are cached briefly too, so timing does not give away what the message withholds.

    Resolved keys are cached for five minutes

    Authentication costs a lookup by hash plus a workspace read. The activity endpoint alone is called by every game server on a timer forever, so paying that on every request would dominate the bill. A revoked key can therefore keep working for up to five minutes on an instance that has already seen it. Revocations of a key you believe is compromised should be followed by rotating whatever it protected.

    The rank ceiling

    Every key carries a maximum rank and can never assign at or above it, however it is used. A key is a machine actor with no human behind it, so it gets an explicit limit rather than inheriting whatever its creator could do. A game-server key lives somewhere a game server can read it, which is to say somewhere that leaks, and a leaked key must not be able to create an administrator.

    The ceiling is also capped at the rank of the person issuing it. Without that, a low-ranked seat holding ranking.run could mint a key at 254, call the API with it, and promote themselves past the rank ceiling every other check depends on. A key is never a ladder out of your own rank.

    Ranks that a Rostack role is mapped to are refused outright to a key, with role_overreach. Moving somebody into such a rank hands them Rostack permissions, and a key holds a rank ceiling and no permissions of its own, so there is nothing to check it against. Those moves are made by a person, from the dashboard, under their name.

    Revoking

    Revoke on the API keys page. Because every endpoint authenticates through the same gate, revoking stops the key everywhere at once rather than on the endpoint you were thinking about.

    Revoked, not deleted

    A revoked key is kept so the audit log can still resolve which key made a past change. A record that points at a deleted key is not a record.

    The Open Cloud key

    The other direction. This is the key Roblox issues to you, that Rostack uses to write ranks on your behalf. Reading your group is public; writing a rank is not.

    Rostack encrypts it with Cloud KMS and stores only the ciphertext. It is never sent anywhere but Roblox, never shown back to you, and never written to a log. Connecting one is an owner-level act rather than a staff one.

    Ranking never needs your account cookie

    Nothing here, and nothing in ranking, asks for a .ROBLOSECURITY cookie. A cookie is your whole account; an Open Cloud key is a scoped credential you create, can restrict to one group and two permissions, and can revoke from Roblox's own dashboard without touching your account. The one exception is payouts: Roblox offers no other way to move Robux, so that screen asks for a cookie, encrypts it so this website can never read it back, and says so before you connect one.