Authentication
How to authenticate with the Wallet Service API using JWT tokens, API keys, and mTLS.
Overview
wallet-svc uses three authentication mechanisms depending on the endpoint group:
| Endpoint Group | Auth Mechanism | Details |
|---|---|---|
| Most endpoints | JWT Bearer Token (HS256) | Authorization: Bearer <token> + x-tenant-id header |
Jobs (/jobs/scheduled/*) | Internal API Key | x-internal-api-key header |
Health (/_internal/*) | None | No authentication required |
Obtaining a JWT Token
Login via auth-svcbash
curl -X POST https://535ubezkse.execute-api.us-east-1.amazonaws.com/auth/v1/login \
-H "Content-Type: application/json" \
-H "x-tenant-id: 00000000-0000-4000-a000-000000000001" \
-d '{
"email": "admin@eventzr.com",
"password": "Password123!"
}'
# Response:
# {
# "data": {
# "accessToken": "eyJhbGciOiJIUzI1NiIs...",
# "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
# "expiresIn": 86400
# }
# }Use the token with wallet-svcbash
export TOKEN="<access-token-from-response>"
curl -X GET https://535ubezkse.execute-api.us-east-1.amazonaws.com/wallet/v1/wallets \
-H "Authorization: Bearer $TOKEN" \
-H "x-tenant-id: 00000000-0000-4000-a000-000000000001" \
-H "Content-Type: application/json"Refresh an expired tokenbash
curl -X POST https://535ubezkse.execute-api.us-east-1.amazonaws.com/auth/v1/refresh \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "eyJhbGciOiJIUzI1NiIs..." }'Test Credentials
Staging Environment Credentials
Use these credentials to test the API in the Scalar playground above.
| Role | Password | Tenant ID | |
|---|---|---|---|
| Super Admin | admin@eventzr.com | Password123! | 00000000-0000-4000-a000-000000000001 |
| Developer | dev@eventzr.com | Password123! | 00000000-0000-4000-a000-000000000001 |
| Organizer | organizer@eventzr.com | Password123! | 00000000-0000-4000-a000-000000000001 |
| User | user@eventzr.com | Password123! | 00000000-0000-4000-a000-000000000001 |
JWT Claims Structure
Decoded JWT payloadjson
{
"sub": "00000000-0000-4000-a000-000000000002",
"email": "admin@eventzr.com",
"tenant": "00000000-0000-4000-a000-000000000001",
"tenantId": "00000000-0000-4000-a000-000000000001",
"roles": ["admin", "organizer", "user"],
"scopes": ["read", "write", "admin"],
"jti": "unique-token-id",
"iss": "eventzr.com",
"aud": "eventzr-api",
"iat": 1771697147,
"exp": 1771783547
}Important
The JWT payload must include both tenant and tenantId fields with the same tenant UUID value. Missing either field will cause 401 errors.
Standard Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer JWT token |
x-tenant-id | Yes | Tenant UUID (must match JWT tenant claim) |
Content-Type | POST/PUT/PATCH | application/json |
x-request-id | No | Request trace ID (UUID), auto-generated if absent |
Idempotency-Key | No | Idempotency key for write operations (24h TTL, Redis) |
x-internal-api-key | Jobs only | Internal API key for scheduled job endpoints |
Response Envelope
Standard success response formatjson
{
"data": { ... },
"error": null,
"meta": {
"requestId": "req_1708425600_a1b2c3d",
"traceId": "abc123-def456",
"timestamp": "2026-02-21T10:00:00.000Z"
}
}Standard error response formatjson
{
"data": null,
"error": {
"code": "ERR_WALLET_NOT_FOUND",
"message": "Wallet not found",
"details": null,
"traceId": "abc123-def456"
},
"meta": {
"requestId": "req_1708425600_a1b2c3d",
"traceId": "abc123-def456",
"timestamp": "2026-02-21T10:00:00.000Z"
}
}