Download OpenAPI specification:
Subscriber Management System — billing and subscriber management endpoints for the EncoraStream OTT Platform.
Covers:
Permissions are assigned to roles via role_permissions (never directly to users).
Roles are assigned to users via user_role_assignments with optional expiry.
A user may hold multiple roles simultaneously.
Every access token payload includes a roles array derived from the user's active role
assignments at token-issuance time. Clients may read this for UI decisions (e.g. showing
admin menus). Server-side permission evaluation always queries the database.
Each role_permission record carries an optional resource_type and resource_id,
enabling three tiers of access (first match wins):
| Tier | Condition | Example |
|---|---|---|
| 1 — Exact | permission + resource_type + resource_id |
User can refund invoice abc-123 only |
| 2 — Type-scoped | permission + resource_type |
User can refund any invoice |
| 3 — Global | permission only |
User can refund anything |
Subscriber role permissions are type-scoped (e.g. users.read scoped to resource_type: user).
They satisfy API calls that pass a matching resource_type but not no-scope admin list calls.
Admin/superadmin permissions are global and satisfy all tiers.
On mutating subscriber endpoints the server additionally verifies the caller owns the target resource. Subscribers cannot modify another user's profiles, payment methods, or notifications. Admins holding a global permission bypass the ownership check.
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| display_name | string <= 100 characters |
| phone | string <= 20 characters ^\+[1-9]\d{1,14}$ |
| locale | string |
| timezone | string |
| country_code | string = 2 characters |
| preferred_language | string |
object Per-type notification opt-in/opt-out. |
{- "display_name": "string",
- "phone": "string",
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "st",
- "preferred_language": "en",
- "notification_preferences": {
- "payment": true,
- "new_content": true,
- "account_security": true,
- "marketing": true
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Initiates account deletion. A grace period applies (typically 30 days) during which
the user can cancel. At period end, all personal data is permanently erased per GDPR Art. 17.
Use /users/me/deletion-request for cancellation.
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "pending",
- "scheduled_deletion_at": "2019-08-24T14:15:22Z",
- "requested_at": "2019-08-24T14:15:22Z"
}Changes the account password. All other sessions are revoked on success.
| current_password required | string <password> |
| new_password required | string <password> [ 10 .. 128 ] characters |
{- "current_password": "pa$$word",
- "new_password": "pa$$word_q"
}{- "data": {
- "access_token": "string",
- "token_type": "Bearer",
- "expires_in": 900,
- "refresh_token": "string",
- "scope": "openid profile content:read subscription:read watchlist devices drm",
- "id_token": "string"
}
}Upload a new avatar image. Maximum 5MB, JPEG or PNG only.
| file required | string <binary> Avatar image file (JPEG or PNG, max 5 MB). |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "is_primary": true,
- "pin_protected": false,
- "content_rating_limit": "G",
- "language": "en-US",
- "is_kids": false,
- "autoplay_next_episode": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Creates a new profile. Returns 409 if the plan's profile limit is reached.
| name required | string <= 50 characters |
| avatar_preset_id | string <uuid> Preset avatar UUID from the platform's avatar library. |
| pin | string [ 4 .. 6 ] characters ^\d+$ Numeric PIN for profile lock. Required if is_kids is false and PIN protection is desired. |
| content_rating_limit | string Default: "TV-MA" Enum: "G" "PG" "PG-13" "R" "NC-17" "TV-Y" "TV-G" "TV-PG" "TV-14" "TV-MA" |
| language | string |
| is_kids | boolean Default: false |
| autoplay_next_episode | boolean Default: true |
{- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "pin": "string",
- "content_rating_limit": "G",
- "language": "string",
- "is_kids": false,
- "autoplay_next_episode": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "is_primary": true,
- "pin_protected": false,
- "content_rating_limit": "G",
- "language": "en-US",
- "is_kids": false,
- "autoplay_next_episode": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "is_primary": true,
- "pin_protected": false,
- "content_rating_limit": "G",
- "language": "en-US",
- "is_kids": false,
- "autoplay_next_episode": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| profile_id required | string <uuid> |
| name required | string <= 50 characters |
| avatar_preset_id | string <uuid> Preset avatar UUID from the platform's avatar library. |
| pin | string [ 4 .. 6 ] characters ^\d+$ Numeric PIN for profile lock. Required if is_kids is false and PIN protection is desired. |
| content_rating_limit | string Default: "TV-MA" Enum: "G" "PG" "PG-13" "R" "NC-17" "TV-Y" "TV-G" "TV-PG" "TV-14" "TV-MA" |
| language | string |
| is_kids | boolean Default: false |
| autoplay_next_episode | boolean Default: true |
{- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "pin": "string",
- "content_rating_limit": "G",
- "language": "string",
- "is_kids": false,
- "autoplay_next_episode": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "avatar_preset_id": "308d6212-d330-494c-b2e8-dadf2a06a598",
- "is_primary": true,
- "pin_protected": false,
- "content_rating_limit": "G",
- "language": "en-US",
- "is_kids": false,
- "autoplay_next_episode": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Deletes profile and associated watchlist/progress data. The primary profile cannot be deleted.
| profile_id required | string <uuid> |
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}Returns a short-lived profile session token. Required before switching to a PIN-protected profile.
| profile_id required | string <uuid> |
| pin required | string [ 4 .. 6 ] characters ^\d+$ |
{- "pin": "string"
}{- "profile_token": "string",
- "expires_in": 3600
}Returns all subscriptions for the authenticated user across all types
(svod, live, addon, ppv). Filter by type or status to narrow results.
| type | string (SubscriptionType) Enum: "svod" "live" "addon" "ppv" Filter by subscription type. |
| status | string Enum: "trialing" "active" "past_due" "canceled" "paused" "expired" |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Creates a new subscription for the authenticated user. The plan's type
determines the subscription type. Returns 409 if the user already has
an active subscription of that type — cancel or upgrade the existing one first.
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| plan_id required | string <uuid> |
| payment_method_id required | string <uuid> Payment method UUID from the gateway. Never send raw card data. |
| coupon_code | string <= 50 characters |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "coupon_code": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| subscription_id required | string <uuid> |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Changes to another plan of the same type. Cross-type plan changes are not
permitted — cancel the existing subscription and start a new one instead.
Proration is calculated server-side. Use /{subscription_id}/preview first
to show the cost to the user before committing.
| subscription_id required | string <uuid> |
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| plan_id required | string <uuid> Target plan — must be the same |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Schedules cancellation at end of the current billing period.
Set immediate: true for instant termination (no refund).
| subscription_id required | string <uuid> |
| immediate | boolean Default: false |
| reason | string <= 500 characters |
{- "immediate": false,
- "reason": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns proration amounts and next billing date for a plan change without committing.
| subscription_id required | string <uuid> |
| plan_id required | string <uuid> |
| coupon_code | string <= 50 characters |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "coupon_code": "string"
}{- "data": {
- "from_plan_id": "d841a014-75f2-42da-a20a-4836623c2ec7",
- "to_plan_id": "0910f027-1b25-4687-aad0-d8a5ca6b89a1",
- "proration_credit": 0.1,
- "amount_due_now": 0.1,
- "currency": "string",
- "next_billing_date": "2019-08-24",
- "effective": "immediate"
}
}Returns saved payment methods. Full card numbers are never returned.
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "card",
- "brand": "visa",
- "last4": "stri",
- "exp_month": 1,
- "exp_year": 2000,
- "is_expired": true,
- "is_default": true,
- "billing_name": "string",
- "billing_country": "US",
- "wallet_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Attaches a tokenised payment method to the account.
The payment_method_token must be obtained from the client-side payment SDK
(Stripe, Braintree, etc.). Never send raw card data to this API.
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| payment_method_token required | string Token from client-side payment SDK. Never send raw card data. |
| set_as_default | boolean Default: false |
| billing_name | string <= 100 characters |
{- "payment_method_token": "string",
- "set_as_default": false,
- "billing_name": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "card",
- "brand": "visa",
- "last4": "stri",
- "exp_month": 1,
- "exp_year": 2000,
- "is_expired": true,
- "is_default": true,
- "billing_name": "string",
- "billing_country": "US",
- "wallet_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "card",
- "brand": "visa",
- "last4": "stri",
- "exp_month": 1,
- "exp_year": 2000,
- "is_expired": true,
- "is_default": true,
- "billing_name": "string",
- "billing_country": "US",
- "wallet_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Cannot remove the default payment method if an active subscription exists.
| pm_id required | string <uuid> |
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}| pm_id required | string <uuid> |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "card",
- "brand": "visa",
- "last4": "stri",
- "exp_month": 1,
- "exp_year": 2000,
- "is_expired": true,
- "is_default": true,
- "billing_name": "string",
- "billing_country": "US",
- "wallet_email": "user@example.com",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
| status | string Enum: "open" "paid" "uncollectible" "void" |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "invoice_number": "INV-2026-00142",
- "subscription_id": "aa11a4c2-a467-43db-b413-c4ab0f5cf627",
- "status": "draft",
- "amount": 0.1,
- "amount_paid": 0.1,
- "discount_amount": 0,
- "tax_amount": 0,
- "amount_due": 0.1,
- "currency": "str",
- "description": "string",
- "period_start": "2019-08-24T14:15:22Z",
- "period_end": "2019-08-24T14:15:22Z",
- "due_date": "2019-08-24T14:15:22Z",
- "paid_at": "2019-08-24T14:15:22Z",
- "line_items": [
- {
- "description": "string",
- "quantity": 1,
- "unit_price": 0.1,
- "amount": 0.1,
- "type": "subscription"
}
], - "created_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "invoice_number": "INV-2026-00142",
- "subscription_id": "aa11a4c2-a467-43db-b413-c4ab0f5cf627",
- "status": "draft",
- "amount": 0.1,
- "amount_paid": 0.1,
- "discount_amount": 0,
- "tax_amount": 0,
- "amount_due": 0.1,
- "currency": "str",
- "description": "string",
- "period_start": "2019-08-24T14:15:22Z",
- "period_end": "2019-08-24T14:15:22Z",
- "due_date": "2019-08-24T14:15:22Z",
- "paid_at": "2019-08-24T14:15:22Z",
- "line_items": [
- {
- "description": "string",
- "quantity": 1,
- "unit_price": 0.1,
- "amount": 0.1,
- "type": "subscription"
}
], - "created_at": "2019-08-24T14:15:22Z"
}
}Checks if a coupon code is valid for the current user and plan before applying.
| code required | string <= 50 characters |
| plan_id required | string <uuid> |
{- "code": "string",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72"
}{- "valid": true,
- "coupon": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "redemption_count": 0,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "error_code": "not_found"
}Returns the current balance and status of a gift card before redemption.
| code required | string <= 64 characters |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "initial_value": 0.1,
- "remaining_value": 0.1,
- "currency": "string",
- "status": "active",
- "redeemed_by": "61b8282b-fd6d-4a53-8c86-650d790b4549",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
}Applies a gift card to the authenticated user's account balance.
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| code required | string <= 64 characters |
{- "code": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "initial_value": 0.1,
- "remaining_value": 0.1,
- "currency": "string",
- "status": "active",
- "redeemed_by": "61b8282b-fd6d-4a53-8c86-650d790b4549",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
| unread_only | boolean Default: false |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "payment_failed",
- "priority": "low",
- "title": "string",
- "body": "string",
- "is_read": false,
- "read_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
], - "unread_count": 0,
- "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}| notif_id required | string <uuid> |
| is_read | boolean |
{- "is_read": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "type": "payment_failed",
- "priority": "low",
- "title": "string",
- "body": "string",
- "is_read": false,
- "read_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
}Polls the latest export job status. When ready, the response includes a signed, time-limited download URL. The URL expires in 24 hours.
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "pending",
- "requested_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z"
}
}Queues a data export job. When ready, a download link is emailed to the account address. One pending export per account at a time.
{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "pending",
- "requested_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z"
}Initiates account deletion with a 30-day grace period. Active subscriptions are canceled immediately (no refund). During grace period the user may log in to cancel the request.
| password required | string <password> Current account password for confirmation. |
| reason | string <= 500 characters |
{- "password": "pa$$word",
- "reason": "string"
}{- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "pending",
- "scheduled_deletion_at": "2019-08-24T14:15:22Z",
- "requested_at": "2019-08-24T14:15:22Z"
}Cancels an active deletion request during the 30-day grace period. Restores full account access. Audit-logged.
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}Returns all registered users with filtering support. Results exclude deleted accounts by default.
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
| q | string <= 200 characters Full-text search query (max 200 characters). |
| status | string Enum: "active" "suspended" "pending_verification" "deleted" |
| role | string Enum: "subscriber" "partner" "admin" |
| country_code | string = 2 characters |
| created_after | string <date-time> |
| created_before | string <date-time> |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Allows changing a user's status and roles. Requires admin scope.
Role escalation to superadmin requires superadmin scope.
All changes are audit-logged with actor ID.
| user_id required | string <uuid> |
| status | string Enum: "active" "suspended" |
| roles | Array of strings Items Enum: "subscriber" "partner" "admin" |
{- "status": "active",
- "roles": [
- "subscriber"
]
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Immediately suspends the user account.
All active sessions and stream concurrency slots are revoked.
Suspended users receive 403 on login attempts.
Audit-logged with actor ID and reason.
| user_id required | string <uuid> |
| reason required | string <= 500 characters Reason for suspension. Required for audit trail. |
| notify_user | boolean Default: true Whether to send an email notification to the user. |
{- "reason": "string",
- "notify_user": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Restores account access for a suspended user. Audit-logged.
| user_id required | string <uuid> |
| note | string <= 500 characters Optional reinstatement note for the audit record. |
{- "note": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "email": "user@example.com",
- "email_verified": true,
- "display_name": "string",
- "phone": "string",
- "phone_verified": true,
- "locale": "en-US",
- "timezone": "America/New_York",
- "country_code": "US",
- "preferred_language": "en",
- "status": "active",
- "roles": [
- "subscriber"
], - "mfa_enabled": false,
- "terms_accepted_at": "2019-08-24T14:15:22Z",
- "last_login_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns all plans including inactive ones. Superadmin only.
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}| name required | string <= 100 characters |
| type required | string (SubscriptionType) Enum: "svod" "live" "addon" "ppv" Determines what this plan unlocks. A user can hold at most one active subscription per type at a time. |
| description | string <= 500 characters |
| price required | number <double> >= 0 |
| currency required | string = 3 characters ISO 4217 currency code. |
| billing_cycle required | string Enum: "monthly" "quarterly" "semi_annual" "annual" |
| max_profiles required | integer [ 1 .. 6 ] Maximum sub-profiles allowed under this plan. |
| max_concurrent_streams required | integer [ 1 .. 8 ] Maximum simultaneous streams across all devices. |
| max_devices required | integer [ 1 .. 20 ] Maximum registered devices allowed. |
| max_quality required | string Enum: "SD" "HD" "FHD" "UHD_4K" "UHD_8K" Highest supported playback quality. |
| has_downloads required | boolean Whether offline downloads are permitted. |
| allow_download_count | integer >= 0 Maximum simultaneous downloads per profile. Null = unlimited (if has_downloads is true). |
| has_ads required | boolean Whether this plan includes ad breaks. |
| has_hdr | boolean Whether HDR (HDR10 / Dolby Vision) content is accessible on this plan. |
| has_dolby_atmos | boolean Whether Dolby Atmos spatial audio is accessible on this plan. |
| trial_days | integer >= 0 Default: 0 Free trial duration in days. 0 = no trial. |
| is_active required | boolean False means new subscriptions are blocked; existing subscriptions continue. |
{- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Changes to price, billing_cycle, or max_* fields only apply to new subscriptions.
Existing subscribers are grandfathered until next renewal.
| plan_id required | string <uuid> |
| If-Match | string ETag of the resource version the client last read. Enables optimistic concurrency on writes:
the request is rejected with |
| name required | string <= 100 characters |
| type required | string (SubscriptionType) Enum: "svod" "live" "addon" "ppv" Determines what this plan unlocks. A user can hold at most one active subscription per type at a time. |
| description | string <= 500 characters |
| price required | number <double> >= 0 |
| currency required | string = 3 characters ISO 4217 currency code. |
| billing_cycle required | string Enum: "monthly" "quarterly" "semi_annual" "annual" |
| max_profiles required | integer [ 1 .. 6 ] Maximum sub-profiles allowed under this plan. |
| max_concurrent_streams required | integer [ 1 .. 8 ] Maximum simultaneous streams across all devices. |
| max_devices required | integer [ 1 .. 20 ] Maximum registered devices allowed. |
| max_quality required | string Enum: "SD" "HD" "FHD" "UHD_4K" "UHD_8K" Highest supported playback quality. |
| has_downloads required | boolean Whether offline downloads are permitted. |
| allow_download_count | integer >= 0 Maximum simultaneous downloads per profile. Null = unlimited (if has_downloads is true). |
| has_ads required | boolean Whether this plan includes ad breaks. |
| has_hdr | boolean Whether HDR (HDR10 / Dolby Vision) content is accessible on this plan. |
| has_dolby_atmos | boolean Whether Dolby Atmos spatial audio is accessible on this plan. |
| trial_days | integer >= 0 Default: 0 Free trial duration in days. 0 = no trial. |
| is_active required | boolean False means new subscriptions are blocked; existing subscriptions continue. |
{- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Marks a plan as inactive — new subscriptions to this plan are blocked. Existing subscriptions continue until they are canceled or expire naturally. Plans with active subscribers cannot be hard-deleted. Audit-logged.
| plan_id required | string <uuid> |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Admin subscription management — assign, modify, cancel, pause, resume, extend, and reactivate subscriptions on behalf of any user
Returns subscriptions across all users. Supports filtering by type, status,
plan, and date range. Results are ordered by created_at descending.
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
| type | string (SubscriptionType) Enum: "svod" "live" "addon" "ppv" Filter by subscription type. |
| status | string Enum: "trialing" "active" "past_due" "canceled" "paused" "expired" Filter by subscription status. |
| plan_id | string <uuid> Filter by plan. |
| created_after | string <date-time> |
| created_before | string <date-time> |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Returns all subscriptions for a specific user across all types. A user may hold one active subscription per type simultaneously.
| user_id required | string <uuid> |
| type | string (SubscriptionType) Enum: "svod" "live" "addon" "ppv" Subscription type determines what content or service the plan unlocks:
|
| status | string Enum: "trialing" "active" "past_due" "canceled" "paused" "expired" |
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Assigns a plan to a user on their behalf. The plan's type determines the
subscription type. Payment method is optional — admins can grant complimentary
or manually-billed subscriptions. Returns 409 if the user already has an
active subscription of that type.
| user_id required | string <uuid> |
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| plan_id required | string <uuid> Plan to assign to the user. |
| payment_method_id | string or null <uuid> Payment method to charge. Null for complimentary or manually-billed subscriptions where no automatic charge is needed. |
| coupon_code | string <= 50 characters Optional coupon to apply at assignment. |
| trial_end | string <date-time> Override trial end date. If omitted and the plan has a trial period, the standard trial applies. Set to a past date to skip the trial. |
| current_period_end | string <date-time> Override the first billing period end. Useful for prorating a partial month when migrating a user from another platform. |
| auto_renew | boolean Default: true Whether the subscription renews automatically at period end. |
| admin_note | string <= 500 characters Internal note recorded in the audit log. Not visible to the user. |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "coupon_code": "string",
- "trial_end": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "auto_renew": true,
- "admin_note": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Partially updates a subscription — change plan (within same type), swap payment method, toggle auto-renew, override period end, or schedule cancellation. All changes are audit-logged with the acting admin's identity.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
| If-Match | string ETag of the resource version the client last read. Enables optimistic concurrency on writes:
the request is rejected with |
| plan_id | string <uuid> Change the subscribed plan (upgrade or downgrade). Proration applied automatically. |
| payment_method_id | string or null <uuid> Swap the payment method. Null removes the payment method (switches to manual billing). |
| auto_renew | boolean Enable or disable automatic renewal. |
| current_period_end | string <date-time> Override the current period end date directly. |
| cancel_at_period_end | boolean Schedule or unschedule cancellation at period end. |
| admin_note | string <= 500 characters Internal note recorded in the audit log. |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "auto_renew": true,
- "current_period_end": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "admin_note": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Cancels a specific subscription. Access continues until period end by default.
Set immediate: true to terminate instantly. Audit-logged with reason.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
| immediate | boolean Default: false |
| reason | string <= 500 characters |
{- "immediate": false,
- "reason": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Suspends billing and access. Status changes to paused. Optionally schedule
automatic resumption via resume_at.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
| resume_at | string <date-time> Schedule automatic resumption. Null for indefinite pause. |
| reason | string <= 500 characters |
{- "resume_at": "2019-08-24T14:15:22Z",
- "reason": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Resumes a paused subscription. Billing restarts from the resume date; the period end is extended by the paused duration.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Reactivates a canceled or expired subscription, optionally on a different
plan of the same type. A new billing period starts from the reactivation date.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
| plan_id | string <uuid> Plan to reactivate on (must be same type). Defaults to the previous plan. |
| payment_method_id | string or null <uuid> |
| admin_note | string <= 500 characters |
{- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "admin_note": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Extends the current billing period by a given number of days without charging the user. Used for goodwill extensions, outage compensation, or manual proration adjustments. Audit-logged.
| user_id required | string <uuid> |
| subscription_id required | string <uuid> |
| days required | integer [ 1 .. 365 ] Number of days to add to the current period end. |
| reason | string <= 500 characters Reason recorded in the audit log. |
{- "days": 1,
- "reason": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "plan_id": "00713021-9aea-41da-9a88-87760c08fa72",
- "type": "svod",
- "plan": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "Standard HD",
- "type": "svod",
- "description": "string",
- "price": 9.99,
- "currency": "USD",
- "billing_cycle": "monthly",
- "max_profiles": 1,
- "max_concurrent_streams": 1,
- "max_devices": 1,
- "max_quality": "SD",
- "has_downloads": true,
- "allow_download_count": 0,
- "has_ads": true,
- "has_hdr": true,
- "has_dolby_atmos": true,
- "trial_days": 0,
- "is_active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}, - "status": "trialing",
- "auto_renew": true,
- "current_period_start": "2019-08-24T14:15:22Z",
- "current_period_end": "2019-08-24T14:15:22Z",
- "next_billing_date": "2019-08-24T14:15:22Z",
- "cancel_at_period_end": true,
- "canceled_at": "2019-08-24T14:15:22Z",
- "paused_at": "2019-08-24T14:15:22Z",
- "trial_start": "2019-08-24T14:15:22Z",
- "trial_end": "2019-08-24T14:15:22Z",
- "payment_method_id": "ec18d2d7-d2e0-41e4-98e4-847f14422d8a",
- "payment_method_last4": "stri",
- "coupon_id": "97ffaabb-eb3d-43ed-8769-a889d53b9a3d",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
| status | string Enum: "active" "expired" "disabled" |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "redemption_count": 0,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}| code required | string <= 50 characters ^[A-Z0-9_-]+$ Human-readable coupon code. Uppercase alphanumeric, hyphens, underscores. |
| description | string <= 500 characters |
| discount_type required | string Enum: "percent" "fixed_amount" "free_trial_days" |
| discount_value required | number <double> Interpretation depends on discount_type:
percent — percentage off (1–100).
fixed_amount — flat discount in |
| currency | string = 3 characters ISO 4217 currency code. Required and only applicable when discount_type is fixed_amount. |
| applicable_plan_ids | Array of strings <uuid> [ items <uuid > ] Plan UUIDs this coupon applies to. Empty array = applies to all plans. |
| max_redemptions | integer >= 1 Maximum total redemptions allowed. Null = unlimited. |
| max_redemptions_per_user | integer >= 1 Default: 1 Maximum redemptions allowed per individual user account. |
| valid_from required | string <date-time> Coupon becomes active at this timestamp (UTC). |
| valid_until | string <date-time> Coupon expires at this timestamp. Null = no expiry date. |
| status required | string Enum: "active" "expired" "disabled" active — usable. expired — past valid_until; system-managed. disabled — manually deactivated by admin. |
{- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "redemption_count": 0,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "redemption_count": 0,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Allowed updates: status (disable/re-enable), max_redemptions, valid_until, description.
code, discount_type, and discount_value are immutable after creation.
| coupon_id required | string <uuid> |
| status | string Enum: "active" "disabled" |
| max_redemptions | integer >= 1 |
| valid_until | string <date-time> |
| description | string <= 500 characters |
{- "status": "active",
- "max_redemptions": 1,
- "valid_until": "2019-08-24T14:15:22Z",
- "description": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "description": "string",
- "discount_type": "percent",
- "discount_value": 0.1,
- "currency": "str",
- "applicable_plan_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "max_redemptions": 1,
- "max_redemptions_per_user": 1,
- "redemption_count": 0,
- "valid_from": "2019-08-24T14:15:22Z",
- "valid_until": "2019-08-24T14:15:22Z",
- "status": "active",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Hard-deletes a coupon. Forbidden if the coupon has been redeemed (disable instead).
| coupon_id required | string <uuid> |
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}Bulk-generates gift cards with a specified value.
| quantity required | integer [ 1 .. 500 ] |
| initial_value required | number <float> >= 0.01 |
| currency required | string = 3 characters |
| expires_at | string <date-time> |
{- "quantity": 1,
- "initial_value": 0.01,
- "currency": "str",
- "expires_at": "2019-08-24T14:15:22Z"
}{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "code": "string",
- "initial_value": 0.1,
- "remaining_value": 0.1,
- "currency": "string",
- "status": "active",
- "redeemed_by": "61b8282b-fd6d-4a53-8c86-650d790b4549",
- "redeemed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
]
}Returns all refunds issued against a specific invoice.
| invoice_id required | string <uuid> |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "invoice_id": "f4c4edb8-11e0-4b33-bcc1-482dc59ebb32",
- "amount": 0.1,
- "currency": "string",
- "reason": "requested_by_customer",
- "status": "pending",
- "notes": "string",
- "provider_refund_id": "string",
- "actor_id": "04f37679-bfbf-4906-b749-01756515cecf",
- "processed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Initiates a refund against an invoice. Refunds are audit-logged with the actor ID. Partial refunds are supported.
| invoice_id required | string <uuid> |
| Idempotency-Key | string <= 255 characters Client-generated unique key (UUIDv7 recommended — time-ordered, collision-resistant) that makes a write request safely retryable. Replaying the same key within 24h returns the original result instead of performing the action twice. Strongly recommended on all payment and subscription mutations. |
| amount required | number <float> >= 0.01 Refund amount (must be ≤ invoice amount_paid). |
| reason required | string Enum: "requested_by_customer" "duplicate" "fraudulent" "service_issue" "goodwill" |
| notes | string <= 500 characters |
{- "amount": 0.01,
- "reason": "requested_by_customer",
- "notes": "string"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "invoice_id": "f4c4edb8-11e0-4b33-bcc1-482dc59ebb32",
- "amount": 0.1,
- "currency": "string",
- "reason": "requested_by_customer",
- "status": "pending",
- "notes": "string",
- "provider_refund_id": "string",
- "actor_id": "04f37679-bfbf-4906-b749-01756515cecf",
- "processed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
}Returns all platform roles (system-built-in and custom).
| type | string Enum: "system" "custom" Filter by role type. |
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "content_editor",
- "display_name": "Content Editor",
- "description": "Can create and update content; cannot publish.",
- "type": "system",
- "permissions": [
- "content.write"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7",
- "inherited_permissions": [
- "string"
], - "is_active": true
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Creates a new custom role. name must be unique. Requires superadmin scope.
| name required | string^[a-z][a-z0-9_]{1,63}$ |
| display_name | string |
| description | string |
| permissions required | Array of strings non-empty |
| parent_role_id | string or null <uuid> Optional parent role ID for inheritance. Max depth 3. |
{- "name": "regional_manager",
- "display_name": "Regional Manager",
- "description": "string",
- "permissions": [
- "users.read"
], - "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "content_editor",
- "display_name": "Content Editor",
- "description": "Can create and update content; cannot publish.",
- "type": "system",
- "permissions": [
- "content.write"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7",
- "inherited_permissions": [
- "string"
], - "is_active": true
}
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "content_editor",
- "display_name": "Content Editor",
- "description": "Can create and update content; cannot publish.",
- "type": "system",
- "permissions": [
- "content.write"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7",
- "inherited_permissions": [
- "string"
], - "is_active": true
}
}Updates a custom role's display name, description, or permission set. System roles are read-only — 403 is returned if attempted. Requires superadmin scope.
| role_id required | string <uuid> |
| display_name | string |
| description | string |
| permissions | Array of strings non-empty |
| parent_role_id | string or null <uuid> |
| is_active | boolean |
{- "display_name": "string",
- "description": "string",
- "permissions": [
- "string"
], - "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7",
- "is_active": true
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "content_editor",
- "display_name": "Content Editor",
- "description": "Can create and update content; cannot publish.",
- "type": "system",
- "permissions": [
- "content.write"
], - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "parent_role_id": "7ea77ce3-4218-4d39-ad84-02444a2f4ee7",
- "inherited_permissions": [
- "string"
], - "is_active": true
}
}Permanently deletes a custom role and revokes all existing assignments. System roles cannot be deleted. Requires superadmin scope.
| role_id required | string <uuid> |
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}Returns all roles currently assigned to the specified user.
| user_id required | string <uuid> |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "role_id": "ac4e70c8-d5be-48af-93eb-760f58fc91a9",
- "role_name": "content_editor",
- "granted_by": "a8e4a498-f971-4203-a849-4967743579d4",
- "granted_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z"
}
]
}Grants the specified role to a user. Assigning superadmin requires superadmin scope. All assignments are audit-logged.
| user_id required | string <uuid> |
| role_id required | string <uuid> |
| expires_at | string or null <date-time> Optional expiry. Omit for a permanent assignment. |
{- "role_id": "ac4e70c8-d5be-48af-93eb-760f58fc91a9",
- "expires_at": "2019-08-24T14:15:22Z"
}{- "data": {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "role_id": "ac4e70c8-d5be-48af-93eb-760f58fc91a9",
- "role_name": "content_editor",
- "granted_by": "a8e4a498-f971-4203-a849-4967743579d4",
- "granted_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z"
}
}Removes the role assignment. The user immediately loses all permissions granted exclusively by that role. Revoking superadmin requires superadmin scope. All revocations are audit-logged.
| user_id required | string <uuid> |
| role_id required | string <uuid> |
{- "code": "UNAUTHORIZED",
- "message": "Access token is missing or invalid.",
- "request_id": "018fde1a-9b2c-7f3e-8d4a-2b5c6e7f8a9b"
}Returns the paginated list of users who currently hold this role.
| role_id required | string <uuid> |
| cursor | string Opaque pagination cursor from |
| limit | integer [ 1 .. 100 ] Default: 20 Number of items per page (1–100, default 20). |
{- "data": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "role_id": "ac4e70c8-d5be-48af-93eb-760f58fc91a9",
- "role_name": "content_editor",
- "granted_by": "a8e4a498-f971-4203-a849-4967743579d4",
- "granted_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Permission catalogue, grouping, synchronous permission checks, and per-user effective permission resolution
Returns all discrete permissions defined in the platform. Use this to build a role editor UI.
| resource | string Filter by resource, e.g. |
{- "data": [
- {
- "key": "users.read",
- "display_name": "Read Users",
- "description": "Allows listing and viewing subscriber accounts.",
- "resource": "users",
- "action": "read",
- "group": "user_management",
- "is_deprecated": false
}
], - "meta": {
- "total": 2450,
- "count": 20,
- "limit": 20,
- "has_more": true,
- "next_cursor": "eyJpZCI6IjEyMyJ9",
- "prev_cursor": null
}
}Returns the complete, deduplicated set of permissions a user holds, derived from all their assigned roles. Useful for access-control debugging.
| user_id required | string <uuid> |
{- "data": {
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
- "roles": [
- "subscriber",
- "content_editor"
], - "permissions": [
- "content.read",
- "content.write",
- "users.read"
], - "role_details": [
- {
- "role_id": "ac4e70c8-d5be-48af-93eb-760f58fc91a9",
- "role_name": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "permissions": [
- {
- "permission_key": "string",
- "resource_type": "string",
- "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
- "scope": "string"
}
]
}
]
}
}Synchronously evaluates whether a user holds a given permission, optionally scoped to a specific resource.
Intended for internal service-to-service authorisation checks. Responses include evaluated_at to support
short-lived client-side caching. Always returns 200; use the allowed field to branch logic.
Rate limit: 600 req / min per calling service.
| subject_id required | string <uuid> ID of the user whose access is being checked. |
| permission required | string The permission key to evaluate, e.g. |
| resource_type | string Optional resource type for resource-scoped checks. |
| resource_id | string <uuid> Optional ID of the specific resource for resource-scoped checks. |
{- "subject_id": "80e197be-61ad-4068-b4ff-a483fb5c18f9",
- "permission": "users.suspend",
- "resource_type": "movie",
- "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f"
}{- "data": {
- "allowed": true,
- "subject_id": "80e197be-61ad-4068-b4ff-a483fb5c18f9",
- "permission": "users.suspend",
- "resource_type": "string",
- "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
- "matched_role": "string",
- "matched_role_permission_id": "7bd3822f-3950-4734-9ffe-91441f194817",
- "scope": "string",
- "evaluated_at": "2019-08-24T14:15:22Z"
}
}Returns the full permission catalogue organised into groups. Use this to render a role-editor UI.
{- "data": [
- {
- "key": "user_management",
- "display_name": "User Management",
- "description": "string",
- "permissions": [
- "users.read",
- "users.write"
]
}
]
}