Plans & Billing
How PodPDF charges for PDFs, how monthly subscriptions and one-off credits work together, and the endpoints that report your balance.
Two Ways to Pay
Every PDF costs $0.01, whichever way you pay. You can use either option, or both at once.
| Monthly subscription | One-off credit packs | |
|---|---|---|
| Plans | Starter: $20/month for 2,000 PDFs Business: $100/month for 10,000 PDFs | $10, $100, $300, $700, $1,000 or $1,500 |
| Cost per PDF | $0.01 | $0.01 |
| Renews | Every month until cancelled | Never — single payment |
| Unused balance | Resets on renewal, does not roll over | Never expires |
| If a subscription ends | Allowance is gone | Credits stay and keep working |
Subscriptions are optional. There is no free tier: an account stays pending, and conversion requests return 402 UPGRADE_REQUIRED, until it buys a credit pack or starts a subscription.
Current prices are on the pricing page.
Consumption Order
Each charge is taken from the first bucket that can cover it:
- Subscription allowance — while the subscription is active and the current billing period has not ended
- Free credits — if any were granted to your account
- One-off credits — your
credits_balance
So one-off credits act as overage: if your allowance runs out mid-month, requests keep working and are charged to your one-off credits until the next renewal.
A request is rejected with 403 INSUFFICIENT_CREDITS only when none of the buckets can cover it. For bulk jobs and background merge/split jobs, the check covers the whole job before it starts. See Error Handling.
Allowances Are Tracked in Dollars
The subscription allowance is stored in the same unit as credits_balance: dollars. A Starter allowance starts at 20, which is 2,000 PDFs at $0.01 each.
This means every operation is charged exactly as before, just from the allowance first:
- A PDF from
/quickjob,/longjob,/bulkjobor a template render deducts $0.01. - Merge and split operations deduct their normal operation cost, including page-band multipliers.
- Failed and skipped work is not charged.
subscription_pdfs_remaining is the same allowance expressed as PDFs: subscription_credits_remaining / price_per_pdf.
Renewal and Rollover
On each renewal the allowance is reset to the plan amount. Anything left from the previous period is not carried forward.
One-off credits are unaffected by renewals and never expire.
Changing or Cancelling
Subscriptions are managed in the dashboard under Plans & Credits:
| Action | When it takes effect | Effect on the allowance |
|---|---|---|
| Upgrade (Starter → Business) | Immediately, with a prorated charge for the rest of the period | Increases by the difference between the plans |
| Downgrade (Business → Starter) | At the next renewal | Unchanged until renewal, then reset to the lower amount |
| Cancel | At the end of the current billing period | Usable until the period ends, then removed |
| Resume | Immediately (undoes a scheduled cancel) | Unchanged |
| Update payment method | Through the customer portal | Unchanged |
When a subscription is cancelled, paused or ends, one-off credits remain in the account and keep working. API keys, templates and webhooks are not affected.
Billing Summary
GET /accounts/me/billing returns your balances. Like the other account endpoints, it requires a dashboard session token (Authorization: Bearer <cognito_id_token>), not an API key. See Authentication.
curl https://api.podpdf.com/accounts/me/billing \
-H "Authorization: Bearer <cognito_id_token>"
{
"billing": {
"plan_id": "paid-standard",
"plan_type": "paid",
"monthly_quota": null,
"credits_balance": 4.5,
"free_credits_remaining": 0,
"subscription_credits_remaining": 12.37,
"subscription_pdfs_remaining": 1237,
"subscription": {
"subscription_id": "sub_01j9x...",
"status": "active",
"name": "Starter",
"price_id": "pri_01j9x...",
"price": 20,
"monthly_pdfs": 2000,
"credits_remaining": 12.37,
"pdfs_remaining": 1237,
"period_start": "2026-09-01T10:15:00.000Z",
"period_end": "2026-10-01T10:15:00.000Z",
"active": true,
"scheduled_change": null
},
"total_pdf_count": 2763,
"total_amount": 27.63,
"price_per_pdf": 0.01
}
}
| Field | Type | Description |
|---|---|---|
credits_balance | number | One-off credit balance in USD |
free_credits_remaining | number | Remaining free credits |
subscription_credits_remaining | number | Usable subscription allowance in USD. 0 when there is no active subscription or the period has ended |
subscription_pdfs_remaining | number | The allowance expressed as PDFs |
subscription | object | null | The current subscription, or null if the account has no subscription |
total_pdf_count | number | All-time PDFs generated |
price_per_pdf | number | Price per PDF in USD |
The subscription Object
| Field | Type | Description |
|---|---|---|
subscription_id | string | Paddle subscription ID |
status | string | active, trialing, past_due, paused or canceled |
name | string | Plan name, such as Starter or Business |
price_id | string | Paddle price ID of the current plan |
price | number | Monthly price in USD |
monthly_pdfs | number | PDFs included each billing period |
credits_remaining | number | Same as subscription_credits_remaining |
pdfs_remaining | number | Same as subscription_pdfs_remaining |
period_start | string | Start of the current billing period (ISO 8601) |
period_end | string | End of the current billing period (ISO 8601) |
active | boolean | Whether the allowance is currently usable |
scheduled_change | object | null | A pending change, or null |
scheduled_change, when present:
{
"action": "downgrade",
"effective_at": "2026-10-01T10:15:00.000Z",
"price_id": "pri_01j9x...",
"name": "Starter",
"monthly_pdfs": 2000
}
action is cancel, pause or downgrade. price_id, name and monthly_pdfs are only included for a downgrade.
Subscription Endpoints
These endpoints back the dashboard's Plans & Credits page. Apart from the plan list, they require a dashboard session token; API keys are rejected.
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /accounts/me/subscription/plans | None (public) | Active plans: price_id, name, price, monthly_pdfs |
GET | /accounts/me/subscription | JWT | { "subscription": ... }, the same object as in the billing summary, or null |
POST | /accounts/me/subscription/cancel | JWT | Cancel at the end of the current billing period |
POST | /accounts/me/subscription/resume | JWT | Undo a scheduled cancellation |
POST | /accounts/me/subscription/change | JWT | Switch plan. Body: { "price_id": "pri_..." }. Returns 409 if there is no active subscription |
POST | /accounts/me/subscription/portal | JWT | Returns { "url": "..." } for the customer portal (payment method and invoices) |
New subscriptions are started through checkout in the dashboard, not through the API.
Insufficient Credits
When the allowance, free credits and one-off credits together cannot cover a request, the API returns 403 with the same code and action_required as before. The details now also include subscription_credits_remaining:
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits to generate PDF. Please purchase credits to continue.",
"details": {
"current_balance": 0.005,
"required_amount": 0.01,
"subscription_credits_remaining": 0,
"action_required": "purchase_credits"
}
}
}
current_balance is the one-off credit balance. To continue, buy a credit pack, upgrade your plan, or wait for your subscription to renew.