BillStack Docs

Products & Prices

Manage products and their pricing tiers

Products

All product endpoints are scoped to a project:

/api/billstack/teams/{teamId}/projects/{projectId}/products

List Products

GET /products?activeOnly=true
ParameterTypeDefaultDescription
activeOnlybooleantrueOnly return active products
curl "https://your-billstack.com/.../products?activeOnly=true" \
  -H "Authorization: Bearer bs_..."

Response:

{
  "products": [
    {
      "id": "pp_e5f6g7h8",
      "name": "Pro Plan",
      "description": "Full access to all features",
      "isActive": true,
      "stripeProductId": "prod_xxx",
      "metadata": {},
      "projectId": "proj_abc123",
      "createdAt": "2026-03-30T12:00:00Z"
    }
  ]
}

Auth: Read access (session or API key with products:read).


Create Product

POST /products
FieldTypeRequiredDescription
namestringYesProduct name
descriptionstringNoProduct description
metadataobjectNoArbitrary key-value pairs
curl -X POST "https://your-billstack.com/.../products" \
  -H "Authorization: Bearer bs_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pro Plan",
    "description": "Full access to all features"
  }'

Response (201):

{
  "product": {
    "id": "pp_e5f6g7h8",
    "name": "Pro Plan",
    "description": "Full access to all features",
    "isActive": true,
    "stripeProductId": "prod_xxx",
    "metadata": {},
    "projectId": "proj_abc123",
    "createdAt": "2026-03-30T12:00:00Z"
  }
}

Creates the product in both Stripe and BillStack.

Auth: Write access (session or API key with products:write).


Get Product

GET /products/{productId}
curl "https://your-billstack.com/.../products/pp_e5f6g7h8" \
  -H "Authorization: Bearer bs_..."

Auth: Read access.


Update Product

PATCH /products/{productId}
FieldTypeDescription
namestringNew product name
descriptionstringNew description
isActivebooleanActivate or deactivate
metadataobjectNew metadata
curl -X PATCH "https://your-billstack.com/.../products/pp_e5f6g7h8" \
  -H "Authorization: Bearer bs_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "Pro Plan v2" }'

Auth: Write access.


Delete Product

DELETE /products/{productId}

Archives the product in Stripe and removes it from the BillStack database.

curl -X DELETE "https://your-billstack.com/.../products/pp_e5f6g7h8" \
  -H "Authorization: Bearer bs_..."

Auth: Write access.


Prices

Price endpoints are also scoped to a project:

/api/billstack/teams/{teamId}/projects/{projectId}/prices

List Prices

GET /prices?activeOnly=true&productId=pp_xxx
ParameterTypeDefaultDescription
activeOnlybooleantrueOnly return active prices
productIdstringFilter by BillStack product ID
curl "https://your-billstack.com/.../prices?productId=pp_e5f6g7h8" \
  -H "Authorization: Bearer bs_..."

Response:

{
  "prices": [
    {
      "id": "pri_i9j0k1l2",
      "productId": "pp_e5f6g7h8",
      "unitAmount": 2999,
      "currency": "usd",
      "type": "recurring",
      "interval": "month",
      "intervalCount": 1,
      "isActive": true,
      "stripePriceId": "price_xxx",
      "metadata": {},
      "createdAt": "2026-03-30T12:00:00Z"
    }
  ]
}

Auth: Read access.


Create Price

POST /prices
FieldTypeRequiredDescription
productIdstringYesBillStack product ID (pp_...)
unitAmountnumberYesAmount in cents (e.g., 2999 = $29.99)
currencystringYesThree-letter currency code (usd, eur, etc.)
typestringNorecurring (default) or one_time
intervalstringNoday, week, month, or year (required for recurring)
intervalCountnumberNoNumber of intervals between billings (default: 1)
metadataobjectNoArbitrary key-value pairs
curl -X POST "https://your-billstack.com/.../prices" \
  -H "Authorization: Bearer bs_..." \
  -H "Content-Type: application/json" \
  -d '{
    "productId": "pp_e5f6g7h8",
    "unitAmount": 2999,
    "currency": "usd",
    "type": "recurring",
    "interval": "month",
    "intervalCount": 1
  }'

Response (201):

{
  "price": {
    "id": "pri_i9j0k1l2",
    "productId": "pp_e5f6g7h8",
    "unitAmount": 2999,
    "currency": "usd",
    "type": "recurring",
    "interval": "month",
    "intervalCount": 1,
    "isActive": true,
    "stripePriceId": "price_xxx",
    "createdAt": "2026-03-30T12:00:00Z"
  }
}

Auth: Write access.


Get Price

GET /prices/{priceId}
curl "https://your-billstack.com/.../prices/pri_i9j0k1l2" \
  -H "Authorization: Bearer bs_..."

Auth: Read access.


Update Price

PATCH /prices/{priceId}
FieldTypeDescription
isActivebooleanActivate or deactivate the price
metadataobjectNew metadata

Only isActive and metadata can be updated. Stripe does not allow changing the amount or interval of an existing price — create a new price instead.

curl -X PATCH "https://your-billstack.com/.../prices/pri_i9j0k1l2" \
  -H "Authorization: Bearer bs_..." \
  -H "Content-Type: application/json" \
  -d '{ "isActive": false }'

Auth: Write access.


Delete Price

DELETE /prices/{priceId}

Deactivates the price in Stripe and removes it from the BillStack database. Existing subscriptions using this price are not affected.

curl -X DELETE "https://your-billstack.com/.../prices/pri_i9j0k1l2" \
  -H "Authorization: Bearer bs_..."

Auth: Write access.

On this page