curl -X PATCH https://invoice.horizonpay.co/api/v1/prices/price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7 \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nickname": "Monthly (annual contract)",
"type": "recurring",
"recurring": { "interval": "month", "interval_count": 1 }
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const price = await invoiceai.prices.update('price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7', {
nickname: 'Monthly (annual contract)',
type: 'recurring',
recurring: { interval: 'month', interval_count: 1 },
})
console.log(price.nickname)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
price = client.prices.update(
"price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
nickname="Monthly (annual contract)",
type="recurring",
recurring={"interval": "month", "interval_count": 1},
)
print(price.nickname){
"data": {
"id": "price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
"object": "price",
"product": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"nickname": "Monthly (annual contract)",
"unit_amount": 2500000,
"currency": "USD",
"billing_scheme": "per_unit",
"type": "recurring",
"recurring": {
"interval": "month",
"interval_count": 1
},
"tax_rate": 0,
"active": true,
"created": "2026-09-22T09:30:00.000Z"
}
}{
"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": "Price not found.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "not_found"
}{
"type": "https://invoice.horizonpay.co/problems/validation",
"title": "Validation failed",
"status": 422,
"detail": "A price cannot move to another product.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "validation",
"errors": [
{
"path": "product",
"message": "Create a new price on the other product instead."
}
]
}{
"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 price
Updates the fields you send and leaves the rest unchanged. A price cannot move to another product (422) — create a new price instead. Finalized invoices keep the amount they were billed at; a draft picks up the change the next time it is saved.
Scope: products:write
curl -X PATCH https://invoice.horizonpay.co/api/v1/prices/price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7 \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nickname": "Monthly (annual contract)",
"type": "recurring",
"recurring": { "interval": "month", "interval_count": 1 }
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const price = await invoiceai.prices.update('price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7', {
nickname: 'Monthly (annual contract)',
type: 'recurring',
recurring: { interval: 'month', interval_count: 1 },
})
console.log(price.nickname)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
price = client.prices.update(
"price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
nickname="Monthly (annual contract)",
type="recurring",
recurring={"interval": "month", "interval_count": 1},
)
print(price.nickname){
"data": {
"id": "price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7",
"object": "price",
"product": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"nickname": "Monthly (annual contract)",
"unit_amount": 2500000,
"currency": "USD",
"billing_scheme": "per_unit",
"type": "recurring",
"recurring": {
"interval": "month",
"interval_count": 1
},
"tax_rate": 0,
"active": true,
"created": "2026-09-22T09:30:00.000Z"
}
}{
"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": "Price not found.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "not_found"
}{
"type": "https://invoice.horizonpay.co/problems/validation",
"title": "Validation failed",
"status": 422,
"detail": "A price cannot move to another product.",
"instance": "req_7f3c9a1e2b4d4e8a9c6f2d1b0a3e5f71",
"code": "validation",
"errors": [
{
"path": "product",
"message": "Create a new price on the other product instead."
}
]
}{
"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 price, price_… or UUID.
"price_Jc5Tn8Wq1Ze6Ra3Ym9Ub2Gs7"
Body
Any subset of fields. Omitted fields are left unchanged.
Not updatable — sending it is a 422. Create a new price on the other product instead.
1Internal label. null or "" clears it.
Price per unit in integer minor units (2500000 is $25,000.00).
0 <= x <= 90071992547409912500000
ISO 4217 code, three letters (uppercased for you). Must match the invoice currency when billed.
3^[A-Z]{3}$"USD"
Switching to one_time clears the interval; switching to recurring needs recurring.interval unless one is stored.
one_time, recurring "recurring"
Required when type is recurring; must be omitted for one_time.
Show child attributes
Show child attributes
Default tax percentage, 0–100, for lines billed from this price. Defaults to 0.
0 <= x <= 1000
false archives, true restores.
true
Response
The updated price.
The updated price.
Show child attributes
Show child attributes