API credentials

Personal tokens vs machine keys, scopes, number restrictions, step-up and what revokes a credential.

The SUZKO API takes exactly one kind of authentication: a bearer credential in the Authorization header.

Shell
curl https://www.suzko.com/api/v1/numbers \
  -H "Authorization: Bearer szk_mk_YOUR_MACHINE_KEY"

Cookies, app sign-ins and anything else are ignored. A bad credential is 401 unauthorized even if you're signed in to the dashboard in the same browser.

Credentials are managed in the developer console at /dashboard/developers. The Profile → Developers tab shows a summary (what's expiring, what's due for rotation) and links there. The console always works on the account you're currently in.

Two kinds of credential

Personal tokenMachine key
Looks likeszk_pat_ + 43 letters and digitsszk_mk_ + 43 letters and digits
Belongs toYou, on one accountA service account: the account's machine identity
Who can create oneThe owner, or a team member with the permissions its scopes needThe account owner only
ExpiresAlways. 30 days by default, 90 at mostNever. Due for rotation after 90 days
Survives you leaving the accountNoYes
Use it forYour own scripts, one-off jobs, trying the APIServers, integrations, webhooks

Use a machine key for anything that runs unattended. A personal token stops working when it expires, when you change your password, or when your access to the account changes, and every webhook endpoint it created pauses with it. A machine key keeps working through all of that.

Every credential is shown once, when you create it. SUZKO stores only a SHA-256 hash of it plus its first 12 characters (the prefix you see in the console, e.g. szk_mk_4Fq9z). Lost it? Revoke it and make a new one. Keep credentials on your server: never in a mobile app, a browser, or a repository.

Personal tokens

  • Pick an expiry when you create it. The API accepts 1–90 days and defaults to 30; the console offers 7, 30, 60 or 90.
  • SUZKO emails you and the account owner 14 days and 3 days before it expires.
  • Each scope must be within your current permissions on the account, and that's re-checked on every request. If the owner takes a permission away from you, requests that need it fail at once with 403 scope_not_permitted. The owner is checked the same way: owning the account doesn't widen a token past its scopes.
  • The owner sees every personal token on the account (with who made it) and can revoke any of them. A team member sees only their own.

Service accounts and machine keys

A service account holds the scopes and number restrictions; its keys are the secrets you deploy.

  • At most 2 live keys per service account: keys that aren't revoked or expired. An expired key stops working and frees its slot. A third live key is 409 key_limit.
  • Keys don't expire. Each one is due for rotation 90 days after it's created: the console flags it, and it keeps working.
  • To rotate without downtime: create the second key, deploy it, then revoke the old one.
  • A service account can be suspended (its keys stop working until the owner re-enables it) or disabled (permanent: its keys are revoked).
  • Only the account owner can see or manage service accounts.

Scopes

Give each credential only what it uses. There is no "full access" scope.

ScopeAllowsPermission a personal token's holder needsNeeds a SUZKO Phone plan
messages:sendPOST /messages, POST /messages/batchMake calls + send SMS (voip.use)Yes
messages:readGET /messages, GET /messages/{id}View phone system (voip.view)Yes
numbers:readGET /numbersView phone system (voip.view)Yes
usage:readGET /usageView phone system (voip.view)Yes
webhooks:manageEverything under /webhooksBuy + configure numbers (voip.numbers)Only to create an endpoint
  • A credential without the scope a request needs gets 403 forbidden_scope.
  • A personal token whose holder lost the permission gets 403 scope_not_permitted.
  • Scopes that need a plan answer 403 plan_required on every request, reads included, while the account has no active SUZKO Phone plan.
  • Webhook endpoints only receive message and opt-out events when their creator's credential also has messages:read. See Webhooks.

Restricting a credential to some numbers

Each credential covers either all numbers on the account or an explicit list of up to 100 numbers, picked by their pn_… id. With a list:

  • it can only send from those numbers (from, and the default sender);
  • GET /messages, GET /messages/{id} and GET /numbers only show those numbers and their messages;
  • its webhook endpoints only get message events for those numbers. Opt-out events are account-wide and still arrive.

Anything outside the list behaves as if it didn't exist: a from outside it is 422 invalid_request ("That number isn't on your account"), and a message outside it is 404 not_found. GET /usage is account-wide either way.

Confirming it's you (step-up)

Creating, revoking or changing anything in the developer console (tokens, service accounts, keys, webhooks) needs a fresh confirmation:

  • Two-factor authentication must be on. Without it you get 403 mfa_enrollment_required. The console offers to set it up right there; confirming your new authenticator's code also counts as the confirmation, so you carry straight on.
  • The console asks for a 6-digit code from your authenticator app. Backup codes and your password are not accepted here.
  • One confirmation covers 5 minutes of changes. After that the console asks again (401 step_up_required).
  • Code attempts are limited (5 per 15 minutes per person, 20 per 15 minutes per address).
  • Staff signed in as you from SUZKO support can't pass step-up.

The console's own endpoints only accept a signed-in browser session, never a bearer credential: an API credential can't create, list or revoke credentials.

What revokes or suspends credentials

EventPersonal tokensMachine keys
You change your passwordAll of yours, on every account, revokedUnchanged
You change your email (or SUZKO support does)All of yours revokedUnchanged
You turn off two-factor authenticationAll of yours revokedUnchanged
You reset your password through account recoveryAll of yours revokedThe service accounts on your own account suspended
The owner removes you from their accountYours on that account revoked—
The owner changes your permissionsNot revoked; scopes you no longer qualify for fail with 403 scope_not_permitted—
SUZKO closes an accountThat person's tokens revoked on every account; any other token used on the closed account gets 403 account_suspendedThe closed account's service accounts suspended
You revoke it, or it expiresThat token stops at onceThat key stops at once

A revoked, expired or suspended credential gets the same 401 unauthorized as an unknown one. Texts it already queued still go out. A suspended service account comes back when the owner re-enables it in the console (with step-up).

Webhook endpoints follow their creator: when a credential loses its authority, the endpoints it created pause. See pause rules.

Next

Want a complete example client and webhook receiver? Ask SUZKO support; examples are available on request.