curl -X PATCH https://invoice.horizonpay.co/api/v1/invoices/in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8 \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"due_date": "2026-10-22",
"description": "Consulting retainer — net 30.",
"footer": "Thank you for your business."
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const invoice = await invoiceai.invoices.update('in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8', {
due_date: '2026-10-22',
description: 'Consulting retainer — net 30.',
footer: 'Thank you for your business.',
})
console.log(invoice.due_date, invoice.total)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
invoice = client.invoices.update(
"in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8",
due_date="2026-10-22",
description="Consulting retainer — net 30.",
footer="Thank you for your business.",
)
print(invoice.due_date, invoice.total){
"data": {
"id": "in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8",
"object": "invoice",
"number": null,
"status": "draft",
"customer": "cus_Nf3kQ8pR2mX7vB1cT9wL4sZ6",
"currency": "USD",
"collection_method": "send_invoice",
"issue_date": "2026-09-22",
"due_date": "2026-10-22",
"description": "Consulting retainer — net 30.",
"footer": "Thank you for your business.",
"subtotal": 2550000,
"discount": 0,
"taxable": 2550000,
"tax": 0,
"total": 2550000,
"amount_due": 0,
"amount_in_words": "Twenty Five Thousand Five Hundred USD Only",
"public_url_token": "2b7e4c1a-9f3d-4e68-8a5b-0d1c7f3e9a46",
"finalized_at": null,
"paid_at": null,
"voided_at": null,
"void_reason": null,
"created": "2026-09-22T09:30:00.000Z",
"updated": "2026-09-22T09:45:00.000Z",
"lines": {
"data": [
{
"id": "ii_Da4Vq9Ns2Kx7Bm3Yt8Rc1Lp6",
"object": "invoiceitem",
"price": "price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
"product": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"description": "Consulting retainer",
"quantity": 1,
"unit": "NOS",
"unit_amount": 2500000,
"amount": 2500000,
"discount_percent": 0,
"tax_rate": 0,
"tax_amount": 0
},
{
"id": "ii_Ew8Hz3Jc6Tq1Ms5Nv9Kb2Xr4",
"object": "invoiceitem",
"price": null,
"product": null,
"description": "Onboarding workshop",
"quantity": 1,
"unit": "NOS",
"unit_amount": 50000,
"amount": 50000,
"discount_percent": 0,
"tax_rate": 0,
"tax_amount": 0
}
]
}
}
}{
"type": "https://invoice.horizonpay.co/problems/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Send your API key as `Authorization: Bearer inv_live_…`.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "unauthorized"
}{
"type": "https://invoice.horizonpay.co/problems/forbidden",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential is missing the invoices:write scope.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "forbidden"
}{
"type": "https://invoice.horizonpay.co/problems/not-found",
"title": "Not found",
"status": 404,
"detail": "Invoice not found.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "not_found"
}{
"type": "https://invoice.horizonpay.co/problems/invalid-state",
"title": "Invalid state for this operation",
"status": 409,
"detail": "This invoice has been finalized and can no longer be edited.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "invalid_state"
}{
"type": "https://invoice.horizonpay.co/problems/validation",
"title": "Validation failed",
"status": 422,
"detail": "Some fields need attention.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "validation",
"errors": [
{
"path": "due_date",
"message": "Invalid ISO date"
}
]
}{
"type": "https://invoice.horizonpay.co/problems/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "Rate limit of 120 per 60s exceeded.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "rate_limited"
}Update a draft invoice
Updates a draft. Send only the fields to change; items, when sent, replaces every line (line ids change). Once finalized an invoice is frozen and this returns 409. Emits invoice.updated.
Scope: invoices:write + business:read + clients:read
curl -X PATCH https://invoice.horizonpay.co/api/v1/invoices/in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8 \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"due_date": "2026-10-22",
"description": "Consulting retainer — net 30.",
"footer": "Thank you for your business."
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const invoice = await invoiceai.invoices.update('in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8', {
due_date: '2026-10-22',
description: 'Consulting retainer — net 30.',
footer: 'Thank you for your business.',
})
console.log(invoice.due_date, invoice.total)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
invoice = client.invoices.update(
"in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8",
due_date="2026-10-22",
description="Consulting retainer — net 30.",
footer="Thank you for your business.",
)
print(invoice.due_date, invoice.total){
"data": {
"id": "in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8",
"object": "invoice",
"number": null,
"status": "draft",
"customer": "cus_Nf3kQ8pR2mX7vB1cT9wL4sZ6",
"currency": "USD",
"collection_method": "send_invoice",
"issue_date": "2026-09-22",
"due_date": "2026-10-22",
"description": "Consulting retainer — net 30.",
"footer": "Thank you for your business.",
"subtotal": 2550000,
"discount": 0,
"taxable": 2550000,
"tax": 0,
"total": 2550000,
"amount_due": 0,
"amount_in_words": "Twenty Five Thousand Five Hundred USD Only",
"public_url_token": "2b7e4c1a-9f3d-4e68-8a5b-0d1c7f3e9a46",
"finalized_at": null,
"paid_at": null,
"voided_at": null,
"void_reason": null,
"created": "2026-09-22T09:30:00.000Z",
"updated": "2026-09-22T09:45:00.000Z",
"lines": {
"data": [
{
"id": "ii_Da4Vq9Ns2Kx7Bm3Yt8Rc1Lp6",
"object": "invoiceitem",
"price": "price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
"product": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"description": "Consulting retainer",
"quantity": 1,
"unit": "NOS",
"unit_amount": 2500000,
"amount": 2500000,
"discount_percent": 0,
"tax_rate": 0,
"tax_amount": 0
},
{
"id": "ii_Ew8Hz3Jc6Tq1Ms5Nv9Kb2Xr4",
"object": "invoiceitem",
"price": null,
"product": null,
"description": "Onboarding workshop",
"quantity": 1,
"unit": "NOS",
"unit_amount": 50000,
"amount": 50000,
"discount_percent": 0,
"tax_rate": 0,
"tax_amount": 0
}
]
}
}
}{
"type": "https://invoice.horizonpay.co/problems/unauthorized",
"title": "Unauthorized",
"status": 401,
"detail": "Send your API key as `Authorization: Bearer inv_live_…`.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "unauthorized"
}{
"type": "https://invoice.horizonpay.co/problems/forbidden",
"title": "Insufficient scope",
"status": 403,
"detail": "This credential is missing the invoices:write scope.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "forbidden"
}{
"type": "https://invoice.horizonpay.co/problems/not-found",
"title": "Not found",
"status": 404,
"detail": "Invoice not found.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "not_found"
}{
"type": "https://invoice.horizonpay.co/problems/invalid-state",
"title": "Invalid state for this operation",
"status": 409,
"detail": "This invoice has been finalized and can no longer be edited.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "invalid_state"
}{
"type": "https://invoice.horizonpay.co/problems/validation",
"title": "Validation failed",
"status": 422,
"detail": "Some fields need attention.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "validation",
"errors": [
{
"path": "due_date",
"message": "Invalid ISO date"
}
]
}{
"type": "https://invoice.horizonpay.co/problems/rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "Rate limit of 120 per 60s exceeded.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "rate_limited"
}Authorizations
An Invoice-AI API key sent as Authorization: Bearer inv_live_….
Create keys in Settings → API keys; the secret is shown once. Each key carries scopes, and every operation lists the scope it needs (x-required-scope):
business:read— Read your business profile, tax ID and bank detailsclients:read— List and read your clientsclients:write— Create, update and archive clientsproducts:read— List and read products and pricesproducts:write— Create, update and archive products and pricesinvoices:read— List and read invoices, including PDFsinvoices:write— Create, edit and delete draftsinvoices:finalize— Finalize invoices and void theminvoices:send— Email invoices to your clientspayments:write— Mark invoices as paidwebhooks:manage— Manage webhook endpoints
Keys cannot be created or revoked through the API, so a leaked key cannot mint more keys.
Path Parameters
The draft, in_… or UUID.
"in_Pb2Xk7Mv4Qs9Lr1Wd6Tn3Fh8"
Body
Any subset of fields. Omitted fields keep their stored value; omit items to keep the lines.
Bill a different customer, cus_… or UUID. Omit to keep the current one.
1"cus_Nf3kQ8pR2mX7vB1cT9wL4sZ6"
ISO 4217 code. Defaults to your business currency.
3^[A-Z]{3}$"USD"
Defaults to send_invoice. Informational today.
charge_automatically, send_invoice "send_invoice"
Due date, YYYY-MM-DD. "" clears it.
^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))$"2026-10-22"
Alternative to due_date on create only: issue date + N days (0–365). Ignored on update.
0 <= x <= 36530
Notes printed on the invoice.
Terms printed at the foot of the invoice.
The lines, at least one. On update, replaces every existing line; omit to keep them.
1Show child attributes
Show child attributes
Response
The updated draft, with lines.
The updated draft.
Show child attributes
Show child attributes