Docs · Integrations

Personal API tokens

A personal access token lets a script, a CI job or an AI assistant call the API as you, without an interactive login and without embedding your password anywhere. It carries exactly your permissions — global role, project memberships, restricted-ticket visibility — and is re-checked against your live account on every request, so deactivating the account or revoking the token cuts access immediately. Treat a token like a password.

Create a token

Open Account → API tokens (/account), give the token a name that says what it is for ("Release bot", "Claude Desktop"), pick an expiry — never, 30 days, 90 days or a year — and press Create token. The raw value is shown once, with a copy button; after you dismiss the panel only its first 12 characters (isk_ plus eight more) remain visible as an identifier. The same flow exists over the API:

Omit expiresInDays for a token that never expires; zero or negative values are rejected
curl -s -X POST http://localhost:8088/api/v1/account/tokens \
  -H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
  -d '{"name":"Release bot","expiresInDays":90}'
# → {"token":{"id":"…","name":"Release bot","prefix":"isk_3kQ9xYz1","createdAt":"…","expiresAt":"…","lastUsedAt":null,"revokedAt":null},
#    "rawToken":"isk_3kQ9xYz1…"}   ← shown once; store it in your secret manager now
EndpointPurpose
GET /api/v1/account/tokensYour tokens, newest first — name, visible prefix, created/expires/last-used/revoked timestamps. Never the secret. Revoked tokens stay listed.
POST /api/v1/account/tokensCreate (201): name (required, ≤ 100 characters), optional expiresInDays and optional scope (READ, WRITE — the default — or FULL). Returns the token row plus rawToken.
DELETE /api/v1/account/tokens/{id}Revoke (204). Only your own tokens; revoking twice is harmless.

Use it

Send the token on the very same header a session JWT uses. The backend tells the two apart by prefix — every personal token starts with isk_ — so nothing else changes: the same endpoints, the same permission checks, the same 401/403 semantics.

A token works everywhere a JWT works — including /api/v1/account/tokens itself
export ISKUE_TOKEN='isk_…'

# Search tickets with TQL
curl -s "http://localhost:8088/api/v1/search/tql?query=assignee%20%3D%20me%20AND%20status%20!%3D%20Done" \
  -H "Authorization: Bearer $ISKUE_TOKEN"

# Add a comment from a CI job
curl -s -X POST http://localhost:8088/api/v1/tickets/CORE-42/comments \
  -H "Authorization: Bearer $ISKUE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"body":"Build 1234 passed on main"}'
  • Format — isk_ followed by 43 URL-safe base64 characters (32 random bytes): 47 characters in total. Only a SHA-256 hash is stored; the raw value cannot be recovered, so a lost token is replaced, not retrieved.
  • Lifetime — a token works until it expires (expiresAt) or is revoked; each successful use stamps lastUsedAt, which the Account page shows so stale tokens are easy to spot.
  • Access level — pick Read only, Read & write (the default) or Full access (administration, the Jira importer, tokens, 2FA, connected accounts) when you create a token; a request beyond the token's level gets a 403 that says so. Within that level a token is you — never more than your own permissions.
  • Who may create them — any active user, in every edition. No limit on the number of tokens per account.
  • Where they are not useful — on the paths that are open without a login anyway (customer portal, inbound webhooks), and on the SSE stream and attachment thumbnails, where the browser cannot set headers and the app uses a short-lived access_token query parameter instead.

Revoke and rotate

Press Revoke next to a token (the UI confirms: *Anything using it will stop working immediately*) or call DELETE /api/v1/account/tokens/{id}. Revocation is a soft delete — the row stays in the list marked Revoked so you keep a record of what existed. To rotate, create the replacement first, update the consumer, then revoke the old one.

Rate limits apply per authenticated user, not per token (app.ratelimit.api-per-min, default 240 requests per minute per backend node). A chatty automation sharing your account competes with your own browser session; give heavy integrations their own account.

Token creation and revocation are self-service and are not written to the audit log in this release; administrators cannot list other users' tokens. Deactivating a user (Administration → Users) is the administrative kill switch: it invalidates every token the user holds on the next request.