Skip to main content

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
statusstringFilter 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.