curl https://invoice.horizonpay.co/api/v1/products \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "Consulting retainer",
"description": "Monthly advisory block."
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const product = await invoiceai.products.create({
name: 'Consulting retainer',
description: 'Monthly advisory block.',
})
console.log(product.id)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
product = client.products.create(
name="Consulting retainer",
description="Monthly advisory block.",
)
print(product.id){
"data": {
"id": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"object": "product",
"name": "Consulting retainer",
"description": "Monthly advisory block.",
"images": [],
"active": true,
"created": "2026-09-22T09:30:00.000Z",
"updated": "2026-09-22T09:30:00.000Z"
}
}Create a product
Creates a product. Amounts live on prices: add one with POST /prices before billing it.
Scope: products:write
Idempotency: Idempotency-Key optional. With one, a retry with the same key and body replays the first response (Idempotent-Replayed: true); the same key with a different body is a 422 idempotency_mismatch.
curl https://invoice.horizonpay.co/api/v1/products \
-H "Authorization: Bearer $INVOICE_AI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"name": "Consulting retainer",
"description": "Monthly advisory block."
}'import InvoiceAI from '@horizonpay/invoice-ai'
const invoiceai = new InvoiceAI() // reads INVOICE_AI_API_KEY
const product = await invoiceai.products.create({
name: 'Consulting retainer',
description: 'Monthly advisory block.',
})
console.log(product.id)from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
product = client.products.create(
name="Consulting retainer",
description="Monthly advisory block.",
)
print(product.id){
"data": {
"id": "prod_Hy7Rq2Lm9Xc4Vb8Nt3Kd6Pw1",
"object": "product",
"name": "Consulting retainer",
"description": "Monthly advisory block.",
"images": [],
"active": true,
"created": "2026-09-22T09:30:00.000Z",
"updated": "2026-09-22T09:30:00.000Z"
}
}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.
Headers
A unique key per distinct operation (a UUID works), reused only when retrying that same request. Up to 255 characters; stored for 24 hours.
255"6f1c2d9e-8a4b-4c3f-9e7d-2b5a1c8f4e30"
Body
Product name, 1–200 characters. Becomes the default line description.
1 - 200"Consulting retainer"
Longer description.
Up to 8 image URLs.
8[]
Whether the product is available. Defaults to true on create.
true
Response
The created product.
The created product.
Show child attributes
Show child attributes