Skip to main content

Invoices

Invoices​

AINative generates invoices for every billing period using its own invoicing system (not Stripe Invoicing). Invoices include line items, PDF download URLs, and payment history.

Base URL: https://api.ainative.studio


Invoice statuses​

StatusDescription
draftCreated but not yet sent. Can still be edited.
sentFinalized and delivered to the customer. Immutable.
paidPayment received.
overdueDue date passed without payment.
voidCancelled. Cannot be paid or un-voided.

List Invoices (Billing Portal)​

GET /api/v1/billing/invoices

Paginated list of invoices for the authenticated user from the billing portal. Amounts are returned in dollars (not cents).

Auth required.

Query parameters

ParamTypeDefaultDescription
pageinteger1Page number
page_sizeinteger20Invoices per page
statusstring—Filter by status (omit for all)
curl "https://api.ainative.studio/api/v1/billing/invoices?page=1&page_size=10" \
-H "Authorization: Bearer <your_api_key>"
import httpx

resp = httpx.get(
"https://api.ainative.studio/api/v1/billing/invoices",
headers={"Authorization": "Bearer <your_api_key>"},
params={"page": 1, "page_size": 10},
)
data = resp.json()["data"]
for invoice in data["items"]:
print(invoice["number"], invoice["status"], invoice["amount"])

Response

{
"success": true,
"data": {
"items": [
{
"id": "invoice-uuid",
"number": "INV-2026-0042",
"amount": 49.00,
"amount_paid": 49.00,
"currency": "USD",
"status": "paid",
"period_start": "2026-04-01T00:00:00Z",
"period_end": "2026-04-30T23:59:59Z",
"due_date": "2026-05-05T00:00:00Z",
"paid_at": "2026-04-25T10:30:00Z",
"invoice_pdf": "https://storage.example.com/invoices/INV-2026-0042.pdf",
"line_items": [
{
"description": "Pro Plan - Monthly Subscription",
"amount": 4900,
"quantity": 1
}
],
"created_at": "2026-04-01T00:00:00Z"
}
],
"total": 3,
"page": 1,
"page_size": 10,
"has_more": false
}
}

Get Invoice​

GET /api/v1/billing/invoices/{invoice_id}

Retrieve a single invoice by its Stripe invoice ID.

Auth required.

curl https://api.ainative.studio/api/v1/billing/invoices/in_xxx \
-H "Authorization: Bearer <your_api_key>"

Response

{
"success": true,
"data": {
"id": "in_xxx",
"amount": 49.00,
"currency": "USD",
"status": "paid",
"created_at": "2026-04-01T00:00:00Z",
"period_start": "2026-04-01T00:00:00Z",
"period_end": "2026-04-30T23:59:59Z",
"items": [...]
}
}

Download Invoice PDF​

GET /api/v1/billing/invoices/{invoice_id}/download

Returns the PDF download URL for an invoice. No authentication required — the invoice UUID acts as an unguessable access token, allowing PDF links in emails to work without login.

Void and cancelled invoices return 404.

curl https://api.ainative.studio/api/v1/billing/invoices/invoice-uuid/download

Response

{
"success": true,
"data": {
"invoice_id": "invoice-uuid",
"invoice_number": "INV-2026-0042",
"pdf_url": "https://storage.example.com/invoices/INV-2026-0042.pdf",
"amount": 49.00,
"currency": "USD",
"status": "paid"
}
}

Email Invoice​

POST /api/v1/billing/invoices/{invoice_id}/email

Send an invoice email to the authenticated user. Duplicate sends are prevented by checking invoice_email_log. Use resend-email with force_send=true to override.

Auth required.

curl -X POST https://api.ainative.studio/api/v1/billing/invoices/in_xxx/email \
-H "Authorization: Bearer <your_api_key>"

Resend Invoice Email​

POST /api/v1/billing/invoices/{invoice_id}/resend-email

Resend an invoice email with duplicate detection. The email type (due_invoice or paid_invoice) is determined automatically from the invoice status.

Auth required.

Query parameters

ParamTypeDefaultDescription
force_sendbooleanfalseSend even if already sent previously
## Force resend even if email was already sent
curl -X POST \
"https://api.ainative.studio/api/v1/billing/invoices/in_xxx/resend-email?force_send=true" \
-H "Authorization: Bearer <your_api_key>"

Response (success)

{
"success": true,
"message": "Invoice email sent to user@example.com",
"invoice_id": "in_xxx",
"invoice_number": "INV-2026-0042",
"email_type": "paid_invoice",
"recipient": "user@example.com",
"log_id": "log-uuid",
"forced": false
}

Response (already sent, force_send not set)

{
"success": false,
"message": "Invoice email already sent. Use force_send=true to resend.",
"already_sent": true,
"previous_sends": [
{
"type": "paid_invoice",
"status": "sent",
"sent_at": "2026-04-25T11:00:00Z"
}
]
}

Bulk Download Invoices​

POST /api/v1/billing/invoices/download-bulk

Get PDF download URLs for up to 50 invoices in a single request.

Auth required.

Request body

FieldTypeDescription
invoice_idsstring[]Stripe invoice IDs to download (max 50)
curl -X POST https://api.ainative.studio/api/v1/billing/invoices/download-bulk \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"invoice_ids": ["in_aaa", "in_bbb", "in_ccc"]}'

Response

{
"success": true,
"data": {
"invoices": [
{
"invoice_id": "in_aaa",
"invoice_number": "INV-2026-0040",
"pdf_url": "https://storage.example.com/invoices/INV-2026-0040.pdf",
"amount": 49.00,
"currency": "USD",
"created_at": "2026-03-01T00:00:00Z"
}
],
"total_requested": 3,
"total_available": 1,
"failed": [
{"invoice_id": "in_bbb", "reason": "PDF not available"},
{"invoice_id": "in_ccc", "reason": "Invoice not found"}
]
}
}

Billing Information​

GET /api/v1/billing

Returns a summary of the user's billing info: primary payment method, next billing date, and amount due. Card numbers are masked — only the last 4 digits are shown.

Auth required.

curl https://api.ainative.studio/api/v1/billing \
-H "Authorization: Bearer <your_api_key>"

Response (with active subscription)

{
"success": true,
"data": {
"payment_method": {
"type": "card",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027,
"brand": "visa"
},
"next_billing_date": "2026-05-01T00:00:00Z",
"amount_due": 49.00,
"currency": "USD",
"billing_cycle": "monthly"
}
}

Response (no active subscription)

{
"success": true,
"data": {
"payment_method": null,
"next_billing_date": null,
"amount_due": 0.00,
"currency": "USD",
"billing_cycle": null
}
}

Payment Methods​

List Payment Methods​

GET /api/v1/billing/payment-methods

Returns all Stripe payment methods attached to the user's customer account.

Auth required.

curl https://api.ainative.studio/api/v1/billing/payment-methods \
-H "Authorization: Bearer <your_api_key>"

Response

{
"success": true,
"data": {
"payment_methods": [
{
"id": "pm_xxx",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
}
}
]
}
}

Add Payment Method​

POST /api/v1/billing/payment-methods

Attach a Stripe payment method to the user's customer account. The payment_method_id must be created by Stripe Elements on the frontend before calling this endpoint.

Auth required.

Request body

FieldTypeRequiredDescription
payment_method_idstringYesStripe payment method ID (e.g. "pm_xxx")
curl -X POST https://api.ainative.studio/api/v1/billing/payment-methods \
-H "Authorization: Bearer <your_api_key>" \
-H "Content-Type: application/json" \
-d '{"payment_method_id": "pm_xxx"}'

Response 201 Created

{
"success": true,
"data": {
"id": "pm_xxx",
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2027
}
},
"message": "Payment method added successfully"
}

Returns 404 if the user has no Stripe customer (must subscribe to a plan first).


Admin: Invoice Management​

The following endpoints are restricted to users with ADMIN or SUPERUSER roles.

Create Invoice​

POST /api/v1/invoices

Create a new draft invoice with line items. Invoice number is auto-generated in INV-YYYY-NNNN format.

Admin only.

List All Invoices​

GET /api/v1/invoices

Paginated list of all invoices with optional filters.

Admin only.

ParamDescription
statusFilter by status
user_idFilter by customer user ID
skip / limitPagination

Get Invoice by ID​

GET /api/v1/invoices/{invoice_id}

Users can view their own invoices. Admins can view any invoice.

Update Draft Invoice​

PATCH /api/v1/invoices/{invoice_id}

Update line items, due date, billing period, or metadata on a draft invoice. Finalized invoices are immutable.

Admin only.

Finalize Invoice​

POST /api/v1/invoices/{invoice_id}/finalize

Transitions invoice from draft to sent, generates a PDF asynchronously, and sends an email notification.

Admin only.

Void Invoice​

POST /api/v1/invoices/{invoice_id}/void

Cancel an invoice. Void is irreversible.

Admin only.

Mark Invoice Paid​

POST /api/v1/invoices/{invoice_id}/mark-paid

Manually mark an invoice as paid for non-Stripe payments (wire transfer, ACH, etc.).

Admin only.

Request body

FieldTypeDescription
payment_methodstringe.g. "wire_transfer", "ach", "check"
payment_referencestringReference number or note
paid_atstringISO-8601 timestamp (optional, defaults to now)

Get Invoice PDF​

GET /api/v1/invoices/{invoice_id}/pdf

Returns the PDF URL or generates the PDF on-demand if not yet created.

Create Payment Intent for Invoice​

POST /api/v1/invoices/{invoice_id}/payment-intent

Creates a Stripe Payment Intent for the invoice amount. Returns a client_secret for use with Stripe.js.