Skip to main content

Plan CRUD

The Public API exposes operations on the plan entity. A plan is the pricing template applied to a product; it is referenced by planId on subscriptions and one-time orders.

For the concept (categories of plans, the relationship to products), see Products and plans.

Create a plan

curl -X POST \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/plans" \
-H 'Content-Type: application/json' \
-H "Authorization: ApiKey ${API_KEY}" \
-d '{
"name": "Monthly Pro",
"currency": "USD",
"productId": "prod_xxx",
"pricing": {
"price": 29,
"formula": "fixed-fee"
},
"description": "Monthly Pro subscription",
"isActive": true,
"isTrialOnly": false
}'

Request fields

FieldNotes
nameDisplay name of the plan.
currencyCurrencyCodesEnum (USD, EUR, etc.).
productIdThe product this plan applies to.
pricingObject with price and formula (fixed-fee, flat-rate, tiered, volume, stairstep). See Pricing.
descriptionPlain-text description.
richDescriptionLong-form description.
isActivefalse hides the plan from new subscriptions but does not affect existing ones.
isTrialOnlytrue for trial-only plans (no recurring cadence after the trial).

Advanced fields

These fields are present on the plan schema and accepted by the API. Behavior of productOptions and recognition is implementation-specific — confirm before relying on them.

FieldNotes
productOptionsFree-form object. Defined as an empty schema in the API spec — verify the expected shape with the engineering team before use.
currencySignString. The display sign for currency (for example, $).
setupObject with approvalLink and price. Setup fee or approval URL applied on the first charge.
revisionNumber. Internal revision marker.

List plans

curl -X GET \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/plans?limit=20&offset=0&sortBy=createdAt&sortDirection=desc" \
-H "Authorization: ApiKey ${API_KEY}"
Query parameterTypeNotes
limitinteger 0–100, default 20Pagination page size.
offsetinteger ≥0Pagination offset.
sortByenumcreatedAt or updatedAt.
sortDirectionenumasc or desc.
searchstringFree-text search.
updatedFrom / updatedTodate-timeFilter by last-update timestamp range.

Response: paginated list with { type: "list", totalCount, paginationMeta, data: [Plan, ...] }.

Retrieve a plan

curl -X GET \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/plans/${PLAN_ID}" \
-H "Authorization: ApiKey ${API_KEY}"

Upsert a plan

Create the plan at the given planId if it does not exist, or replace the full resource if it does. The API does not expose a separate PATCH endpoint — use Create (POST) for new plans and Upsert (PUT) when you need to replace an existing one in full.

curl -X PUT \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/plans/${PLAN_ID}" \
-H 'Content-Type: application/json' \
-H "Authorization: ApiKey ${API_KEY}" \
-d '{
"name": "Updated Monthly Pro",
"currency": "USD",
"productId": "prod_xxx",
"pricing": {
"price": 39,
"formula": "fixed-fee"
},
"description": "Updated plan"
}'

Body fields are the same as Create. Returns 201 Plan upserted.

To move customers to different pricing, see Upgrade and downgrade.

Delete a plan

curl -X DELETE \
"https://staging-api.payments.ai/v1/public-api/organizations/${ORGANIZATION_ID}/plans/${PLAN_ID}" \
-H "Authorization: ApiKey ${API_KEY}"

Returns 204 on success.

May return 409 Conflict with a generic message ("Conflict with the current state of the target resource"). The exact condition that triggers 409 on plan deletion is not documented in the API spec — verify with the engineering team if you hit it in practice.