Skip to content

feat: manage team API tokens - #49

Merged
bjarn merged 1 commit into
feat/project-api-tokensfrom
feat/team-api-tokens
Oct 30, 2026
Merged

bjarn merged 1 commit into
feat/project-api-tokensfrom
feat/team-api-tokens

Conversation

@bjarn

@bjarn bjarn commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

What changed

Adds team.apiTokens, a sub-resource for the team's API tokens, next to team.members and team.invites and in the same style (team token):

Method Request Returns
list(query?, options?) GET /team/api-tokens (page: { size, cursor }, sort) ListTeamApiTokensResponse (CursorPage<TeamApiToken>)
iterate(query?, options?) follows next_cursor AsyncGenerator<TeamApiToken>
create(body, options?) POST /team/api-tokens with StoreTeamApiTokenData TeamApiTokenCreatedResponse (201)
delete(tokenId, options?) DELETE /team/api-tokens/{tokenId} MessageResponse
  • create takes a name, the abilities (for example read:domains) and an optional expires_at (ISO 8601 or null). The new token can only have abilities that the requesting token has. It copies the requesting token's IP allowlist, and it can't outlive the requesting token: expires_at defaults to, and can't be later than, its expiry.
  • create returns the token value once, in data.token. The docblock and README say to store it right away; as with project tokens, the SDK does not redact generated response types.
  • list and iterate return token metadata only. delete stops the token from working immediately; a token can only delete tokens whose abilities it also has.
  • A 403 throws the existing PermissionError, a 422 the existing ValidationError. No new error classes.
  • Empty, . and .. token IDs are rejected before any request, as for the other methods.
  • None of these operations take an Idempotency-Key, so there is no idempotency option.
  • TeamApiTokens is exported as a type, like TeamInvites.
  • README: team.apiTokens is in the Team API table and the Team API example.
  • The coverage test no longer has a pending list: every operation in the generated table has an SDK method again.

Stacked on #48. Non-breaking. Suggested bump: minor.

Usage

const lettermint = new Lettermint({ teamToken: process.env.LETTERMINT_TEAM_TOKEN });

const created = await lettermint.team.apiTokens.create({
  name: 'Deploys',
  abilities: ['read:domains'],
  expires_at: '2027-01-01T00:00:00Z',
});
console.log(created.data.token); // only returned once

for await (const token of lettermint.team.apiTokens.iterate({ sort: ['name'] })) {
  console.log(token.name, token.abilities, token.expires_at);
}

await lettermint.team.apiTokens.delete(created.data.id);

Checks

On this branch:

  • npm run lint: passed
  • npm run type-check: passed
  • npm run generate:check: generated files up to date with the pinned spec; the header-only mode that CI runs also passes
  • npm run test:coverage: 8 suites, 365 tests passed
  • Jest on Node 20.20.2, 22.23.4 and 24.22.1: 365 passed each
  • npm run build: passed
  • npm run test:smoke: ESM import, CJS require and type declarations OK

Not run locally

Nothing; every CI step was run locally.

Suggested release tag

v3.3.0 (minor), together with #48 once both are merged.

Add `team.apiTokens` with `list`, `iterate`, `create` and `delete` for
the team's API tokens (team token). A new token can only have abilities
that the requesting token has, copies its IP allowlist and can't outlive
it. `create` returns the token value once.

The coverage test now checks every operation again.
@bjarn
bjarn requested a review from a team as a code owner October 29, 2026 16:59
@bjarn
bjarn added this pull request to stack #50 October 29, 2026 16:59
@bjarn
bjarn merged commit 3b60f8a into main Oct 30, 2026
4 checks passed
@bjarn
bjarn deleted the feat/team-api-tokens branch October 30, 2026 08:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants