# Create invoice

Create an issued invoice or credit note.

Creates an issued invoice or credit note. invoice_type is always issued. invoiceNumber, invoiceDate, amountExclVat, and amountInclVat are required. sourceId is optional and defaults to invoiceNumber. If no counterpartyId is sent, identity fields are used to look up or create a counterparty. Expected payment is computed from the due date and this customer’s previous paid invoices. If no schedule is sent, Invunion creates a single payment. Issued invoices may auto-apply unused credit notes and unapplied cash.


- HTTP method: `POST`
- Path: `/api/v1/invoices`
- URL: `https://api.invunion.com/api/v1/invoices`
- Required scope: `invoices:write`
- HTML docs: https://www.invunion.com/knowledge-base/api/create-invoice/
- Markdown docs: https://www.invunion.com/knowledge-base/api/create-invoice.md



## Body parameters

| Name | Type | Required | Description | Allowed values | Example |
| --- | --- | --- | --- | --- | --- |
| `invoiceNumber` | string, max 100 | required | Invoice number. Unique per tenant. This is how you identify the invoice later. |  | `INV-2026-0042` |
| `invoiceDate` | string, no maximum | required | Invoice date (YYYY-MM-DD). |  | `2026-09-01` |
| `amountExclVat` | number | required | Amount excluding VAT, in major currency units unless the tenant stores minor units and sourceType is api. |  | `10000` |
| `amountInclVat` | number | required | Amount including VAT. |  | `12000` |
| `kind` | string, no maximum | recommended | invoice or credit_note. Default invoice. | `invoice`, `credit_note` |  |
| `sourceType` | string, max 50 | recommended | Origin of the record. Use api for integrations. Default manual. |  | `api` |
| `recipientName` | string, max 255 | recommended | Recipient display name. Defaults from the resolved counterparty when omitted. |  | `Leones Cars` |
| `paymentScheduleCode` | string, max 50 | recommended | Payment-schedule template code. If omitted, Invunion creates a single payment unless useDefaultPaymentSchedule is true. |  | `NET-30` |
| `vatAmount` | number | optional | VAT amount. If omitted, Invunion stores the difference of the two amounts. |  | `2000` |
| `currency` | string, max 3 | recommended | ISO 4217 currency. Default EUR. |  | `EUR` |
| `dueDate` | string, no maximum | recommended | Due date (YYYY-MM-DD). When present, paymentTermDays is not stored on the invoice. |  | `2026-10-01` |
| `sourceId` | string, max 255 | optional | Optional idempotency key from your system. Together with sourceType this is unique per tenant. Defaults to invoiceNumber — you do not need a separate source id. |  | `INV-2026-0042` |
| `externalReference` | string, max 255 | optional | Your order or billing reference. |  | `LC-SO-9081` |
| `description` | string, max 1000 | optional | Line description. |  | `Fleet maintenance — September 2026` |
| `paymentMethod` | string, no maximum | optional | Expected payment channel. | `card`, `transfer`, `direct_debit`, `cash`, `check`, `crypto`, `other` |  |
| `paymentTermDays` | integer | optional | Used only when dueDate is omitted, to compute due date from the invoice date. Not stored if dueDate is sent. |  | `30` |
| `counterpartyId` | string, no maximum | optional | Existing counterparty code (`account_code`). If omitted, identity fields below are used to look up or create one. |  | `CPT-042` |
| `counterpartyAccountCode` | string, max 50 | recommended | Counterparty account_code for identity lookup (for example CPT-042). |  | `CPT-042` |
| `counterpartyExternalReference` | string, max 255 | optional | Counterparty external reference. |  | `ERP-1842` |
| `counterpartyVatNumber` | string, max 30 | optional | Counterparty VAT number. |  | `FR12345678901` |
| `counterpartyEmail` | string, max 255 | optional | Counterparty email. |  | `carl@leonescars.fr` |
| `counterpartyIban` | string, max 64 | optional | Optional catalog IBAN to attach after the counterparty is resolved. |  | `FR7630006000011234567890189` |
| `counterpartyBic` | string, max 11 | optional | BIC for the catalog instrument. |  | `BNPAFRPP` |
| `paymentMethodId` | string, no maximum | optional | Existing catalog payment-method code to attach. |  | `PM-001` |
| `originInvoiceId` | string, no maximum | optional | For credit notes, the invoice number of the invoice being credited. |  | `INV-2026-0042` |
| `useDefaultPaymentSchedule` | boolean | optional | If true, apply the tenant default schedule. If omitted or false, Invunion creates a single payment. | `true`, `false` |  |
| `installments` | array | optional | Exact installment plan. When present, this replaces any template. Each item needs dueDate and amount. |  |  |
| `installments.dueDate` | string, no maximum | required | Installment due date (YYYY-MM-DD). |  | `2026-10-01` |
| `installments.amount` | number | required | Installment amount, zero or greater. |  | `12000` |
| `installments.sequence` | integer | optional | 1-based sequence. |  | `1` |
| `installments.label` | string, max 100 | optional | Optional label. |  | `Balance` |
| `analytic1` | string, max 100 | optional | Analytic axis 1. |  | `SALES-EU` |
| `analytic2` | string, max 100 | optional | Analytic axis 2. |  | `CHANNEL-DIRECT` |
| `metadata` | object | optional | JSON object. At most 32 keys, nested depth 3, 8 KB serialized, and 64-character key names. Keys __proto__, constructor, and prototype are rejected. |  | `{"erp_id":"INV-1842"}` |

## Errors

| Error | HTTP code | Description |
| --- | --- | --- |
| `Missing Bearer token` | `401` | The Authorization header is missing or is not a Bearer token. |
| `Invalid or revoked API key` | `401` | The API key is unknown, malformed, expired, or has been revoked. |
| `API key is missing scope invoices:write` | `403` | The key does not include invoices:write. A write scope does not imply the matching read scope. |
| `Too many requests, please try again later` | `429` | Wait and retry. The Retry-After header is the number of seconds to wait. |
| `Tenant ID required` | `400` | The authenticated credential is not bound to a tenant. |
| `Validation failed` | `400` | The body failed schema validation. details lists field and message. |
| `Unknown or inactive payment schedule.` | `400` | paymentScheduleId or paymentScheduleCode did not match an active template. |
| `duplicate_invoice` | `409` | An invoice with this invoice_number already exists. The message includes the number and existing_invoice_id. |
| `Internal server error` | `500` | Unexpected server error. The JSON body includes correlationId. Retry with backoff. |

## Request (curl)

```bash
curl --request POST \
  --url https://api.invunion.com/api/v1/invoices \
  --header 'accept: application/json' \
  --header 'authorization: Bearer uk_live_YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --data '{
  "invoiceNumber": "INV-2026-0042",
  "invoiceDate": "2026-09-01",
  "amountExclVat": 10000,
  "amountInclVat": 12000,
  "vatAmount": 2000,
  "currency": "EUR",
  "kind": "invoice",
  "sourceType": "api",
  "recipientName": "Leones Cars",
  "paymentScheduleCode": "NET-30",
  "dueDate": "2026-10-01",
  "counterpartyAccountCode": "CPT-042",
  "description": "Fleet maintenance — September 2026"
}'
```

## Request (Python)

```python
import requests

url = "https://api.invunion.com/api/v1/invoices"
headers = {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json",
}
payload = {
    "invoiceNumber": "INV-2026-0042",
    "invoiceDate": "2026-09-01",
    "amountExclVat": 10000,
    "amountInclVat": 12000,
    "vatAmount": 2000,
    "currency": "EUR",
    "kind": "invoice",
    "sourceType": "api",
    "recipientName": "Leones Cars",
    "paymentScheduleCode": "NET-30",
    "dueDate": "2026-10-01",
    "counterpartyAccountCode": "CPT-042",
    "description": "Fleet maintenance — September 2026"
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
```

## Request (Ruby)

```ruby
require 'net/http'
require 'json'
require 'uri'

uri = URI("https://api.invunion.com/api/v1/invoices")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Accept'] = 'application/json'
request['Authorization'] = 'Bearer uk_live_YOUR_API_KEY'
request['Content-Type'] = 'application/json'
request.body = "{\n  \"invoiceNumber\": \"INV-2026-0042\",\n  \"invoiceDate\": \"2026-09-01\",\n  \"amountExclVat\": 10000,\n  \"amountInclVat\": 12000,\n  \"vatAmount\": 2000,\n  \"currency\": \"EUR\",\n  \"kind\": \"invoice\",\n  \"sourceType\": \"api\",\n  \"recipientName\": \"Leones Cars\",\n  \"paymentScheduleCode\": \"NET-30\",\n  \"dueDate\": \"2026-10-01\",\n  \"counterpartyAccountCode\": \"CPT-042\",\n  \"description\": \"Fleet maintenance — September 2026\"\n}"
response = http.request(request)
puts response.body
```

## Request (JavaScript)

```javascript
const response = await fetch("https://api.invunion.com/api/v1/invoices", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "invoiceNumber": "INV-2026-0042",
  "invoiceDate": "2026-09-01",
  "amountExclVat": 10000,
  "amountInclVat": 12000,
  "vatAmount": 2000,
  "currency": "EUR",
  "kind": "invoice",
  "sourceType": "api",
  "recipientName": "Leones Cars",
  "paymentScheduleCode": "NET-30",
  "dueDate": "2026-10-01",
  "counterpartyAccountCode": "CPT-042",
  "description": "Fleet maintenance — September 2026"
}),
});
const data = await response.json();
```

## Request (Go)

```go
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
)

func main() {
	payload := []byte(`{
  "invoiceNumber": "INV-2026-0042",
  "invoiceDate": "2026-09-01",
  "amountExclVat": 10000,
  "amountInclVat": 12000,
  "vatAmount": 2000,
  "currency": "EUR",
  "kind": "invoice",
  "sourceType": "api",
  "recipientName": "Leones Cars",
  "paymentScheduleCode": "NET-30",
  "dueDate": "2026-10-01",
  "counterpartyAccountCode": "CPT-042",
  "description": "Fleet maintenance — September 2026"
}`)
	req, err := http.NewRequest("POST", "https://api.invunion.com/api/v1/invoices", bytes.NewBuffer(payload))
	if err != nil {
		panic(err)
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer uk_live_YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}
```

## Request (Node)

```javascript
const response = await fetch("https://api.invunion.com/api/v1/invoices", {
  method: "POST",
  headers: {
    "Accept": "application/json",
    "Authorization": "Bearer uk_live_YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "invoiceNumber": "INV-2026-0042",
  "invoiceDate": "2026-09-01",
  "amountExclVat": 10000,
  "amountInclVat": 12000,
  "vatAmount": 2000,
  "currency": "EUR",
  "kind": "invoice",
  "sourceType": "api",
  "recipientName": "Leones Cars",
  "paymentScheduleCode": "NET-30",
  "dueDate": "2026-10-01",
  "counterpartyAccountCode": "CPT-042",
  "description": "Fleet maintenance — September 2026"
}),
});
console.log(await response.json());
```

## Success (201)

```json
{
  "success": true,
  "data": {
    "id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
    "tenant_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
    "counterparty_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "invoice_number": "INV-2026-0042",
    "kind": "invoice",
    "invoice_type": "issued",
    "status": "unpaid",
    "currency": "EUR",
    "amount_excl_vat": 10000,
    "vat_amount": 2000,
    "amount_incl_vat": 12000,
    "settled_amount": 0,
    "open_amount": 12000,
    "recovery_percent": 0,
    "invoice_date": "2026-09-01T00:00:00.000Z",
    "due_date": "2026-10-01T00:00:00.000Z",
    "payment_expected_date": "2026-10-01T00:00:00.000Z",
    "payment_term_days": null,
    "recipient_name": "Leones Cars",
    "customer_name": "Leones Cars",
    "description": "Fleet maintenance — September 2026",
    "external_reference": "LC-SO-9081",
    "counterparty_name_display": "Leones Cars",
    "is_overdue": false,
    "next_due_date": "2026-10-01",
    "created_at": "2026-09-01T10:00:00.000Z",
    "updated_at": "2026-09-12T09:00:00.000Z",
    "_counterparty_resolution": {
      "method": "account_code",
      "confidence": "exact",
      "created": false,
      "category": "professional"
    },
    "_payment_method_resolution": {
      "status": "none",
      "paymentMethodId": null
    },
    "_wallet": {
      "skipped": true,
      "skipReason": "nothing_to_apply",
      "applied": 0,
      "remainingDue": 12000,
      "currency": "EUR"
    }
  }
}
```
