Subscriptions and Product Quantities

Use subscription metadata to discover every product your team can adjust. Voice Clone Slots are used below as one example; the same workflow applies to any product marked adjustable by the API.

Set the credentials and base URL used in the examples:

$export RESEMBLE_API_KEY="your_api_key"
$export BILLING_API_BASE="https://app.resemble.ai/billing/api/v1"

Discover plans

Plan discovery is public. List active self-serve plans before changing a subscription:

$curl "$BILLING_API_BASE/plans"

Retrieve one plan using its returned slug:

$curl "$BILLING_API_BASE/plans/flex"

A plan’s products array describes included quantities, prices, and plan-specific limits. Do not maintain a hard-coded catalog of adjustable product slugs; products and rules can vary by plan.

Find the current subscription

$curl "$BILLING_API_BASE/subscription" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY"

The response contains subscription: null when the team has no customer-visible active subscription. Otherwise, subscription.subscription_items contains the current product quantities and consumption.

Find every adjustable product

An item is adjustable when both of these conditions are true:

  • product.category is subscription.
  • plan_product.allow_additional_usage is true.

List the team’s adjustable products and their effective constraints with jq:

$curl --silent "$BILLING_API_BASE/subscription" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> | jq '
> .subscription.subscription_items[]
> | select(
> .product.category == "subscription"
> and .plan_product.allow_additional_usage == true
> )
> | {
> name: .product.name,
> slug: .product.slug,
> quantity,
> consumed_quantity,
> included_quantity: .plan_product.included_quantity,
> minimum: .plan_product.min_usage_per_period,
> maximum: .plan_product.max_usage_per_period,
> locked_rate_per_unit_cents: .rate_per_unit_cents,
> current_rate_per_unit_cents
> }
> '

Use the returned values as the source of truth:

  • quantity is the current absolute quantity.
  • consumed_quantity is currently in use and is the lowest quantity you can select.
  • included_quantity is supplied by the plan.
  • min_usage_per_period and max_usage_per_period are the plan’s allowed bounds. A null maximum means there is no plan-specific maximum.
  • rate_per_unit_cents is the subscription item’s locked-in rate; current_rate_per_unit_cents is the current catalog rate.

Update product quantities

PATCH /subscription/products accepts one or more changes in a single request. Every new_quantity is the desired absolute total, not an amount to add or subtract.

$curl --request PATCH "$BILLING_API_BASE/subscription/products" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> -H 'Content-Type: application/json' \
> --data '{
> "changes": [
> {
> "product_slug": "voice_clone",
> "new_quantity": 5
> },
> {
> "product_slug": "another_adjustable_product",
> "new_quantity": 10
> }
> ]
> }'

The API validates every change before applying the batch:

  • The product must exist on the current plan.
  • Only subscription products with allow_additional_usage: true can change.
  • The new quantity cannot be negative or fall outside the returned plan bounds.
  • The new quantity cannot be less than consumed_quantity. Remove the resources using those slots first.

Replace another_adjustable_product with a product slug returned by the adjustable-product query. The Voice Clone example uses the same batch operation as every other adjustable product.

Example: increase Voice Clone Slots

First, find the existing Voice Clone quantity rather than assuming it:

$curl --silent "$BILLING_API_BASE/subscription" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> | jq '.subscription.subscription_items[] | select(.product.slug == "voice_clone") | {quantity, consumed_quantity, plan_product}'

If the current quantity is 3 and the desired total is 5, send new_quantity: 5:

$curl --request PATCH "$BILLING_API_BASE/subscription/products" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> -H 'Content-Type: application/json' \
> --data '{
> "changes": [
> {
> "product_slug": "voice_clone",
> "new_quantity": 5
> }
> ]
> }'

This sets the total to five Voice Clone Slots. It does not add five slots. Use the same process for every product returned by the adjustable-product filter.

Complete additional payment authentication

A prorated quantity or plan change can require additional payment authentication. In that case the mutation returns 402 Payment Required:

1{
2 "requires_action": true,
3 "client_secret": "pi_..._secret_..."
4}

Send the client_secret to a secure browser payment flow so the customer can complete authentication. After authentication succeeds, send the completed payment intent ID from your server:

$curl --request POST "$BILLING_API_BASE/subscription/confirm_payment" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> -H 'Content-Type: application/json' \
> --data '{
> "payment_intent_id": "pi_123456789"
> }'

The response contains the synchronized subscription. Keep the API key on your server while the customer completes payment authentication.

Change plans

Change to another active plan. The change is prorated and can return the same 402 flow described above:

$curl --request PATCH "$BILLING_API_BASE/subscription/change_plan" \
> -H "Authorization: Bearer $RESEMBLE_API_KEY" \
> -H 'Content-Type: application/json' \
> --data '{
> "plan_slug": "PLAN_SLUG_FROM_GET_PLANS",
> "product_quantities": {
> "voice_clone": 5
> }
> }'

Custom enterprise plans cannot be changed through self-service endpoints. Contact Resemble support to manage them.

API reference