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

# Invoices

Create, send, and manage invoices through the admin API.

For general conventions, see [JSON-API Conventions](/developers/guides/json-api-conventions). For authentication, see [Authentication](/developers/guides/authentication).

***

## Prerequisites

* Bearer token with admin access + `?o={organization_id}`

***

## Invoice Actions

### Cancel an Invoice

```http theme={null}
POST /api/v1/invoices/{invoice_id}/cancel?o={org_id}
```

Creates a credit note and voids the invoice.

### Mark as Paid

Mark a SENT invoice as paid without processing a payment:

```http theme={null}
PUT /api/v1/invoices/{invoice_id}/set-paid?o={org_id}

{
  "send_notification": true
}
```

Set `send_notification` to `true` to email the customer a payment confirmation.

### Change Recipient

Transfers an invoice to a different customer. This cancels the original invoice and creates a new copy for the new recipient:

```http theme={null}
POST /api/v1/invoices/{invoice_id}/change-recipient?o={org_id}

{
  "customer_id": "new-customer-uuid"
}
```

***

## Creating an Invoice

All examples below assume `BASE_URL = https://{your-domain}/api/v1`.

<Steps>
  <Step title="Find a Customer by Email">
    ```http theme={null}
    GET {BASE_URL}/customers?o={org_id}&filter[email]=jane@example.com&include=address
    ```

    The `email` filter performs an exact (case-insensitive) match.

    For a fuzzy name/email/phone search, use the `search` filter instead:

    ```http theme={null}
    GET {BASE_URL}/customers?o={org_id}&filter[search]=jane&include=address
    ```

    #### Filter by Custom Field

    Custom fields are referenced by their UUID. See [Custom Field Filters](/developers/guides/json-api-conventions#custom-field-filters) for the full syntax and supported operators.

    ```http theme={null}
    GET {BASE_URL}/customers?o={org_id}&filter[custom_fields][{FIELD_UUID}][f_id]={FIELD_UUID}&filter[custom_fields][{FIELD_UUID}][o]==&filter[custom_fields][{FIELD_UUID}][v]=Premium
    ```

    For checkbox fields, pass `true` / `false` as the value. For multi-select fields, the `in` operator accepts comma-separated values.
  </Step>

  <Step title="Create a Customer (if not found)">
    ```http theme={null}
    POST {BASE_URL}/customers?o={org_id}
    ```

    ```json theme={null}
    {
      "data": {
        "type": "customers",
        "attributes": {
          "given_name": "Jane",
          "family_name": "Doe",
          "email": "jane@example.com",
          "company": "Acme Inc",
          "locale": "de",
          "mobile": "+4917612345678"
        }
      }
    }
    ```

    **Required:** `email`, `locale`

    Create the customer's address as a separate resource:

    ```http theme={null}
    POST {BASE_URL}/addresses?o={org_id}
    ```

    ```json theme={null}
    {
      "data": {
        "type": "addresses",
        "attributes": {
          "name": "Jane Doe",
          "street_address": "Hauptstraße 42",
          "zip_code": "50667",
          "city": "Köln",
          "country_code": "DE"
        },
        "relationships": {
          "addressable": {
            "data": { "type": "customers", "id": "{customer_id}" }
          }
        }
      }
    }
    ```
  </Step>

  <Step title="Create the Invoice (draft)">
    ```http theme={null}
    POST {BASE_URL}/invoices?o={org_id}
    ```

    ```json theme={null}
    {
      "data": {
        "type": "invoices",
        "attributes": {
          "currency": "EUR",
          "recipient": "Acme Inc\nJane Doe\nHauptstraße 42\n50667 Köln",
          "calculate_from_net": true
        },
        "relationships": {
          "customer": {
            "data": { "type": "customers", "id": "{customer_id}" }
          }
        }
      }
    }
    ```

    #### Customer linking

    | Method                                                        | When to use                                         |
    | ------------------------------------------------------------- | --------------------------------------------------- |
    | `relationships.customer` in the request body                  | Manual invoices — pass the customer ID directly     |
    | `relationships.reference` (order, subscription, booking pass) | Backend derives customer from the referenced entity |
    | Neither                                                       | Create without a customer; link one later via PATCH |

    When the invoice is **sent**, the backend snapshots `recipient` and `buyer_data` from the customer so the invoice stays valid even if the profile changes later.

    #### Attributes

    | Attribute            | Type    | Required | Notes                                                               |
    | -------------------- | ------- | -------- | ------------------------------------------------------------------- |
    | `currency`           | string  | **yes**  | e.g. `"EUR"`, `"USD"`                                               |
    | `recipient`          | string  | no       | Free-text address block; auto-filled from customer on send if blank |
    | `invoicing_party`    | string  | no       | Your company's address block                                        |
    | `calculate_from_net` | boolean | no       | Default `false`. Set `true` when entering net amounts               |
    | `issued_at`          | date    | no       | Required when status ≠ `draft`                                      |
    | `due_date`           | date    | no       |                                                                     |
    | `notes`              | string  | no       | Appears on the invoice                                              |
    | `vat_number`         | string  | no       |                                                                     |
    | `is_quote`           | boolean | no       | Set `true` to create a quote instead                                |
    | `number`             | string  | no       | Must be unique within org if provided                               |
  </Step>

  <Step title="Add Line Items">
    ```http theme={null}
    POST {BASE_URL}/items?o={org_id}&calculate_from_net=true
    ```

    ```json theme={null}
    {
      "data": {
        "type": "items",
        "attributes": {
          "title": "Consulting — March 2026",
          "quantity": 10,
          "single_net_amount": 150.00,
          "tax_rate": 19
        },
        "relationships": {
          "document": {
            "data": { "type": "invoices", "id": "{invoice_id}" }
          }
        }
      }
    }
    ```

    | Attribute             | Type    | Required  | Notes                                    |
    | --------------------- | ------- | --------- | ---------------------------------------- |
    | `title`               | string  | **yes**   | Max 185 chars                            |
    | `quantity`            | integer | **yes**   |                                          |
    | `tax_rate`            | number  | **yes**   | ≥ 0 (e.g. `19` for 19%)                  |
    | `single_net_amount`   | number  | **yes**\* | Required when `calculate_from_net=true`  |
    | `single_gross_amount` | number  | **yes**\* | Required when `calculate_from_net=false` |
    | `subtitle`            | string  | no        | Max 185 chars                            |

    \* Provide the amount matching the invoice direction. The backend derives the other automatically.

    Repeat for each line item. Invoice totals recalculate after each item.
  </Step>

  <Step title="Send the Invoice">
    ```http theme={null}
    POST {BASE_URL}/invoices/{invoice_id}/send?o={org_id}
    ```

    Transitions status to `sent` and delivers via the configured notification channel.
  </Step>

  <Step title="Mark as Paid (optional)">
    ```http theme={null}
    POST {BASE_URL}/invoices/{invoice_id}/set-paid?o={org_id}&sendNotification=true
    ```
  </Step>
</Steps>

***

## Full Workflow Summary

```text theme={null}
1. GET  /customers?filter[email]=...&include=address     → Find customer
2. POST /customers                                        → Create customer (if new)
3. POST /addresses                                        → Create customer address (if new)
4. POST /invoices                                         → Create draft invoice
5. POST /items  (repeat per line item)                    → Add line items
6. POST /invoices/{id}/send                               → Send invoice
7. POST /invoices/{id}/set-paid                           → Mark as paid
```

All endpoints include `?o={organization_id}` for tenant context.

***

## Common Errors

| Error                              | Cause                                       | Solution                                      |
| ---------------------------------- | ------------------------------------------- | --------------------------------------------- |
| `403` — unauthorized               | Missing permissions for invoice operations  | Ensure admin token has the required abilities |
| `422` — invoice not in SENT status | `set-paid` on draft or already-paid invoice | Check invoice status first                    |
