> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cleo-pay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create an invoice

> POST /v1/invoices creates an invoice to a contact, as a draft or sent right away with a hosted pay link.

```
POST /v1/invoices
```

**Scope:** `invoices:write`  ·  **Idempotency-Key:** optional, recommended

## Body

<ParamField body="contactId" type="string" required>
  The customer's contact id. The contact must be active, not archived, and set to `bidirectional` or `can_be_paid`.
</ParamField>

<ParamField body="items" type="array" required>
  At least one line item. Each takes `name` (required, not blank), `description`, `quantity` (integer, 1 to 99,999,999, default 1) and `unitAmountCents` (required, at least 1). The invoice total is the sum of the line totals and must be at least \$1.00.
</ParamField>

<ParamField body="dueDate" type="string">`YYYY-MM-DD`.</ParamField>
<ParamField body="issueDate" type="string">`YYYY-MM-DD`.</ParamField>
<ParamField body="customNumber" type="string">Invoice number shown to the customer.</ParamField>
<ParamField body="description" type="string">Memo shown on the invoice.</ParamField>

<ParamField body="send" type="object">
  Send right away. Without it the invoice is a draft with its link off. Takes `emails` (recipients; default the customer's email on file), `subject` and `message`. Send `{}` to use the defaults.
</ParamField>

```bash theme={null}
curl -X POST https://api.stg.cleo-pay.com/v1/invoices \
  --header "Authorization: Bearer $CLEO_API_KEY" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: c3d4e5f6-a7b8-4c9d-8e0f-1a2b3c4d5e6f" \
  --data '{
    "contactId": "8a7b6c5d-4e3f-4a1b-9c8d-7e6f5a4b3c2d",
    "items": [
      { "name": "Event catering", "unitAmountCents": 480000 },
      { "name": "Staffing", "quantity": 4, "unitAmountCents": 12500 }
    ],
    "dueDate": "2026-11-30",
    "customNumber": "INV-2026-118",
    "send": { "message": "Thanks for your business." }
  }'
```

## Response

`201` with the [invoice](/api-reference/invoices/get).

With `send`, Cleo first checks that the business can receive, then finalizes the invoice and emails it. If the invoice is created but the email fails, the error message names the invoice id, and a retry with the same `Idempotency-Key` returns that answer instead of creating a second invoice. Send it with [`POST /v1/invoices/{invoiceId}/send`](/api-reference/invoices/send).

## Errors

| Code | When |
| - | - |
| `validation_error` | Total below \$1.00, a blank item name, an invalid date, a contact that is archived, revoked or not set up to pay this business, or a customer with no email and no `send.emails`. |
| `not_found` | The contact is not the business's. |
| `payments_locked`, `setup_incomplete`, `setup_required`, `feature_unavailable` | With `send`: the business cannot receive yet. See [`GET /v1/receiving`](/api-reference/receiving/get). |
| `forbidden_scope` | With `send`, the key lacks the edit permission. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.