Smoke-test a new Sume API key with GET /v1/me before revoking the old

GET /v1/me returns the key's id, prefix and scopes. A TypeScript script fails the deploy if the new key lacks formats:write, so you revoke the old key after.

5 min readSume
All posts

Call GET /v1/me with the new key before you revoke the old one. It verifies the key and returns non-secret metadata: the key id, name, prefix and scopes, plus the workspace and the auth source. If scopes lacks what your job needs, you find out in the deploy, not in production.

Sume's rotation order is documented on the Authentication page: create a replacement key, deploy it to your server, verify GET /v1/me, then revoke the old key. This post adds the check that makes the third step automatic.

What does GET /v1/me return?

The OpenAPI schema describes it as verifying the provided developer API key and returning non-secret account and key metadata. The response is data.account, which carries the fields below. The full secret is never returned.

GET /v1/me response fields, read 2026-10-02
FieldMeaning
data.account.api_key.idThe key id
data.account.api_key.nameThe label you gave it, or null
data.account.api_key.prefixVisible prefix, safe to log
data.account.api_key.scopesArray of scopes, such as formats:read
data.account.auth_sourceledger, env, dashboard or mcp_oauth
data.account.workspace_id / owner_user_idResolved from the key; redact from logs

Why check scopes and not only a 200?

A 200 proves the key is valid. It does not prove the key can do your job. Scopes are fixed when a key is created and cannot be added later, so a key created before a scope existed does not carry it. For Formats, a key without the formats:read or formats:write scope it needs returns 403 insufficient_scope, never a 404.

The errors page also warns that retrying a 403 insufficient_scope in a loop is the most common and most expensive mistake. A /v1/me check at deploy time catches the missing scope once, cheaply.

What does the script look like?

This Node script (save it as an .mjs file so top-level await works) reads the key from the environment, sends it in one header only, exits non-zero on a bad status or a missing scope, and prints the prefix but never the key or the workspace id. Run it in the same environment that will serve traffic, after the new key is deployed there:

const REQUIRED = ["formats:read", "formats:write"];
const key = process.env.SUME_API_KEY ?? "";
if (!key) { console.error("SUME_API_KEY is empty"); process.exit(2); }

const res = await fetch("https://api.sume.com/v1/me", {
  headers: { "x-api-key": key }, // one credential header, never two
});
if (!res.ok) {
  const body = await res.json().catch(() => ({}));
  console.error(res.status, body?.error?.code, body?.error?.request_id);
  process.exit(1);
}

const { api_key } = (await res.json()).data.account;
const missing = REQUIRED.filter((s) => !api_key.scopes.includes(s));
console.log("prefix:", api_key.prefix, "scopes:", api_key.scopes.join(","));
if (missing.length) {
  console.error("missing scopes:", missing.join(","));
  process.exit(1);
}

When is it safe to revoke the old key?

After the check passes in the deployed environment and a real request has succeeded with the new key. Then revoke the old key in the API Keys dashboard. If the old key leaked, rotate immediately instead of waiting for the next release.

Two traps are worth knowing. A team Format needs a key created in that workspace, or the call fails 403 workspace_key_required, and /v1/me is where you see which workspace the key resolves to, so compare it to the Format owner before cutover. And the check cannot catch a gateway that adds an Authorization header on top of your x-api-key; the API rejects both together with 401 unauthorized, so run the script through the same network path as production.

Can I run it from the CLI instead?

Yes. sume me and sume account get both read account context for the configured key, and sume auth status reports local auth state. They are useful when you are rotating a key on a developer machine or a CI runner that already has the CLI installed. Set SUME_API_KEY to the new key in that shell and run sume account get --json.

The CLI's --agent flag redacts account and workspace details where supported, which is what you want when the output lands in a pipeline log. The raw HTTP call is better when you need an exit code tied to a specific scope, as in the script above.

Whichever you use, keep the old key live until the new one has served real traffic. Then revoke it. The authentication page says key metadata includes last-used time, so check that before you pull the old key.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume