Vatly
Api Reference

Subscription Plans

On this page, we'll dive into the different subscription plan endpoints you can use to query your plans programmatically.

The subscription plan model

The subscription plan model contains all the information about the subscription plans you create, including the name, description, price, and billing interval.

Properties

NameTypeDescription
idstringUnique identifier for the subscription plan (always starts with subscription_plan_).
resourcestringThe resource type. Always subscription_plan.
testmodebooleanWhether this plan is in test mode.
namestringDisplay name of the plan.
descriptionstringDetailed description of the plan.
basePriceMoneyPrice per billing interval. A Money object with value (decimal string) and currency (ISO 4217 code). Interpretation depends on taxBehavior: when exclusive, basePrice is the net amount and tax is added at checkout; when inclusive, basePrice already includes tax and the net is back-computed from the buyer's jurisdiction.
taxBehaviorstringWhether basePrice is tax-exclusive (exclusive, the B2B convention) or tax-inclusive (inclusive, the B2C convention). Immutable after plan creation — create a new plan for the other mode. A checkout may not mix products with different taxBehavior values.
intervalstringBilling interval unit. Can be day, week, month, or year.
intervalCountintegerNumber of interval units between billing cycles. For example, interval: month with intervalCount: 3 bills every 3 months.
productTypestringWhat kind of product this plan sells. Always saas — an e-book is a one-time purchase, so sell it as a one-off product instead. Set when the plan is created.
statusstringCurrent status of the plan. Can be active (plan is active and can be subscribed to), pending (plan is awaiting approval), or rejected (plan has been rejected).
archivedAtstring | nullWhen this plan was archived (ISO 8601), or null while it is open to new business. Always present. An archived plan is hidden from GET /v1/subscription-plans, refused by POST /v1/checkouts, and cannot be switched to from PATCH /v1/subscriptions/:id.
pendingUpdatesobject | nullThe changes that will take effect once a submitted update is approved, or null when there is no pending update. Only the fields that actually differ from the live plan are present.
updateStatusstring | nullLifecycle of a pending update, or null when there is none. Can be pending (an update was submitted and is awaiting review) or reviewing (the update is being reviewed).
createdAtstringWhen this plan was created (ISO 8601 format).
linksobjectHATEOAS links to related resources. Contains self link.

List all subscription plans

GET /v1/subscription-plans

This endpoint retrieves a paginated list of all subscription plans. Only plans with active status can be used in checkouts. Archived plans are excluded unless includeArchived=true is passed.

Optional query parameters

NameTypeDescription
limitintegerThe number of subscription plans to return (default: 10, max: 100).
startingAfterstringA cursor for use in pagination. Returns results after this plan ID.
endingBeforestringA cursor for use in pagination. Returns results before this plan ID.
includeArchivedbooleanInclude archived plans in the listing. Archived plans are hidden by default because they cannot be sold; set this to true to see them alongside the live ones (tell them apart by the non-null archivedAt). Default: false.
curl -G https://api.vatly.com/v1/subscription-plans \
  -H "Authorization: Bearer live_your_api_key_here" \
  -d limit=10

Create a subscription plan

POST /v1/subscription-plans

Creates a new subscription plan for the authenticated merchant, in the testmode determined from the API token.

A plan created with a live_ token starts in pending status and must be approved by Vatly before it can be used in checkouts — the same review that applies to plans created in the dashboard. A plan created with a test_ token is auto-approved (active) so you can trial checkout immediately.

Constraints:

  • productType must be saas — e-books are one-off purchases and cannot be sold on a recurring basis.
  • The day interval is sandbox-only; live plans support week, month, and year.
  • intervalCount is bounded per unit: up to 365 days, 52 weeks, or 12 months. year always bills once per year (intervalCount is ignored).

Required attributes

NameTypeDescription
namestringDisplay name of the plan (3–255 characters).
descriptionstringDetailed description of the plan.
basePriceMoneyPrice per billing interval. A Money object with value (decimal string) and currency (ISO 4217 code).
productTypestringTax product classification. Must be saas.
intervalstringBilling interval unit. One of day (sandbox-only), week, month, or year.
intervalCountintegerNumber of interval units between billing cycles (at least 1).

Optional attributes

NameTypeDescription
taxBehaviorstringWhether basePrice is tax-exclusive (exclusive, the B2B convention) or tax-inclusive (inclusive, the B2C convention). Defaults to exclusive. Immutable after plan creation — create a new plan for the other mode.
curl https://api.vatly.com/v1/subscription-plans \
  -H "Authorization: Bearer live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pro Monthly",
    "description": "Full access to all Pro features, billed monthly",
    "basePrice": { "value": "29.00", "currency": "EUR" },
    "productType": "saas",
    "interval": "month",
    "intervalCount": 1
  }'

Retrieve a subscription plan

GET /v1/subscription-plans/:id

This endpoint retrieves a specific subscription plan by its ID.

URL parameters

NameTypeDescription
idstringThe ID of the subscription plan to retrieve.
curl https://api.vatly.com/v1/subscription-plans/subscription_plan_Bm7xNvPwKr3YjTgHcZaE \
  -H "Authorization: Bearer live_your_api_key_here"

Update a subscription plan

PATCH /v1/subscription-plans/:id

Submits an update to a live subscription plan. Because plans drive VAT-bearing recurring sales, the change is held as a pending update and reviewed by Vatly before it takes effect (updateStatus moves pendingreviewing → applied). In test mode the update is approved automatically.

Each request is the complete set of changes relative to the current live plan, and must contain at least one field. Fields equal to the live value are ignored, and a request that nets to no change clears any pending update. A new request replaces the not-yet-reviewed one; while an update is being reviewed, further requests return 409. Changing the interval on a plan that has ever been used by a subscription — active or not — also returns 409. The price stays changeable.

The submitted change is surfaced on the plan resource as pendingUpdates (only the fields that differ), with updateStatus tracking the review. Approval is signalled by the subscriptionPlan.update_submitted, subscriptionPlan.update_approved, and subscriptionPlan.update_rejected webhook events.

URL parameters

NameTypeDescription
idstringThe ID of the subscription plan to update.

Optional attributes

At least one field must be provided.

NameTypeDescription
namestringNew display name of the plan (3–255 characters).
descriptionstringNew description of the plan.
basePriceMoneyNew price per billing interval. A Money object with value (decimal string) and currency (ISO 4217 code).
productTypestringTax product classification. Must be saas.
intervalstringNew billing interval unit. One of day (sandbox-only), week, month, or year.
intervalCountintegerNumber of interval units between billing cycles (at least 1). Required when interval is provided.
curl -X PATCH https://api.vatly.com/v1/subscription-plans/subscription_plan_Bm7xNvPwKr3YjTgHcZaE \
  -H "Authorization: Bearer live_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pro Weekly",
    "basePrice": { "value": "9.00", "currency": "EUR" },
    "interval": "week",
    "intervalCount": 1
  }'

Archive a subscription plan

POST /v1/subscription-plans/:id/archive

Closes the plan to new business. It is hidden from GET /v1/subscription-plans (unless includeArchived=true), refused by POST /v1/checkouts, and can no longer be switched to from PATCH /v1/subscriptions/:id.

Subscribers already on the plan are deliberately untouched: a subscription snapshots its plan at signup and renews off that snapshot, so archiving never cancels anyone or changes what they are billed. To end a subscription, cancel it with DELETE /v1/subscriptions/:id.

Likewise a checkout created before the plan was archived snapshots its product data at creation time and can still be completed. Archiving applies to new checkouts only.

Nothing is deleted — the plan remains readable by id, now carrying a non-null archivedAt. Repeating the request is a no-op that returns 204 and does not move archivedAt. Reverse it by unarchiving the plan.

URL parameters

NameTypeDescription
idstringThe ID of the subscription plan to archive.
curl -X POST https://api.vatly.com/v1/subscription-plans/subscription_plan_Bm7xNvPwKr3YjTgHcZaE/archive \
  -H "Authorization: Bearer live_your_api_key_here"

Returns 204 No Content on success (or if the plan was already archived).


Unarchive a subscription plan

DELETE /v1/subscription-plans/:id/archive

Re-opens an archived plan to new business: it reappears in GET /v1/subscription-plans and can be added to checkouts and switched to again. Calling it on a plan that is not archived is a no-op. The refreshed plan is returned in the response body.

URL parameters

NameTypeDescription
idstringThe ID of the subscription plan to unarchive.
curl -X DELETE https://api.vatly.com/v1/subscription-plans/subscription_plan_Wt5mNvBxKw7YcZaEjLhR/archive \
  -H "Authorization: Bearer live_your_api_key_here"
Copyright © 2026