---
name: online-free-invoice-generator
description: Generate, customize, and download professional PDF invoices. Use when the user wants to create an invoice, bill a client, send a payment request, generate a receipt, or quote services rendered. Returns the invoice number, a preview URL, and a download URL for the server-rendered PDF.
homepage: https://onlinefreeinvoicegenerator.com
metadata:
  {
    "openclaw":
      {
        "requires": { "bins": [] },
        "primaryEnv": null
      }
  }
---

# Online Free Invoice Generator

A free, no-signup, programmatic invoice generator. Five templates
(Modern, Classic, Professional, Elegant, Nature), 29 currencies, 4
languages (English, Spanish, French, German). The full SPA is
also available at https://onlinefreeinvoicegenerator.com for human
use; this skill exposes the same engine as a JSON API so an agent
can create and download invoices in a single round-trip.

## When to use this skill

- The user asks to "bill", "invoice", "send a payment request to",
  or otherwise produce a document describing money owed
- The user provides a client name, a service or product
  description, a quantity, and a rate
- The user wants a downloadable PDF (not just text)
- The user wants the invoice in a specific currency or template

## When NOT to use this skill

- The user just wants a quote (a "would you charge X for Y"
  question) — that's a conversation, not an invoice
- The user wants to track payments against an existing invoice —
  this skill creates new invoices; the current build does not
  expose a payment-status update endpoint
- The user wants a receipt (proof of payment received) — this
  skill generates invoices (requests for payment), not receipts

## Endpoints

All endpoints are JSON over HTTPS. The base URL is the same as
the site (https://onlinefreeinvoicegenerator.com) and all paths
below are appended to it.

### Authentication (required)

Every API and MCP call needs the user's API token. Ask the user
for it; they can regenerate it any time from their account page.

```
Authorization: Bearer <api_token>
```

Requests without a valid token get `401 {"error":
"Authentication required"}`. All invoice operations are scoped to
the token's account: a user only ever sees their own invoices, and
`invoice_number` uniqueness is per account (two users can both use
"INV-0001").

### Discovery (cheap, safe to call first)

```
GET /api/v1/templates    → 5 templates with id, name, description
GET /api/v1/currencies   → 29 currencies with code, name, symbol
```

### Core CRUD

```
GET    /api/v1/invoices              → list (filter with ?status=, ?template=)
GET    /api/v1/invoices/:id          → one invoice
POST   /api/v1/invoices              → create (body = the invoice attrs)
PATCH  /api/v1/invoices/:id          → partial update
DELETE /api/v1/invoices/:id          → remove
GET    /api/v1/invoices/:id/pdf      → server-rendered PDF download
```

### Wire format

The body of POST/PATCH is the same shape the static SPA uses
(client-side invoiceData), denormalized: the four scalar fields
(`status`, `template`, `currency`, `language`) are at the top
level, and the rest lives in the `data` JSON column:

```json
{
  "invoice_number": "INV-0042",
  "status":         "unpaid",
  "template":       "modern1",
  "currency":       "USD",
  "language":       "en",
  "data": {
    "sender":    { "name": "Acme Corp", "address": "123 Main St", "email": "billing@acme.test" },
    "client":    { "name": "Client LLC", "address": "456 Oak Ave", "email": "ap@client.test" },
    "invoice":   { "number": "INV-0042", "date": "2026-06-08", "dueDate": "2026-07-08", "poNumber": "PO-123", "taxDetail": "VAT 123", "notes": "Net 30" },
    "lineItems": [
      { "description": "Consulting",  "quantity": 10, "rate": 100, "tax": 10 },
      { "description": "Development", "quantity":  5, "rate": 200, "tax":  0 }
    ],
    "discount":   { "type": "percent", "value": 5 },
    "payment":    { "bank": "Bank of America - 1234", "paypal": "pay@acme.test", "link": "https://stripe.com/..." }
  }
}
```

### Constraints (validate before sending)

- `invoice_number` — required, must be unique
- `status`         — one of {`unpaid`, `paid`, `overdue`}
- `template`       — one of {`modern1`, `classic`, `business`, `elegant`, `nature`}
- `currency`       — 3-letter ISO code from `/api/v1/currencies`
- `language`       — one of {`en`, `es`, `fr`, `de`}
- `lineItems[].quantity`, `lineItems[].rate`, `lineItems[].tax` — numeric

## Common workflows

### 1. Create and download an invoice in one go

```bash
INVOICE=$(curl -sS -X POST https://onlinefreeinvoicegenerator.com/api/v1/invoices \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice_number": "INV-0042",
    "template":       "modern1",
    "currency":       "USD",
    "language":       "en",
    "data": {
      "sender":  { "name": "Acme Corp", "email": "billing@acme.test" },
      "client":  { "name": "Client LLC", "email": "ap@client.test" },
      "invoice": { "number": "INV-0042", "date": "2026-06-08", "dueDate": "2026-07-08" },
      "lineItems": [ { "description": "Consulting", "quantity": 10, "rate": 100, "tax": 10 } ]
    }
  }')
ID=$(echo "$INVOICE" | jq -r .invoice.id)
curl -sS -H "Authorization: Bearer $TOKEN" "https://onlinefreeinvoicegenerator.com/api/v1/invoices/${ID}/pdf" -o invoice.pdf
```

### 2. Discover the supported templates first, then create

```bash
TEMPLATES=$(curl -sS -H "Authorization: Bearer $TOKEN" https://onlinefreeinvoicegenerator.com/api/v1/templates)
# pick one based on the user description
curl -sS -H "Authorization: Bearer $TOKEN" https://onlinefreeinvoicegenerator.com/api/v1/currencies
# validate the user's chosen currency is supported
# ...then POST as above
```

### 3. Update an invoice's status (e.g. after a payment is confirmed)

```bash
curl -sS -X PATCH https://onlinefreeinvoicegenerator.com/api/v1/invoices/$ID \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "paid"}'
```

## Notes

- Auth is required: `Authorization: Bearer <api_token>` on every
  call. Ask the user for their token; never guess or fabricate one.
- There is no webhook or push channel. The agent polls (GET
  /api/v1/invoices?status=) to discover new invoices in
  multi-agent flows.
- The PDF endpoint is a 200 with `Content-Type: application/pdf`
  and a filename derived from the invoice number.
- The `data` column is a free-form JSON payload; the static SPA
  has always used this shape, and the API and SPA can talk to
  each other without a translation layer.
