# Invoices

An invoice bills one named customer for a fixed amount, and suits a bill to pay later or a customer who should choose the coin. Unlike a charge it needs their name and email but no coin, and it has no timer: it stays open until it is paid or you void it, and the exchange rate is only locked when the customer opens its page and chooses a coin. Every attempt to pay is a charge with invoice set, so the usual charge events and webhooks apply; the invoice becomes paid when one of its charges does, even after it was voided.

## The invoice object

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Public code, the last path segment of hosted_url. |
| `object` | "invoice" | The kind of object. |
| `number` | string | Sequential per account and mode, e.g. INV-0042: test invoices are numbered on their own. You can set your own prefix for new invoices in your organization's settings. |
| `status` | "open" \| "paid" \| "void" | Open until one of its charges is paid or you void it. A void invoice still becomes paid if you later accept a late payment on one of its charges. |
| `overdue` | boolean | Open and past the end of due_at (UTC). Overdue invoices can still be paid. |
| `customer_name, customer_email` | string | Who is billed, up to 255 characters each. The invoice and the receipt go to this email. |
| `memo` | string\|null | Shown on the invoice page and in the email, 500 characters max. |
| `amount, currency` | string | What is owed, in your currency: 0.01 or more, with two decimals. |
| `due_at` | string\|null | Date as YYYY-MM-DD, today or later when the invoice is created. |
| `items` | array | The lines of an itemised invoice, up to 50: description (up to 255 characters), quantity (more than 0, up to 999,999, up to three decimals), unit_amount (0 or more, two decimals) and total (quantity × unit_amount, rounded to the cent), all as strings, such as "1.5". Empty when the invoice carries a single amount. |
| `hosted_url` | string | The page the customer pays on. |
| `document_url` | string | A printable version of the invoice, which the customer can save as a PDF. |
| `charges` | array | Payment attempts, newest first: id, status, asset. |
| `sent_at, viewed_at, paid_at, voided_at, created_at` | string\|null | ISO 8601 timestamps in UTC. sent_at is the first email that was not a reminder; viewed_at the first time someone outside your account opened hosted_url. |

## Endpoints

- GET `/v1/invoices` List invoices, newest first. Filter with ?status=, ?search= (the number, customer name or customer email) and ?overdue=true.
- POST `/v1/invoices` Create an invoice. Body: customer_name, customer_email, currency, memo, due_at, send_email and either amount or items (description, quantity, unit_amount each; the amount is then their sum, which must come to at least 0.01, and an amount sent alongside is ignored). In test mode, send_email to anyone who is not a member of your account answers 422 under errors.customer_email and creates nothing; past the hourly email allowance (see send), send_email answers 429 with Retry-After and creates nothing.
- GET `/v1/invoices/{id}` Retrieve an invoice with its payment attempts.
- POST `/v1/invoices/{id}/send` Email the invoice to the customer. The first email sets sent_at; any later one goes out as a reminder. 409 unless it is open; 429 with Retry-After within 10 minutes of the last email, or past 100 emails an hour for the account (invoices, payment requests and refund notices together, shared with the other accounts its owner owns). In test mode, invoices are only emailed to members of your account: anyone else answers 422 under errors.customer_email.
- POST `/v1/invoices/{id}/void` Withdraw an open invoice and cancel its pending charges, each with a charge.canceled event. 409 when it is not open, or one of its charges is underpaid or has a payment confirming.

## Example: create an invoice

```bash
curl -X POST 'https://api.velirapay.com/v1/invoices' \
  --fail-with-body --silent --show-error --max-time 30 \
  -H "Authorization: Bearer ${VELIRAPAY_API_KEY:?Set VELIRAPAY_API_KEY}" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
    "customer_name": "Jane Doe",
    "customer_email": "jane@example.com",
    "currency": "EUR",
    "items": [
      {
        "description": "Consulting",
        "quantity": "2",
        "unit_amount": "75.00"
      }
    ],
    "due_at": "2026-12-31",
    "send_email": true
  }'
```

**Response: 201 Created**

```json
{
  "data": {
    "id": "q7m2xk9wd4ra",
    "object": "invoice",
    "number": "INV-0042",
    "status": "open",
    "overdue": false,
    "amount": "150.00",
    "currency": "EUR",
    "items": [
      {"description": "Consulting", "quantity": "2", "unit_amount": "75.00", "total": "150.00"}
    ],
    "due_at": "2026-12-31",
    "hosted_url": "https://velirapay.com/i/q7m2xk9wd4ra",
    …
  }
}
```

## Reminders

A reminder raises invoice.sent with details.reminder set to true and leaves sent_at as it is. Sending an invoice that was already emailed sends a reminder, and so does the platform on its own schedule.

Turn on invoice reminders under Payment settings and open live invoices with a due date are reminded automatically: the day before it falls due, then 3 and 10 days after, at most once a day, from 09:00 UTC. A step that passed while reminders were off is skipped rather than sent late, and test invoices are never reminded.
