GET /api/v1/apps/:appUuid/tenants/:tenantUuid/payment-providers/:paymentProvider/invoices
Lists local Userdocks invoice records for one app, one tenant, and one payment provider.
This endpoint returns Userdocks-processed billing records from subscriptions and one-time payments. It does not list every draft, open, or externally created invoice from Stripe or Mollie.
Source route file:
src/api/routes/external/private/apiKey/app/tenants/paymentProviders/invoices/get.ts
Request Method
GET
Base URL
https://api.userdocks.local:5000
Endpoint
/api/v1/apps/:appUuid/tenants/:tenantUuid/payment-providers/:paymentProvider/invoices
Path Variables
| Variable | Type | Required | Description |
|---|---|---|---|
appUuid | string | true | App UUID. Must match the x-client-id. |
tenantUuid | string | true | Tenant UUID whose invoices are returned. |
paymentProvider | string | true | Use stripe or mollie. |
Query Parameters
| Variable | Type | Required | Default | Description |
|---|---|---|---|---|
page | number | false | 0 | Zero-based page number. |
limit | number | false | 10 | Number of invoice records to return. |
HTTP Headers
| Variable | Type | Required | Description |
|---|---|---|---|
x-api-key | string | true | Read API key value for the app. |
x-client-id | string | true | Must match :appUuid path variable. |
x-api-key-type | string | true | Use read. |
Request Body
No request body.
Successful Response
Success status code(s): 200.
{
"kind": "invoices",
"totalItems": 2,
"itemsLength": 2,
"items": [
{
"uuid": "otp_11111111-1111-1111-1111-111111111111",
"type": "oneTimePayment",
"tenantUuid": "tenant_11111111-1111-1111-1111-111111111111",
"paymentProviderUuid": "pp_11111111-1111-1111-1111-111111111111",
"productUuid": "product_11111111-1111-1111-1111-111111111111",
"productPriceUuid": null,
"providerPriceId": "price_1AbCdEf",
"unitAmount": 1300,
"currency": "EUR",
"quantity": 1,
"description": "Pro Plan — September",
"recurringInterval": null,
"recurringIntervalCount": null,
"invoiceLineItemId": "il_12345",
"taxRateUuid": "tax_11111111-1111-1111-1111-111111111111",
"invoiceId": "in_12345",
"invoiceUrl": "https://invoice.example.com/in_12345",
"paymentId": "pay_12345",
"paymentUrl": null,
"subscriptionId": null,
"paidFrom": null,
"paidUntil": null,
"status": null,
"changeType": null,
"startedAt": null,
"endedAt": null,
"transitionInvoiceId": null,
"transitionInvoiceUrl": null,
"transitionAmountPaid": null,
"transitionCurrency": null,
"units": 1,
"isPromotion": false,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z"
},
{
"uuid": "subrow_11111111-1111-1111-1111-111111111111",
"type": "subscription",
"tenantUuid": "tenant_11111111-1111-1111-1111-111111111111",
"paymentProviderUuid": "pp_11111111-1111-1111-1111-111111111111",
"productUuid": "product_11111111-1111-1111-1111-111111111111",
"productPriceUuid": "price_11111111-1111-1111-1111-111111111111",
"providerPriceId": "price_legacy123",
"unitAmount": 999,
"currency": "USD",
"quantity": 1,
"description": "Legacy monthly plan",
"recurringInterval": "month",
"recurringIntervalCount": 1,
"invoiceLineItemId": null,
"taxRateUuid": "tax_11111111-1111-1111-1111-111111111111",
"invoiceId": "in_67890",
"invoiceUrl": "https://invoice.example.com/in_67890",
"paymentId": null,
"paymentUrl": null,
"subscriptionId": "sub_12345",
"paidFrom": "2026-01-01T00:00:00.000Z",
"paidUntil": "2026-02-01T00:00:00.000Z",
"status": "active",
"changeType": "started",
"startedAt": "2026-01-01T00:00:00.000Z",
"endedAt": null,
"transitionInvoiceId": "in_67890",
"transitionInvoiceUrl": "https://invoice.example.com/in_67890",
"transitionAmountPaid": 999,
"transitionCurrency": "usd",
"units": null,
"isPromotion": false,
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z"
}
]
}
When no local invoice records exist, the endpoint still returns 200.
{
"kind": "invoices",
"totalItems": 0,
"itemsLength": 0,
"items": []
}
Provider Notes
- Stripe and Mollie use the same endpoint shape.
- Results are scoped to the app, tenant, and payment provider from the path.
- Results are ordered by
createdAtdescending. - Inline records have
productPriceUuid: null. Snapshot amount, currency, quantity, description, provider price ID, and cadence fields remain stable even if the product or a legacy price later changes. - Multi-line one-time invoices return one item per line. Those items share the
same
invoiceIdand have distinctinvoiceLineItemIdvalues. - Subscription records represent plan periods, not individual renewal payments.
Their transition fields are immutable;
invoiceId,invoiceUrl,paidFrom, andpaidUntildescribe the latest successful billing cycle. - For Mollie,
invoiceIdandinvoiceUrlmay refer to a Mollie sales invoice when one was created, or to the payment document URL fallback stored by Userdocks. - This endpoint reads only local Userdocks billing records. Use provider dashboards or provider APIs when you need draft/open invoices that Userdocks has not processed.
Error Responses
| HTTP Status | Example Error |
|---|---|
400 | {"errors":[{"validation":"error","code":"[E4000]","message":"Bad Request / validation error"}]} |
401 | {"errors":[{"validation":"error","code":"[E4010]","message":"Unauthorized Token or API key"}]} |
401 | {"errors":[{"validation":"error","code":"[E4011]","message":"Unauthorized API key type"}]} |
403 | {"errors":[{"validation":"error","code":"[E4030]","message":"App Is Disabled"}]} |
500 | {"errors":[{"validation":"error","code":"[E0000]","message":"Internal Server Error"}]} |
Example
const url =
'https://api.userdocks.local:5000/api/v1/apps/appUuid-value/tenants/tenantUuid-value/payment-providers/stripe/invoices?page=0&limit=10';
const response = await fetch(url, {
method: 'GET',
headers: {
'x-api-key': '<api-key>',
'x-client-id': 'appUuid-value',
'x-api-key-type': 'read',
},
});
const data = await response.json();
console.log(response.status, data);