Skip to main content

POST /api/v1/apps/:appUuid/tenants/:tenantUuid/payment-providers/:paymentProvider/invoices

Creates a new invoices resource.

This endpoint documentation is generated from the current Fastify route implementation and should be treated as the implementation-level contract for this version of the API.

Source route file: src/api/routes/external/private/apiKey/app/tenants/paymentProviders/invoices/post.ts

Request Method​

POST

Base URL​

https://api.userdocks.local:5000

Endpoint​

/api/v1/apps/:appUuid/tenants/:tenantUuid/payment-providers/:paymentProvider/invoices

Path Variables​

VariableTypeRequiredDescription
appUuidstringtruePath variable from route pattern.
tenantUuidstringtruePath variable from route pattern.
paymentProviderstringtruePath variable from route pattern.

Query Parameters​

No query parameters.

HTTP Headers​

VariableTypeRequiredDescription
x-api-keystringtrueAPI key value for the app.
x-client-idstringtrueMust match :appUuid path variable.
x-api-key-typestringtrueUse read for GET and write for POST/PUT/DELETE.
Content-TypestringtrueUse application/json for JSON request bodies.

Request Body​

Schema reference: createInvoicesSchema

{
"tenantUuid": "11111111-1111-1111-1111-111111111111",
"lineItems": [
{
"productUuid": "22222222-2222-2222-2222-222222222222",
"unitAmount": 1300,
"currency": "EUR",
"quantity": 1,
"description": "Pro Plan — September",
"descriptionUnused": "Starter Plan credit",
"recurringInterval": "month",
"recurringIntervalCount": 1
}
],
"taxRateId": "txr_12345",
"type": "subscription"
}

Successful Response​

Success status code(s): 200.

For Stripe, the returned billing document is usually an invoice. For Mollie, the returned billing document is always a payment object/document, and type: "subscription" creates the recurring subscription only after the first payment succeeds and the Mollie webhook is processed.

{
"kind": "invoices",
"totalItems": 1,
"itemsLength": 1,
"items": [
{
"status": "open",
"providerObjectType": "payment",
"providerObjectId": "tr_12345",
"nextAction": {
"url": "https://checkout.mollie.com/pay/tr_12345"
},
"documentUrl": "https://my.mollie.com/dashboard/payments/tr_12345",
"providerResponse": {
"id": "tr_12345",
"status": "open",
"method": "creditcard",
"customerId": "cst_12345",
"sequenceType": "first"
}
}
]
}

Provider Notes​

  • unitAmount is a positive integer in minor units (1300 means EUR 13.00). Currency codes are normalized to uppercase.
  • Payment invoices may contain multiple inline and legacy lines, but every line must resolve to one currency. Mollie preserves each line description in the sales invoice and Stripe creates one invoice item per line.
  • Subscription invoices require exactly one line. Inline subscriptions require recurringInterval; recurringIntervalCount defaults to 1.
  • Stripe subscription descriptions are limited to 500 characters. lineItems[0].descriptionUnused is optional and only labels the unused-time credit on an upgrade; lineItems[0].description labels the remaining-time charge and future billing-cycle lines.
  • Deprecated productPriceUuid, lineItems[].productPriceUuid, provider lineItems[].price, and name remain supported.
  • Stripe: providerObjectType is typically invoice.
  • A higher same-currency Stripe subscription price updates the existing item, invoices the prorated difference immediately, and applies only after payment. An open invoice is returned in nextAction.url; the old plan remains active.
  • For a paid Stripe subscription invoice, planPeriod contains the active period's status, changeType, startedAt, endedAt, and immutable transition invoice/payment fields. It is null while an upgrade is pending.
  • Failed custom-upgrade invoices create no plan period. Custom-description upgrades must retain the existing cadence. Without custom descriptions, cadence changes continue to use Stripe's normal reset behavior. While payment or authentication is pending, the hosted invoice URL is returned; retrying the identical request reuses the pending invoice.
  • Mollie: providerObjectType is payment, and invoiceId/invoiceUrl style fields in downstream resources refer to the Mollie payment id and payment document URL rather than a native Mollie sales invoice.

See Subscription upgrades and plan history.

Error Responses​

HTTP StatusExample 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"}]}
400{"errors":[{"validation":"error","code":"[E4000]","message":"Bad Request / validation error"}]}
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/mollie/invoices`;

const response = await fetch(url, {
method: 'POST',
headers: {
'x-api-key': '<api-key>',
'x-client-id': 'appUuid-value',
'x-api-key-type': 'write',
'Content-Type': 'application/json',
},
body: '{"tenantUuid":"11111111-1111-1111-1111-111111111111","lineItems":[{"productUuid":"22222222-2222-2222-2222-222222222222","unitAmount":1300,"currency":"EUR","quantity":1,"description":"Pro Plan — September","recurringInterval":"month","recurringIntervalCount":1}],"taxRateId":"txr_12345","paymentMethod":"card","type":"subscription"}',
});
const data = await response.json();
console.log(response.status, data);

Named discounts​

Supply lineItems[].discount with { "name": "Partner deal", "amount": 1000, "duration": "once" } or duration "forever". Amounts use the price currency's minor units and reduce the product line once, regardless of quantity. The original price and named reduction remain visible on the invoice. Discounts must be smaller than the product line subtotal; setup sessions and charges below the provider minimum are rejected.

See Named billing discounts for renewal behavior, per-line invoice examples, tax handling, and midterm upgrade calculations.