Tokenization API
The Tokenization API provides endpoints for encrypting PII values into reversible tokens, managing tokenization policies, and controlling detokenization access through time-limited grants.
Base URL: https://api.slim.io/api/v1/tokens
Authentication
- Tokenize endpoint: Requires
X-API-Keyheader (API key authentication). - All other endpoints: Require
Authorization: Bearer <jwt>header (JWT authentication). - Health check: No authentication required.
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /tokenize | API Key | Tokenize one or more PII values |
POST | /grant | JWT | Request a detokenization grant |
POST | /detokenize | JWT | Detokenize tokens using a grant |
GET | /vault | JWT | List token vault entries (paginated) |
DELETE | /vault/:token_id | JWT | Revoke a token |
GET | /policies | JWT | List tokenization policies |
POST | /policies | JWT | Create a policy |
PUT | /policies/:id | JWT | Update a policy |
GET | /usage | JWT | Usage summary for billing |
GET | /health | None | Readiness check |
POST /tokenize
Tokenize one or more PII values according to a policy.
Request
{
"items": [
{"value": "123-45-6789", "pii_type": "us_ssn", "mode": "format_preserving"},
{"value": "john@example.com", "pii_type": "email"}
],
"policy_id": "pol_abc123",
"idempotency_key": "idk_xyz789",
"batch_mode": "BEST_EFFORT"
}| Field | Type | Required | Description |
|---|---|---|---|
items | array | Yes | PII values to tokenize (max 1,000 per request) |
items[].value | string | Yes | The raw PII value |
items[].pii_type | string | Yes | PII type (us_ssn, email, phone, ca_sin, date, passport_us, etc.) |
items[].mode | string | No | Override mode (deterministic, randomized, format_preserving). If omitted, uses policy default. |
policy_id | string | Yes | Which policy to apply |
idempotency_key | string | No | Client-provided key for deduplication (max 256 chars) |
batch_mode | string | No | BEST_EFFORT (default) or ALL_OR_NOTHING |
Add ?dry_run=true to preview results without writing to the vault.
Response (200)
{
"results": [
{"token": "541-89-6743", "token_id": "abc...", "status": "TOKENIZED", "mode": "format_preserving"},
{"token": "slim_AQAB...", "token_id": "def...", "status": "TOKENIZED", "mode": "deterministic"}
],
"success_count": 2,
"failure_count": 0,
"batch_policy_version": 3,
"trace_id": "uuid"
}POST /grant
Request a time-limited detokenization grant.
Request
{
"token_ids": ["tok_abc123", "tok_def456"],
"purpose": "customer_support",
"reason": "Case #12345 — customer identity verification"
}| Field | Type | Required | Description |
|---|---|---|---|
token_ids | array | Yes | Token IDs to grant access to (max 100) |
purpose | string | Yes | Must be in the policy’s allowed_purposes list |
reason | string | Depends | Required if the policy has require_reason: true |
Response (200)
{
"grant_jwt": "eyJ...",
"expires_in_seconds": 300,
"trace_id": "uuid"
}Grants are single-use and expire after 5 minutes. The grant JWT is bound to the requesting user, tenant, and specific token IDs.
POST /detokenize
Decrypt tokens using a valid grant.
Request
{
"tokens": ["tok_abc123", "tok_def456"],
"grant_jwt": "eyJ..."
}Response (200)
{
"results": [
{"token_id": "tok_abc123", "status": "GRANTED", "value": "123-45-6789"},
{"token_id": "tok_def456", "status": "REVOKED", "value": null, "revoked_at": "2026-07-10T..."}
],
"success_count": 1,
"failure_count": 1,
"trace_id": "uuid"
}Token status codes:
| Status | Description |
|---|---|
GRANTED | Authorized and decrypted |
NOT_FOUND | Token ID does not exist |
REVOKED | Token was explicitly revoked |
EXPIRED | Token TTL exceeded |
DENIED | Policy denied (role, purpose, rate limit) |
GET /vault
List token vault entries with cursor-based pagination.
GET /api/v1/tokens/vault?limit=50&pii_type=us_ssn&status=active| Param | Type | Description |
|---|---|---|
limit | int | Max results per page (1-100, default 50) |
cursor | string | Pagination cursor from previous response |
pii_type | string | Filter by PII type |
status | string | Filter: active, revoked, expired |
DELETE /vault/:token_id
Revoke (soft-delete) a token. The token cannot be detokenized after revocation.
{
"reason": "GDPR Article 17 request — ticket PRIV-1234"
}Error Codes
All error responses follow a consistent format:
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded",
"detail": "Per-user limit of 10/minute reached",
"retryable": true,
"retry_after_seconds": 5
}
}| Code | HTTP | Retryable | Description |
|---|---|---|---|
INVALID_INPUT | 400 | No | Request body is malformed |
EMPTY_VALUE | 400 | No | Value cannot be empty |
UNSUPPORTED_PII_TYPE | 400 | No | PII type is not supported |
RATE_LIMIT_EXCEEDED | 429 | Yes | Rate limit exceeded (check Retry-After header) |
QUOTA_EXCEEDED | 429 | No | Quota exceeded |
UNAUTHORIZED | 401 | No | Authentication required |
GRANT_EXPIRED | 403 | No | Grant has expired |
GRANT_NONCE_REUSED | 403 | No | Grant has already been used |
TOKEN_NOT_FOUND | 404 | No | Token not found |
TOKEN_REVOKED | 403 | No | Token has been revoked |
KILL_SWITCH_ACTIVE | 503 | No | Service temporarily disabled |
SERVICE_UNAVAILABLE | 503 | Yes | Transient service failure |
Rate Limits
| Endpoint | Per-User/min | Per-Tenant/min |
|---|---|---|
| Tokenize | 1,000 | 10,000 |
| Detokenize | 10 | 100 |
| Grant | 10 | 100 |
| Vault list | 60 | 600 |
| Revoke | 10 | 100 |
Rate limit headers are included on every response:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 995
X-RateLimit-Reset: 1720000000
Retry-After: 5 (on 429 only)SDK Version Header
SDKs must send X-Slim-SDK-Version with every request. The backend rejects requests from unsupported major versions with 426 Upgrade Required.
X-Slim-SDK-Version: 1.0.0