Developer docs · Browse & search
OPERATE

Keys and security

API keys and roles, tokens that expire, and what keeps keys and secrets safe.

API keys

Make a key on the Developer page of the console, or in code when signed in as an owner or administrator:

ts
const { key, token } = await jwtson.keys.create({ name: 'CI', role: 'builder' }); // Store token now: it's shown once
for await (const each of jwtson.keys.list()) console.log(each.name, each.status, each.expiresAt);
await key.revoke(); // Stops it straight away, and runs it started stop at their next step

A key reaches this environment unless you pass reach: 'project' or 'organization', and lasts at most 90 days. With a key that reaches one environment, new Jwtson({ baseUrl, token }) is all you need.

RoleCan
viewerRead
operatorAlso start, answer and stop runs
builderAlso create and publish agents, workflows, schedules and triggers

A few things always take a person who's an owner or administrator: making keys, granting rights, approving a webhook destination and managing providers.

Key formats, tools and limits

Keys look like jwtson_sk_... and end in a checksum, so a secret scanner can find a leaked one. To add one to yours, match jwtson_sk_[A-Za-z0-9_-]{43}[0-9a-f]{6}.

ts
const { key, token } = await jwtson.keys.create({ name: 'Billing sync', requestsPerMinute: 600 });
for await (const key of jwtson.keys.list()) console.log(key.name, key.lastUsedAt);

A key starts agents and workflows like a person does, but one that uses a tool or skill needs it given to the key first:

ts
await key.allowTool('send_invoice');
await key.allowSkill('Weather');
await key.remove(toolOrSkillId); // Takes one back

It's one key and one tool or skill at a time, it lasts no longer than the key, and revoking the key ends it. A key that leaks can call what it was given until it's revoked, so give it only what it needs.

requestsPerMinute is the most a key can do if it leaks, until you revoke it. Going over gets a RateLimitError, and the client waits and retries for you where that's safe. There's no limit unless you set one. lastUsedAt is accurate to about a minute, so a key that's been idle for a long time is easy to spot and revoke.

Tokens

Pass a function if your token expires. It's asked for each request, and once more after a 401.

ts
new Jwtson({ token: () => myAuth.currentToken() });

Keeping keys safe

Use the SDK on your server. An API key in a web page or a mobile app can be read by anyone who has it.

  • In a web page: the client refuses a fixed token. Your server signs its user in and gives the page a client session instead, so the key stays on your server.
  • In transit: the address must be https, except on this machine. Redirects are refused, so a token or secret isn't sent somewhere else.
  • In logs: a logged client doesn't show its token. signingSecret and the token from keys.create are the two values to handle with care: each is given once.
  • The role: give each service its own key with the lowest role it needs. An operator key can't define anything.
  • If one leaks: revoke it. It stops straight away, and runs it started stop at their next step.

A key sees only runs it started, and only inside its reach.

From the @jwtson/sdk README, as the code stands.