Authentication

How to authenticate with the Subscriptions Service API using JWT tokens and internal API keys.

Overview

The Subscriptions Service uses a two-tier auth model:

  • JWT Bearer tokens for all user-facing endpoints (subscriptions, plans, trials, invoices, etc.)
  • Internal API key for jobs/scheduler endpoints (via x-internal-api-key header)

The tenantId is extracted from the JWT claims automatically via the @CurrentTenant() decorator. You never need to pass it as a URL parameter.

Obtaining a JWT Token

Login via auth-svcbash
curl -X POST https://535ubezkse.execute-api.us-east-1.amazonaws.com/auth/v1/login/email \
  -H "Content-Type: application/json" \
  -H "x-tenant-id: 00000000-0000-0000-0000-000000000001" \
  -d '{
    "email": "organizer@eventzr.com",
    "password": "Password123!"
  }'

# Response:
# {
#   "data": {
#     "accessToken": "eyJhbGciOiJIUzI1NiIs...",
#     "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
#     "expiresIn": 3600
#   }
# }
Use the token with subscriptions-svcbash
export TOKEN="<access-token-from-response>"

curl -X GET https://535ubezkse.execute-api.us-east-1.amazonaws.com/subscriptions/v1/subscriptions \
  -H "Authorization: Bearer $TOKEN" \
  -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": "eyJhbGciOiJSUzI1NiIs..." }'

Test Credentials

Staging Environment Credentials

Use these credentials to test the API in the Scalar playground above.

RoleEmailPasswordTenant ID
Organizerorganizer@eventzr.comPassword123!00000000-0000-0000-0000-000000000001
Useruser@eventzr.comPassword123!00000000-0000-0000-0000-000000000001
Developer (MFA required)dev@eventzr.comPassword123!00000000-0000-0000-0000-000000000001

Internal API Key (Jobs Endpoints)

Fail-Closed Security

Jobs endpoints use an internal API key instead of JWT. The guard is fail-closed: if INTERNAL_API_KEY is not configured, all requests are rejected with 401.

Call a jobs endpointbash
# Jobs endpoints bypass JWT — use x-internal-api-key header instead
curl -X POST https://535ubezkse.execute-api.us-east-1.amazonaws.com/subscriptions/v1/jobs/process-renewals \
  -H "x-internal-api-key: <INTERNAL_API_KEY>" \
  -H "Content-Type: application/json"

JWT Claims Structure

Decoded JWT payloadjson
{
  "sub": "user-uuid",
  "tenantId": "tenant-uuid",
  "email": "user@example.com",
  "roles": ["user", "organizer", "admin"],
  "planTier": "professional",
  "iat": 1740000000,
  "exp": 1740003600
}

Standard Headers

HeaderRequiredDescription
AuthorizationYes (user endpoints)Bearer JWT token
x-internal-api-keyYes (jobs endpoints)Internal API key for scheduler/cron endpoints
Content-TypePOST/PUT/PATCHapplication/json
x-request-idNoRequest trace ID (UUID), auto-generated if absent
x-tenant-idRecommendedTenant UUID for explicit tenant filtering
Idempotency-KeyNoIdempotency key for write operations (24h TTL)

Role-Based Access Control

Endpoints are protected by @Roles() decorator. Common roles:

RoleAccess
userView own subscriptions, plans, trials, invoices
organizerCreate/manage subscriptions, upgrade/downgrade, view analytics
adminFull access including plan management, bulk operations, discount codes

Response Envelope

Standard response formatjson
{
  "data": { ... },
  "error": null,
  "page": {
    "next_cursor": "eyJwYWdlIjoyLCJsaW1pdCI6MjB9",
    "has_more": true,
    "limit": 20
  },
  "meta": {
    "request_id": "550e8400-e29b-41d4-a716-446655440000",
    "trace_id": "abc123",
    "tenant_id": "tenant-uuid"
  }
}