API Overview
Authentication, base URLs, error handling, and conventions for the BillStack REST API
Base URL
All BillStack API endpoints follow this pattern:
https://your-billstack.com/api/billstack/teams/{teamId}/projects/{projectId}/...Team-level endpoints (Stripe connection, API keys) omit the /projects/{projectId} segment:
https://your-billstack.com/api/billstack/teams/{teamId}/...Authentication
BillStack supports two authentication methods:
API Key (for external SaaS apps)
Include your API key in the Authorization header:
curl https://your-billstack.com/api/billstack/teams/{teamId}/projects/{projectId}/customers \
-H "Authorization: Bearer bs_a1b2c3d4..."API keys are prefixed with bs_ and can be scoped to specific projects and permissions. See Create API Keys for details.
Session Cookie (for dashboard users)
Dashboard users authenticate via BetterAuth session cookies. This is handled automatically by the browser — no manual header is needed.
Team-level endpoints (Stripe connection, API key management) require session authentication only and cannot be accessed with API keys.
Request Format
- All request bodies must be JSON with
Content-Type: application/json - Query parameters use standard URL encoding
- IDs use BillStack prefixes (
pc_,pp_,pri_,ps_) — not raw Stripe IDs
Response Format
All responses return JSON. Successful responses include the resource directly:
{
"customer": {
"id": "pc_xxx",
"email": "jane@example.com",
"name": "Jane Doe",
"stripeCustomerId": "cus_xxx",
"createdAt": "2026-03-30T12:00:00Z"
}
}List responses include an array:
{
"customers": [
{ "id": "pc_xxx", "email": "jane@example.com" },
{ "id": "pc_yyy", "email": "john@example.com" }
]
}Error Responses
Errors return an appropriate HTTP status code with a JSON body:
{
"error": "Customer not found"
}| Status Code | Meaning |
|---|---|
400 | Bad request — invalid or missing parameters |
401 | Unauthorized — missing or invalid API key / session |
403 | Forbidden — insufficient permissions or scopes |
404 | Not found — resource doesn't exist or belongs to another project |
409 | Conflict — resource already exists (e.g., duplicate email) |
500 | Internal server error |
Pagination
List endpoints support pagination via query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Maximum items to return |
offset | number | 0 | Number of items to skip |
curl ".../customers?limit=25&offset=50" \
-H "Authorization: Bearer bs_..."ID Prefixes
| Resource | Prefix | Example |
|---|---|---|
| Customer | pc_ | pc_a1b2c3d4 |
| Product | pp_ | pp_e5f6g7h8 |
| Price | pri_ | pri_i9j0k1l2 |
| Subscription | ps_ | ps_m3n4o5p6 |
Each resource also stores its corresponding Stripe ID (e.g., stripeCustomerId, stripeProductId).
Endpoints
| Section | Endpoints |
|---|---|
| Customers | CRUD operations for project-scoped customers |
| Products & Prices | Manage products and their pricing |
| Subscriptions | List, view, cancel, and resume subscriptions |
| Checkout | Create Stripe Checkout sessions |
| Portal | Generate customer portal access tokens |
| Analytics | MRR, churn, customer growth, webhook stats |
| Referrals | Referral codes, application, and configuration |