Product

Invoice API

Create, number, send and track invoices from your own code, with a PDF and a hosted payment page for every one.

The ASHDOCS invoice API turns a JSON body into an issued invoice. Send POST /api/v1/invoices with a customer and line items, set issue to true, and the response comes back with the invoice number, totals, pdf_url and hosted_url.

Add a send block and the invoice is emailed as well. From then on its status follows what happens to it (sent, viewed, partially paid, paid, overdue or void), and you can read that status with GET /api/v1/invoices/{invoice_id} or, on paid plans, receive each change as a signed webhook.

POST /api/v1/invoices
curl https://www.ashdocs.com/api/v1/invoices \
  -H "X-API-Key: ash_test_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042" \
  -d '{
  "customer": { "name": "Acme Inc", "email": "ap@acme.com" },
  "currency": "USD",
  "due_terms": "net_30",
  "template": "clean",
  "line_items": [
    { "description": "Consulting", "quantity": "3", "unit_price": "150.00", "tax_rate": "8.25" }
  ],
  "issue": true,
  "send": { "channels": [{ "type": "email" }] }
}'
Response
{
  "id": "inv_5b4384cd4b224b129b0c",
  "kind": "invoice",
  "status": "issued",
  "number": "INV-0004",
  "customer": {
    "name": "Acme Inc",
    "email": "ap@acme.com",
    "id": "cus_dd447d7c2add41acb140"
  },
  "line_items": [
    {
      "description": "Consulting",
      "quantity": "3",
      "unit_price": "150.00",
      "tax_rate": "8.25",
      "amount_minor": 45000,
      "amount_formatted": "$450.00",
      "tax_minor": 3713
    }
  ],
  "currency": "USD",
  "issue_date": "2026-10-05",
  "due_date": "2026-11-04",
  "totals": {
    "subtotal_minor": 45000,
    "subtotal_formatted": "$450.00",
    "tax_minor": 3713,
    "tax_formatted": "$37.13",
    "total_minor": 48713,
    "total_formatted": "$487.13",
    "paid_minor": 0,
    "balance_minor": 48713,
    "balance_formatted": "$487.13",
    "tax_summary": [
      {
        "name": "Tax",
        "pct": "8.25",
        "taxable_formatted": "$450.00",
        "tax_formatted": "$37.13"
      }
    ]
  },
  "pay_link": {
    "provider": "none",
    "url": null,
    "ref": null
  },
  "pdf_url": "https://api.ashdocs.com/api/v1/invoices/inv_5b4384cd4b224b129b0c/pdf",
  "hosted_url": "https://api.ashdocs.com/i/QGwughJ-wezZB_Dm2ltTNzbv5sWOGd0y2PAMDCNtoAg",
  "testing": true,
  "credits_cost": 0,
  "issued_at": "2026-10-05T13:45:10.376000",
  "sent_at": null,
  "first_viewed_at": null,
  "paid_at": null
}

Response from a test key, trimmed. Test keys report 0 credits; a live key reports 1. Delivery is queued, so the status moves to sent once the email goes out.

Invoice INV-0004 for Acme Inc in the clean design: consulting, 3 at $150.00, 8.25% tax, total $487.13.
The PDF rendered from the request above, in the clean design.

Draft, issue, send

Do it all in one request, or create a draft and issue it later with POST /api/v1/invoices/{invoice_id}/issue. Sending needs an issued invoice, and send.schedule_at delays delivery to a time you choose.

Numbering you set up once

Each account chooses its prefix, digit count and an optional yearly restart. Numbers are gapless and never reused; a voided invoice keeps its number, and quotes and credit notes have their own sequences.

Totals you don't compute

Line items take decimal quantities, unit prices with up to four decimal places, tax rates and discounts, plus shipping and deposits. Every total comes back in minor units and formatted for the locale.

How the invoice API request works

A request needs line_items and, in practice, a customer: either a name with an email address, or the id of a customer saved earlier. Each line item has a description, a quantity, a unit_price and optionally a tax_rate or a saved tax_rate_id, a unit and a discount. Currency, locale, paper size, due terms and design fall back to your invoicing settings when you leave them out.

Amounts are decimal strings, and a value with more decimal places than the currency allows is rejected with a 422 that names the field. Add an Idempotency-Key header and a retried request returns the original result instead of creating a second invoice.

What the response gives you

The response is the full invoice. number is null while it is a draft and set at issue. totals holds subtotal, tax, discounts, shipping, total, paid and balance, each as an integer in minor units and as a formatted string, plus a tax summary by rate.

pdf_url downloads the PDF (it answers 202 for the moment it is still rendering) and hosted_url is the page your customer opens. The timestamps issued_at, sent_at, first_viewed_at and paid_at fill in as the invoice moves along. Delivery runs in the background, so a create-and-send response still says issued; invoice.sent fires when the email is delivered.

Payments and reminders

The Pay button shows on the hosted invoice page when Stripe or Razorpay is connected. With Stripe, ASHDOCS creates a payment link in your own Stripe account; with Razorpay it uses your Razorpay keys. Either way the payment is recorded on the invoice when the provider reports it. Payments made by bank transfer, cash or anything else are recorded with POST /api/v1/invoices/{invoice_id}/payments.

A payment that covers part of the balance sets the status to partially_paid and, with a provider connected, a new payment link is made for what is left. Reminders go out by email 3 days before, on and 7 days after the due date at 09:00 in your timezone, can be changed per account or per invoice, and stop when the invoice is paid or voided.

Other endpoints you will use

The same API key works across the rest of the invoicing endpoints:

  • GET /api/v1/invoices: newest first, filtered by status, customer, due date or a search on number, customer name, reference and PO number.
  • POST /api/v1/invoices/{invoice_id}/void, /credit-note and /duplicate for corrections.
  • POST /api/v1/recurring-invoices: issue the same invoice on an RRULE schedule.
  • POST /api/v1/invoices/preview: a watermarked preview that uses no credits.
  • GET /api/v1/invoices/export.csv: every invoice as CSV for your accountant.

Frequently asked questions

How do I create an invoice with the API?

Send POST /api/v1/invoices with your key in the X-API-Key header and a JSON body holding customer, line_items and "issue": true. The response is the issued invoice with its number, totals, pdf_url and hosted_url; leave issue out and it stays a draft you can edit and issue later.

Can the API send the invoice email?

Yes. Add "send": {"channels": [{"type": "email"}]} to the create request, or call POST /api/v1/invoices/{invoice_id}/send later. The email goes to the customer's address unless you set to, cc or bcc, carries the PDF as an attachment (up to 10 MB) and a link to the hosted page, and uses the subject and body from your settings unless you override them.

How do I know when an invoice is paid?

When payments cover the balance, the status becomes paid, paid_at is set and an invoice.paid event fires. On paid plans that event reaches your endpoint as a webhook signed with an X-ASHDOCS-Signature header (HMAC-SHA256 of the body); on any plan you can read GET /api/v1/invoices/{invoice_id} or list GET /api/v1/invoices?status=paid. Stripe and Razorpay payments are recorded automatically, and any other payment is recorded with POST /api/v1/invoices/{invoice_id}/payments.

Can I use my own invoice numbering?

Yes, within a format you configure: a prefix of up to 20 characters, the number of digits, and whether the sequence restarts each year, combined from {prefix}, {seq} and {year} into numbers such as INV-2026-0001. ASHDOCS keeps the counter itself, so numbers are gapless per account and cannot be typed in or skipped by hand; quotes and credit notes have separate sequences.

Plans

Free
$0/mo
  • 100 credits per month
  • 1 seat
  • No webhooks
Starter
$15/mo
or $150/year
  • 1,500 credits per month
  • 1 seat
  • Webhooks
Growth
$49/mo
or $490/year
  • 10,000 credits per month
  • 3 seats
  • Webhooks
Pro
$99/mo
or $990/year
  • 30,000 credits per month
  • 5 seats
  • Webhooks
Scale
$249/mo
or $2,490/year
  • 100,000 credits per month
  • 10 seats
  • Webhooks

Test keys are free, never expire and never use credits; plan rate limits apply. Webhooks are on paid plans. Issuing an invoice uses 1 credit. No per-seat fees. See full pricing.