CGInvoicerCloud Generated
Documentation

CG Invoicer API

POST structured invoice data, get a branded, tax-correct PDF and the computed breakdown. Base URL in production: https://api.cginvoicer.com/v1. Locally, routes live under /api/v1.

This is v1: single-invoice generation and the supporting API. CSV batch, the SEO funnel, live Stripe billing and the stateful tier (saved clients, gapless numbering) are fast-follows.

The hard part — and the moat — is the calculation engine: it computes line totals, discounts, per-rate tax and the grand total deterministically, in integer minor units, and returns the breakdown in the response.

Getting started

Clone, configure Postgres, mint a key, and run:

npm install
cp .env.example .env          # set DATABASE_URL, etc.
npm run db:push               # create tables
npm run keys:mint -- --email [email protected] --plan starter --live
npm run dev                   # http://localhost:3037

keys:mint prints the key once. Without --live it mints a sandbox sk_test_ key. Then call the API:

curl -s http://localhost:3037/api/v1/invoices \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d @examples/eu-invoice.json | jq

Storage defaults to a local driver (no cloud credentials needed); set the S3_* environment variables to switch to Cloudflare R2 or S3.

Authentication

Pass your key as a bearer token: Authorization: Bearer sk_live_.... Keys are hashed at rest (only a sha256 hash and a non-secret prefix are stored). sk_test_ keys run in sandbox/test mode and sk_live_ keys in production; both produce clean PDFs.

Money & rounding

All money is integer minor units (cents) on the wire; currencyis an ISO-4217 code. Prices are tax-exclusive (net) — tax is added on top and shown separately. Display formatting (symbol, grouping, decimals) happens only at render time via Intl.NumberFormat.

Rounding policy: per-line + per-tax-rate, half-up.

  1. line_subtotal = round(quantity × unit_price) per line.
  2. Line-level discount applied to its line.
  3. subtotal = Σ line nets.
  4. Invoice-level discount computed off the subtotal, then allocated across lines proportionally (largest-remainder) so per-rate bases stay exact.
  5. Group taxable bases by rate; round tax per rate.
  6. grand_total = taxable + tax_total + shipping.

Numbering caveat:v1 is stateless — you supply invoice.number; we validate its format only, never sequence or dedupe. Gapless per-customer numbering is a stateful-tier feature.

Endpoints

MethodPathDescription
GET/v1/templatesList visual themes.
GET/v1/localesList tax locales with their required fields.
GET/v1/document-types/invoice?locale=EUThe merged JSON Schema for a locale.
POST/v1/invoicesGenerate one invoice. 201 JSON, or a PDF via format:"pdf" / Accept: application/pdf.
POST/v1/invoices/validateValidate input and return computed totals. Free, no render, no metering.
GET/v1/invoices/{id}Invoice metadata.
GET/v1/invoices/{id}/downloadRe-signed redirect to the PDF.

Locales

Each locale carries its own required fields, mandatory document wording and tax presentation. Miss a required field and you get a 422.

LocaleTaxTitleRequiredNotes
USSales TaxInvoice-Single rate; EIN optional.
EUVATInvoiceseller.vat_idPer-rate VAT breakdown; reverse charge.
AUGSTTax Invoiceseller.abnMandatory “Tax Invoice” wording.
GENERICTaxInvoice-Arbitrary rate, or none.

Themes

Three typeset themes compose with your logo and accent colour: classic (serif, ruled), modern (accent header band), and minimal (monochrome, hairline). Pass theme and an optional accent_color in the request. Line tables repeat their header across pages and keep totals from orphaning.

Errors

Errors return { "error": { "code", "message", "errors?" } } with a relevant status:

StatusCodeMeaning
400invalid_requestStructural schema error (base schema).
401unauthorizedMissing or invalid API key.
402quota_exceededOver the plan's monthly quota.
422unprocessableUnsupported locale/theme, or a locale-mandated field missing.
429rate_limitedRate limit exceeded.

Plans & quotas

Usage is metered per calendar month; exceeding your plan returns a 402.

PlanPriceInvoices / moNotes
Free / Test$010sk_test_ keys, sandbox.
Starter$19100Live keys, all themes/locales.
Pro$79500+ batch CSV, webhook on generate.
Scale$2492,500+ priority render, higher rate limit.
Overage$0.10/ea-Metered pay-as-you-go.