Customer Invoices
Every payment Throttle processes — a one-time card capture, a Net-N issuance, or a recurring subscription charge — lands in one unified, cursor-paginated invoice list. Your buyers see a single consistent view regardless of how they originally paid.
@usethrottle/invoices/server proxy which resolves the authenticated buyer's identity and forwards only their own invoices. See React Package for the setup.One list, three payment types
Throttle invoices are payment-source agnostic. The same GET /api/v1/invoices endpoint returns all three payment types in a single paginated response, ordered by creation time (newest first by default).
- Single-time card captures (
sourceType: "order") — generated when a buyer completes a one-time checkout session with a card. The invoice is markedpaidimmediately on capture. - Net-N issuances (
sourceType: "net30") — issued at checkout time with a futuredueAttimestamp (N days out). Status starts asopenand transitions topaidonce the merchant marks it paid or a payment is received. - Subscription charges (
sourceType: "subscription") — generated on the initial subscribe and on every renewal. The invoice carriesperiodStartandperiodEndso buyers can see exactly which billing period each charge covers.
Use the type query parameter to filter by source type if your UI needs to show a subset.
Auth and trust model
The Throttle invoice API is a merchant-facing API: every call requires an sk_* secret key. Buyers cannot authenticate directly. The recommended pattern is a thin backend proxy:
- Your backend authenticates the buyer (Clerk, NextAuth, session cookie, etc.) and resolves their internal user id.
- The proxy calls
GET /api/v1/customers/by-external/:externalIdwith your secret key to resolve the ThrottlecustomerId. - All reads are forwarded as
GET /api/v1/customers/:customerId/invoicesso the buyer only ever sees their own invoices.
// app/api/throttle/invoices/[...path]/route.ts
import { createInvoiceProxyHandler } from '@usethrottle/invoices/server';
import { auth } from '@/lib/auth';
const handler = createInvoiceProxyHandler({
apiKey: process.env.THROTTLE_SECRET_KEY!,
async getCustomerId(request) {
// Return your internal customer / user id.
// The proxy resolves it to a Throttle customerId via
// GET /api/v1/customers/by-external/:externalId.
const user = await auth();
return user?.id ?? null;
},
});
export { handler as GET };The @usethrottle/invoices/server package ships this proxy handler ready to mount in any framework that accepts a standard Request / Response interface (Next.js App Router, Hono, Remix, etc.).
Pagination
Invoice list endpoints return a cursor-paginated envelope. Pass the returned meta.pagination.cursor as the cursor query parameter to fetch the next page. When meta.pagination.hasMore is false there are no further pages.
// Cursor-paginated response envelope
{
"data": [
{
"id": "inv_abc123",
"number": "INV-sprinter-001",
"status": "paid",
"sourceType": "order",
"currency": "USD",
"subtotal": 4999,
"taxTotal": 400,
"shippingTotal": 699,
"discountTotal": 0,
"total": 6098,
"amountRefunded": 0,
"issuedAt": "2026-06-01T10:00:00Z",
"dueAt": null,
"periodStart": null,
"periodEnd": null,
"createdAt": "2026-06-01T10:00:00Z"
}
],
"meta": {
"pagination": {
"cursor": "eyJpZCI6Imlu...",
"hasMore": true
}
}
}Per-application branding
Every invoice PDF is rendered with the application's configured logo and brand color. Set these on your application via the dashboard Settings → Branding panel or via PUT /api/v1/embed-config. The PDF renderer reads logoUrl and brandColor from application_env_settings at render time, so changes apply to invoices downloaded after the update (not retroactively).
Refund behavior
When a payment is refunded via the dashboard or API, the corresponding invoice status transitions automatically:
- Full refund — status becomes
refunded; theamountRefundedfield reflects the full invoice total. - Partial refund — status becomes
partially_refunded; theamountRefundedfield shows the refunded portion.
The re-rendered PDF shows the refunded amount and updated status. Buyers who download after a refund automatically see the current state.
REST routes quick reference
# Merchant API: list all invoices (all source types) for the application
curl -G https://api.usethrottle.dev/api/v1/invoices \
-H "x-api-key: $THROTTLE_SECRET_KEY" \
--data-urlencode "limit=25" \
--data-urlencode "sort=desc"
# Merchant API: list invoices for a specific customer
curl https://api.usethrottle.dev/api/v1/customers/cus_xyz/invoices \
-H "x-api-key: $THROTTLE_SECRET_KEY"# Get a signed PDF download URL (JSON mode)
curl "https://api.usethrottle.dev/api/v1/invoices/inv_abc123/download?format=json" \
-H "x-api-key: $THROTTLE_SECRET_KEY"
# Redirect directly to PDF (default)
curl -L "https://api.usethrottle.dev/api/v1/invoices/inv_abc123/download" \
-H "x-api-key: $THROTTLE_SECRET_KEY" \
--output invoice.pdfAll routes require invoices:read scope on the API key. The download route returns a 302 redirect to a short-lived signed S3 URL by default; pass ?format=json to get the URL as a JSON response instead.
{
"data": {
"url": "https://s3.us-east-1.amazonaws.com/…signed-url"
}
}Pages in this section
- React Package —
@usethrottle/invoiceshooks, provider, and server proxy reference.