/subscribd/api/v1) and require bearer token authentication.
Authentication
The REST API uses hashed bearer tokens. Tokens are issued through an authenticated endpoint and passed in theAuthorization header on subsequent requests.
Token abilities
Tokens support optional ability scoping. When a token has no abilities (or abilities isnull), it acts as a wildcard and grants access to all endpoints. Otherwise, each ability must be explicitly listed. The special * ability also grants full access.
Token expiration
Tokens can have an optionalexpires_at date. Expired tokens are rejected automatically. Tokens without an expiry never expire.
Setup
Add the trait to your billable model
TheManagesBilling trait automatically includes the apiTokens() relationship. If you are already using ManagesBilling, no additional setup is needed.
For models that only need API token support without full billing, add the HasApiTokens trait and define the apiTokens() relationship manually:
Configure the API
The API is enabled by default. You can customize the path and middleware inconfig/subscribd.php:
| Key | Type | Default | Description |
|---|---|---|---|
enabled | bool | true | Enable or disable the REST API routes. |
path | string | 'subscribd/api/v1' | URL prefix for all API routes. |
middleware | array | ['api'] | Middleware applied to bearer-protected endpoints. |
token_middleware | array | ['auth'] | Middleware applied to token issuance and revocation endpoints. Must resolve $request->user(). |
The
token_middleware must authenticate the user through your application’s own auth guard (e.g., auth:web, auth:sanctum). This is separate from the bearer token middleware that protects the other API endpoints.Token management
Issue a token
POST
Requires host authentication (configured via /tokenstoken_middleware).
Request body:
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | Yes | A human-readable label for the token (max 255 characters). |
abilities | string[] | No | List of abilities to scope the token. Omit for full access. |
expires_at | string | No | ISO 8601 datetime for token expiry. Must be in the future. null for no expiry. |
201 Created:
Revoke a token
DELETE
Requires host authentication. You can only revoke your own tokens.
Response /tokens/{id}204 No Content
Error responses:
| Status | Description |
|---|---|
401 | Not authenticated. |
404 | Token not found or belongs to another user. |
Plans
List plans
GET
Returns all active plans ordered by /planssort_order.
Response 200 OK:
Get a plan
GET
Returns a single plan. Returns /plans/{id}404 if the plan is inactive.
Response 200 OK:
Plan object
| Field | Type | Description |
|---|---|---|
id | integer | Unique plan identifier. |
key | string | Config-defined plan key. |
name | string | Display name. |
description | string|null | Plan description. |
price | integer | Price in minor currency units (e.g., cents). |
currency | string | ISO 4217 currency code. |
interval | string | Billing interval: day, week, month, or year. |
interval_count | integer | Number of intervals per billing cycle. |
trial_days | integer|null | Free trial duration in days. |
features | object|null | Feature flags and limits defined on the plan. |
is_recurring | boolean | true for recurring plans, false for one-time/lifetime. |
sort_order | integer | Display ordering. |
Subscriptions
All subscription endpoints are scoped to the token owner. You can only view and manage your own subscriptions.List subscriptions
GET
Returns a paginated list of the token owner’s subscriptions, newest first.
Response /subscriptions200 OK:
Get a subscription
GET
Returns a single subscription with the related plan. Returns /subscriptions/{id}404 if the subscription does not belong to the token owner.
Cancel a subscription
POST
Cancels a subscription. By default, cancellation takes effect at the end of the current billing period.
Request body:
/subscriptions/{id}/cancel| Parameter | Type | Required | Description |
|---|---|---|---|
immediately | boolean | No | Set to true to cancel immediately instead of at period end. Defaults to false. |
200 OK — returns the updated subscription object.
Error responses:
| Status | Description |
|---|---|
404 | Subscription not found or does not belong to the token owner. |
422 | Subscription cannot be canceled in its current state. |
Resume a subscription
POST
Resumes a canceled (grace period) or paused subscription.
Response /subscriptions/{id}/resume200 OK — returns the updated subscription object.
Error responses:
| Status | Description |
|---|---|
404 | Subscription not found or does not belong to the token owner. |
422 | Subscription cannot be resumed in its current state. |
Tally metered usage
POST
Triggers a mid-period metered usage tally for the subscription. Subscribd computes overage across all metered plan items for the requested billing window, subtracts any units already billed in prior tallies during the same period, and charges only the incremental delta. If no overage is due, the response returns /subscriptions/{id}/tally-usagedata: null without creating an invoice.
This endpoint is safe to call multiple times per period — delta billing ensures each unit of overage is charged exactly once.
Request body:
| Parameter | Type | Required | Description |
|---|---|---|---|
period_start | string | No | ISO 8601 timestamp for the start of the billing window (inclusive). Defaults to the subscription’s current_period_start. |
period_end | string | No | ISO 8601 timestamp for the end of the billing window (exclusive). Defaults to the current time. |
200 OK — when overage is billed:
200 OK — when no overage is due:
| Status | Description |
|---|---|
404 | Subscription not found or does not belong to the token owner. |
422 | Validation failure, or the subscription has no current_period_start and period_start was not supplied. |
The tally endpoint uses the same delta billing logic as the
subscribd:tally-usage Artisan command. Usage records that contribute to an overage invoice are stamped with the invoice ID for audit purposes.Upgrade a free subscription to a paid plan
POST
Converts a /subscriptions/{id}/upgrade-from-freefree subscription to a paid plan on a real payment gateway. The old free subscription is canceled locally and a new paid subscription is created in a single transaction. The new subscription inherits the same name slot.
Request body:
| Parameter | Type | Required | Description |
|---|---|---|---|
plan_id | integer | Yes | ID of the paid plan to upgrade to. |
gateway | string | No | Payment gateway driver name. Defaults to the configured default gateway. Cannot be null (the null driver). |
quantity | integer | No | Seat count for per-seat plans. Must be at least 1. Defaults to the quantity resolver result or 1. |
201 Created — returns the new subscription object:
| Status | Description |
|---|---|
404 | Subscription not found or does not belong to the token owner. |
422 | Subscription is not in free status, the target gateway is the null driver, or validation failed. |
The old free subscription is canceled locally without calling any gateway API (the null gateway has no remote state). A
SubscriptionCreated event fires for the new paid subscription.Subscription object
| Field | Type | Description |
|---|---|---|
id | integer | Unique subscription identifier. |
name | string | Subscription slot name (e.g., default). |
gateway | string | Payment gateway driver name. |
gateway_id | string|null | Gateway-specific subscription identifier. |
status | string | Current status: active, trialing, past_due, grace, paused, canceled, incomplete, expired, free, or lifetime. |
currency | string | ISO 4217 currency code. |
quantity | integer | Seat count (for per-seat plans). |
plan | object|null | Nested plan object (included when the relation is loaded). |
trial_ends_at | string|null | ISO 8601 trial end datetime. |
current_period_start | string|null | ISO 8601 current period start. |
current_period_end | string|null | ISO 8601 current period end. |
ends_at | string|null | ISO 8601 datetime when the subscription ends (set on cancellation). |
canceled_at | string|null | ISO 8601 cancellation datetime. |
paused_at | string|null | ISO 8601 pause datetime. |
created_at | string | ISO 8601 creation datetime. |
updated_at | string | ISO 8601 last update datetime. |
Invoices
All invoice endpoints are scoped to the token owner.List invoices
GET
Returns a paginated list of the token owner’s invoices, newest first.
Response /invoices200 OK:
Get an invoice
GET
Returns a single invoice. Returns /invoices/{id}404 if the invoice does not belong to the token owner.
Invoice object
| Field | Type | Description |
|---|---|---|
id | integer | Unique invoice identifier. |
subscription_id | integer|null | Associated subscription ID. |
gateway | string | Payment gateway driver name. |
gateway_id | string|null | Gateway-specific invoice identifier. |
number | string|null | Human-readable invoice number. |
status | string | Invoice status: open, paid, failed, refunded, or disputed. |
currency | string | ISO 4217 currency code. |
subtotal | integer | Subtotal in minor currency units. |
tax | integer | Tax amount in minor currency units. |
discount | integer | Discount amount in minor currency units. |
total | integer | Total amount in minor currency units. |
refunded_amount | integer | Total refunded in minor currency units. |
pdf_url | string|null | URL to download the invoice PDF. |
due_at | string|null | ISO 8601 due date. |
paid_at | string|null | ISO 8601 payment datetime. |
created_at | string | ISO 8601 creation datetime. |
updated_at | string | ISO 8601 last update datetime. |
Payment methods
All payment method endpoints are scoped to the token owner.List payment methods
GET
Returns all payment methods for the token owner, with default methods listed first.
Response /payment-methods200 OK:
Delete a payment method
DELETE
Detaches the payment method from the gateway and deletes the local record.
Response /payment-methods/{id}204 No Content
Error responses:
| Status | Description |
|---|---|
404 | Payment method not found or does not belong to the token owner. |
Set default payment method
POST
Sets the specified payment method as the default for its gateway.
Response /payment-methods/{id}/default200 OK — returns the updated payment method object.
Error responses:
| Status | Description |
|---|---|
404 | Payment method not found or does not belong to the token owner. |
Payment method object
| Field | Type | Description |
|---|---|---|
id | integer | Unique payment method identifier. |
gateway | string | Payment gateway driver name. |
gateway_id | string|null | Gateway-specific payment method identifier. |
type | string|null | Payment method type (e.g., card, paypal). |
brand | string|null | Card brand (e.g., visa, mastercard). |
last_four | string|null | Last four digits of the card number. |
exp_month | integer|null | Card expiration month. |
exp_year | integer|null | Card expiration year. |
is_default | boolean | Whether this is the default payment method. |
created_at | string | ISO 8601 creation datetime. |
Error responses
All error responses follow a consistent format:| Status code | Description |
|---|---|
401 Unauthorized | Missing, invalid, or expired bearer token. |
403 Forbidden | Token lacks the required ability. |
404 Not Found | Resource not found or not owned by the token owner. |
422 Unprocessable Entity | Validation failure or business logic error (e.g., invalid state transition). |