Invoice Generation API
Generate professional invoice PDFs programmatically from your own server, suitable for internal systems, marketplaces, or your own SaaS product.
1. Authentication#
Create an API key at app.invosend.com/settings/api-keys. A paid workspace plan and owner role are required.
Send the key as a Bearer token in the Authorization header on every request:
Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx403. Keys are also rejected when the workspace is on a free plan, suspended, or expired.2. Endpoint#
Base URL: https://app.invosend.com
Machine-readable API description: OpenAPI 3.1 and Postman collection. Import either one into Postman, Insomnia, or an SDK generator.
3. Request Body#
Complete request example:
curl -X POST https://app.invosend.com/api/invoices/generate-external \
-H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"items": [
{ "description": "Consulting Services", "quantity": 2, "price": 500, "tax_rate": 11 }
],
"discount_total": 50,
"currency": "USD",
"notes": "Thank you for your business."
}'Recurring invoice example (first invoice now, then one every month, 6 in total):
curl -X POST https://app.invosend.com/api/invoices/generate-external \
-H "Authorization: Bearer isk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"items": [
{ "description": "Monthly retainer", "quantity": 1, "price": 2500 }
],
"currency": "USD",
"recurring_interval": "monthly",
"recurring_count": 6
}'Idempotency-Key header (1-255 characters, for example a UUID you generate for each invoice). If the first request succeeded, the retry returns the same response with the header Idempotent-Replayed: true, without creating another invoice or using another credit (credits_remaining is the value from the first call). Keys are kept for 24 hours per workspace. Only successful responses are stored, so a request that failed can be retried with the same key.4. Response#
200 OK means the invoice was created and the PDF was generated:
{
"data": {
"id": "cjld2cjxh0000qzrmn831i7rn",
"invoice_number": "INV-1-202609-0016",
"pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202609_0016_UNPAID_0da2beeabb.pdf",
"credits_remaining": 24,
"is_recurring": false,
"template": {
"id": "k3p9x2m7c0000abcd1234efgh",
"name": "Classic",
"source": "system_default"
}
}
}credits_remaining is null when the workspace has unlimited quota. id identifies this invoice for the Additional Endpoints below. Invoices created through this API also appear in the workspace invoice list and use the same invoice number sequence as manually-created invoices. Invoice numbers look like INV-{workspace id}-{YYYYMM}-{sequence}. For a recurring invoice the response also includes a recurring object: schedule_id, interval, occurrences, next_issue_date, end_date. recurring.schedule_id is the id to use with the recurring endpoints below.5. Error Codes#
6. Rate Limit#
X-RateLimit-Limit and X-RateLimit-Remaining headers. Workspace API quotas are configured per membership plan in Invosend. Need higher production volume? Contact us from your workspace account. Revoked keys do not count toward the key limit.7. Additional Endpoints#
The same API key can also read and manage invoices it created through generate-external:
payment_gateway (and optionally payment_account) on generate-external, then send your customer the invoice's public payment page: https://app.invosend.com/p/invoice/{id}, using the id returned by the API. They pay there through the connected gateway and the invoice is marked paid automatically. Checkout is handled by that page; there is no separate public checkout endpoint to call.8. Webhooks#
Instead of polling, register an HTTPS URL and Invosend sends it a POST request with a JSON body whenever an invoice changes. Add endpoints in Settings > Webhooks (workspace owner, plan with API access, up to 5 endpoints). Each endpoint has its own signing secret, shown only once.
Events are sent for invoices created in the dashboard and through this API alike. Recurring series templates are never sent.
Every event has the same envelope. data.object is the invoice, in the same shape as GET /api/invoices/external/:id; status events also include data.previous_status:
{
"id": "evt_9f2c1b7a4e3d5c6b8a1f0e2d",
"object": "event",
"type": "invoice.paid",
"created": "2026-10-01T09:30:12.000Z",
"data": {
"object": {
"id": "cjld2cjxh0000qzrmn831i7rn",
"invoice_number": "INV-1-202610-0007",
"customer_name": "Acme Corp",
"customer_email": "billing@acme.com",
"currency": "USD",
"subtotal": 500,
"discount_total": 0,
"tax_rate": 0,
"tax_amount": 0,
"amount": 500,
"amount_paid": 500,
"amount_credited": 0,
"amount_received": 500,
"invoice_status": "paid",
"is_archived": false,
"is_recurring": false,
"recurring_interval": "none",
"issue_date": "2026-10-01T02:15:40.000Z",
"due_date": "2026-10-15",
"paid_at": "2026-10-01T09:30:11.000Z",
"pdf_url": "https://cdn.invosend.com/company/1/pdf/Invoice_INV_1_202610_0007_PAID.pdf",
"pdf_status": "ready"
},
"previous_status": "unpaid"
}
}Each request carries these headers. To verify it, compute an HMAC-SHA256 of {t}.{raw body} with the endpoint's secret and compare it with v1; reject it when t is more than 5 minutes old:
POST /your/webhook/url
Content-Type: application/json
Invosend-Event: invoice.paid
Invosend-Delivery: evt_9f2c1b7a4e3d5c6b8a1f0e2d
Invosend-Signature: t=1790847012,v1=5b1d...e9a2
// Node.js
import crypto from "crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto
.createHmac("sha256", secret)
.update(parts.t + "." + rawBody)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}2xx status within 10 seconds. Anything else is retried up to 7 more times (after 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours, 12 hours and 24 hours). An endpoint that keeps failing is switched off and you are notified. An event can arrive more than once or out of order: use the event id to ignore duplicates and treat invoice_status as the source of truth. Delivery logs are kept for 30 days, and any event can be resent from Settings > Webhooks.9. Limitations#
This API is intentionally scoped to invoice generation and light invoice management. The following are not available yet:
- Webhooks cover only invoice created, paid, overdue and cancelled. Other changes, such as edits or archiving, are not sent: read the current state with
GET /invoices/external/:id. - The invoice created by each request is not emailed: this API only generates the PDF, so delivering it to your customer is up to you (or use the dashboard). The exception is recurring series: each follow-up invoice generated by the scheduler is emailed automatically to
customer_email. - No editing of an invoice after creation — only its status and archived state can be changed via this API.
- Payment gateway support requires the gateway to already be connected in the dashboard; this API only attaches it to the invoice, it does not connect a gateway on its own.
- A recurring series can be paused, resumed, extended, re-timed and have upcoming occurrences skipped through the API, but its content (items, customer, amounts) cannot be edited and a series cannot be deleted from the API; do those in the dashboard.
Frequently Asked Questions#
How do I get an Invosend API key?
Create an account at app.invosend.com, upgrade the workspace to a paid plan, then open Settings > API Keys and click Generate key. The raw key is shown only once when it is created.
How much does each generate invoice API call cost?
Each successful request deducts 1 invoice credit from your workspace balance. It uses the same invoice credit pool as invoices created through the dashboard.
What is the rate limit for this API?
The workspace rate limit follows your paid plan configuration. The Rate Limit section above lists the current limit of each plan.