For AI agents: markdown of this page — /docs-content-en/infra/access-tokens/refresh.md documentation index — /llms.txt

Refresh an access token

POST /v1/infra/servers/:id/access-tokens/:tokenId/refresh

Mints a fresh JWT for an existing api-bearer token — without creating a new record. The JWT is valid for up to 10 minutes (or until the record's expiresAt, whichever is sooner). A long-running client (CI, AI agent) should call refresh before jwtExpiresAt expires rather than minting a new token: refresh does not consume the active-token limit or the hourly mint limit.

No request body is required.

Parameters

Parameter In Type Required Description
id path string (UUID) yes BLACKHOLE server ID
tokenId path string (UUID) yes api-bearer token ID (the data.id field from the mint response)

Examples

curl

Terminal
curl -X POST "https://vibecode.bitrix24.com/v1/infra/servers/SERVER_ID/access-tokens/TOKEN_ID/refresh" \
  -H "X-Api-Key: YOUR_API_KEY"

JavaScript — "use → on 401 refresh → retry" loop

javascript
async function callWithRefresh(serverId, tokenId, appUrl, jwt) {
  let res = await fetch(`${appUrl}/api/health`, {
    headers: { Authorization: `Bearer ${jwt}` },
  })
  if (res.status === 401) {
    const r = await fetch(
      `https://vibecode.bitrix24.com/v1/infra/servers/${serverId}/access-tokens/${tokenId}/refresh`,
      { method: 'POST', headers: { 'X-Api-Key': 'YOUR_API_KEY' } },
    )
    const { data } = await r.json()
    jwt = data.token // same tokenId, fresh JWT
    res = await fetch(`${appUrl}/api/health`, {
      headers: { Authorization: `Bearer ${jwt}` },
    })
  }
  return res
}

Response fields

Field Type Description
success boolean Always true on success
data.id string Token ID — the same as at mint time (no new record is created)
data.mode string "api-bearer"
data.token string Fresh JWT for the Authorization: Bearer header
data.expiresAt string (ISO 8601) Retention period of the token record — unchanged by refresh
data.jwtExpiresAt string (ISO 8601) Real expiry of the new JWT. Capped at 10 minutes (or the record's expiresAt, whichever is sooner)
data.subdomain string Server subdomain
data.appUrl string Full HTTPS address of the app
data.curlExample string Ready-to-use curl example with the new token
data.note string Explanation of validity and re-calling

Response example

JSON
{
  "success": true,
  "data": {
    "id": "tk_7d3fa2b1",
    "mode": "api-bearer",
    "token": "eyJhbGciOiJFUzI1NiJ9...",
    "expiresAt": "2026-06-25T10:50:00.000Z",
    "jwtExpiresAt": "2026-06-25T10:40:10.000Z",
    "subdomain": "app-91306a4c",
    "appUrl": "https://app-91306a4c.vibecode.bitrix24.com",
    "curlExample": "curl -H \"Authorization: Bearer eyJhbGciOiJFUzI1NiJ9...\" https://app-91306a4c.vibecode.bitrix24.com/api/health",
    "note": "Refreshed the Gateway session JWT for this api-bearer token (same token id, no new row)."
  }
}

Errors

HTTP Code Description
400 WRONG_TOKEN_MODE The token is in share-url mode. Refresh applies only to api-bearer; share-url links auto-refresh on each visit
400 SERVER_NO_SUBDOMAIN The server has no subdomain
401 MISSING_API_KEY The X-Api-Key header was not provided
401 INVALID_API_KEY Invalid or expired API key
403 TOKEN_OWNER_MISMATCH The token belongs to a different key, or the server is no longer bound to your key
404 NOT_FOUND Token not found on this server
404 SERVER_NOT_FOUND Server not found or deleted
410 ALREADY_REVOKED The token was revoked — mint a new one
410 TOKEN_EXPIRED The record's retention period has expired — mint a new token via POST /access-tokens
503 FEATURE_DISABLED Access tokens are disabled on the platform

Full list of common API errors — Errors.

Diagnosing a Gateway rejection

If a request to the app with the Authorization: Bearer header returns 401 with code BH_LOGIN_REQUIRED, the response body carries a reason field with the specific Gateway rejection cause:

reason What happened What to do
expired The JWT expired (the 10-minute window elapsed) Refresh the token via this endpoint, or mint a new one
signature The signature did not verify Use a token minted for this server; do not edit it
subdomain The token is bound to a different subdomain Call the server's own app-* subdomain
revoked The token was revoked Mint a new token
type A non-api-bearer token was sent Use an api-bearer token, not a cookie session
malformed / invalid The string is not a valid JWT Check the token is intact

Known specifics

  • Refresh creates no new record. data.id stays the same; the token record and its expiresAt do not change — only the JWT is renewed. A single revoke (DELETE) kills the original and all refreshed JWTs of one token.
  • A JWT never outlives its record. If less than 10 minutes remain until the record's expiresAt, the new jwtExpiresAt is capped to that time.
  • api-bearer only. share-url links refresh automatically on each visit via /auth/bh-login.

See also