Skip to main content

Endpoint

POST /v1/access-tokens
Issue a new access token with a specified ID, scope, and expiration. The response contains the actual token secret, which is only returned once and cannot be retrieved later.
This endpoint is not supported in s2-lite. Access token management is only available in S2 Cloud.
Store the returned access_token value securely. You won’t be able to retrieve it again.

Request Body

id
string
required
Access token ID. Must be unique to the account and between 1 and 96 bytes in length.
expires_at
string
Expiration time in RFC 3339 format (e.g., 2027-01-01T00:00:00Z). If not set, the expiration will be set to that of the requestor’s token.
auto_prefix_streams
boolean
default:false
Namespace streams based on the configured stream-level scope, which must be a prefix. Stream name arguments will be automatically prefixed, and the prefix will be stripped when listing streams.
scope
object
required
Access token scope defining permissions.

Response

access_token
string
required
The created access token. This is the only time the token secret will be returned.

Examples

curl -X POST "https://aws.s2.dev/v1/access-tokens" \
  -H "Authorization: Bearer $S2_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "app-backend-token",
    "expires_at": "2027-01-01T00:00:00Z",
    "scope": {
      "basins": {"prefix": ""},
      "streams": {"prefix": ""},
      "op_groups": {
        "stream": {
          "read": true,
          "write": true
        }
      }
    }
  }'
{
  "access_token": "s2_AcTo01h8mCt9Qn..." 
}

Common Use Cases

Read-only token for specific streams

Create a token that can only read from streams with a specific prefix:
{
  "id": "analytics-readonly",
  "expires_at": "2026-12-31T23:59:59Z",
  "scope": {
    "basins": {"exact": "production"},
    "streams": {"prefix": "logs/"},
    "op_groups": {
      "stream": {
        "read": true,
        "write": false
      }
    }
  }
}

User-scoped token with auto-prefixing

Create a token for a specific user where all stream operations are automatically prefixed:
{
  "id": "user-1234-token",
  "expires_at": "2027-01-01T00:00:00Z",
  "auto_prefix_streams": true,
  "scope": {
    "basins": {"prefix": ""},
    "streams": {"prefix": "users/1234/"},
    "op_groups": {
      "stream": {
        "read": true,
        "write": true
      }
    }
  }
}
With auto_prefix_streams: true, when using this token:
  • append("messages") → actually appends to "users/1234/messages"
  • list_streams() → returns "messages" instead of "users/1234/messages"

Token with specific operations

Create a token with fine-grained permissions using the ops array:
{
  "id": "metrics-collector",
  "scope": {
    "basins": {"prefix": ""},
    "ops": ["account-metrics", "basin-metrics", "stream-metrics"]
  }
}

Security Best Practices

Principle of Least Privilege

Grant only the minimum permissions needed for the token’s intended use.

Set Expiration

Always set an expires_at time appropriate for the token’s use case.

Scope Narrowly

Use specific basin/stream prefixes or exact matches rather than allowing all resources.

Rotate Regularly

Implement token rotation for long-lived tokens.

Build docs developers (and LLMs) love