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

# POST /api/v1/invoices — Create a Retempo Invoice

> POST /api/v1/invoices — creates a billing invoice for a subscriber. Set amount, due date, and status. Cannot create invoices as PAID directly.

Creating an invoice generates a billing record that ties a subscriber to a specific amount owed under a payment plan. You control the initial status — use `DRAFT` for invoices you are not yet ready to collect on, or `OPEN` to immediately signal that payment is due. Retempo marks an invoice as `PAID` only after a confirmed settlement is recorded against it.

```
POST https://api.retempo.xyz/api/v1/invoices
```

## Request Body

<ParamField body="serviceId" type="string" required>
  The ID of the service this invoice belongs to.
</ParamField>

<ParamField body="paymentPlanId" type="string" required>
  The ID of the payment plan associated with this invoice. The plan must belong to the specified service.
</ParamField>

<ParamField body="userId" type="string" required>
  The ID of the existing Retempo user being billed.
</ParamField>

<ParamField body="amount" type="string | number" required>
  The amount to bill, as a decimal string (e.g. `"49.000000"`) or number. Must be a non-negative value.
</ParamField>

<ParamField body="currency" type="string" default="USDC">
  The currency for the invoice. Defaults to `USDC` if omitted.
</ParamField>

<ParamField body="status" type="string" default="DRAFT">
  The initial status of the invoice. Accepted values: `DRAFT`, `OPEN`, `VOID`, `EXPIRED`. Defaults to `DRAFT`. You cannot set this to `PAID` on creation — doing so returns a `400` error.
</ParamField>

<ParamField body="dueAt" type="string">
  An ISO 8601 datetime string specifying when payment is due. If omitted, no due date is set.
</ParamField>

<ParamField body="subscriptionId" type="string">
  The ID of a subscription to associate with this invoice. Optional — use when the invoice is tied to an ongoing subscription. The subscription must belong to the same service and user.
</ParamField>

## Response

A successful request returns HTTP `201 Created` with the new invoice object and all related records.

<ResponseField name="invoice" type="object">
  The newly created invoice with all related records included.

  <Expandable title="invoice fields">
    <ResponseField name="id" type="string">Unique identifier for the invoice.</ResponseField>
    <ResponseField name="serviceId" type="string">ID of the associated service.</ResponseField>
    <ResponseField name="paymentPlanId" type="string">ID of the associated payment plan.</ResponseField>
    <ResponseField name="userId" type="string">ID of the billed user.</ResponseField>
    <ResponseField name="subscriptionId" type="string | null">ID of the linked subscription, or `null`.</ResponseField>
    <ResponseField name="status" type="string">Current invoice status: `DRAFT`, `OPEN`, `VOID`, or `EXPIRED`.</ResponseField>
    <ResponseField name="amount" type="string">Billed amount as a decimal string with six decimal places.</ResponseField>
    <ResponseField name="currency" type="string">Currency of the invoice.</ResponseField>
    <ResponseField name="dueAt" type="string | null">Due date, or `null` if not set.</ResponseField>
    <ResponseField name="paidAt" type="string | null">Always `null` on creation. Populated only after a settlement is confirmed.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 datetime the invoice was created.</ResponseField>
    <ResponseField name="service" type="object">Nested service object.</ResponseField>
    <ResponseField name="paymentPlan" type="object">Nested payment plan object.</ResponseField>
    <ResponseField name="user" type="object">Nested user object.</ResponseField>
    <ResponseField name="subscription" type="object | null">Nested subscription object if `subscriptionId` was provided, otherwise `null`.</ResponseField>
    <ResponseField name="settlements" type="array">List of settlements recorded against this invoice. Empty on creation.</ResponseField>
    <ResponseField name="usageEvents" type="array">List of usage events linked to this invoice. Empty on creation.</ResponseField>
  </Expandable>
</ResponseField>

### 201 — Invoice created

```json theme={null}
{
  "invoice": {
    "id": "clz1invoice999",
    "serviceId": "clz1abc2def3ghi4",
    "paymentPlanId": "clz1plan567",
    "userId": "clz1user111",
    "subscriptionId": null,
    "status": "OPEN",
    "amount": "49.000000",
    "currency": "USDC",
    "dueAt": "2025-07-01T00:00:00.000Z",
    "paidAt": null,
    "createdAt": "2025-06-01T10:15:00.000Z",
    "service": {
      "id": "clz1abc2def3ghi4",
      "name": "DataStream Pro",
      "status": "ACTIVE"
    },
    "paymentPlan": {
      "id": "clz1plan567",
      "name": "Pro Monthly",
      "amount": "49.000000",
      "currency": "USDC"
    },
    "user": {
      "id": "clz1user111",
      "email": "subscriber@example.com"
    },
    "subscription": null,
    "settlements": [],
    "usageEvents": []
  }
}
```

## Example Request

```bash theme={null}
curl -X POST https://api.retempo.xyz/api/v1/invoices \
  -H "Content-Type: application/json" \
  -d '{
    "serviceId": "clz1abc2def3ghi4",
    "paymentPlanId": "clz1plan567",
    "userId": "clz1user111",
    "amount": "49.000000",
    "status": "OPEN",
    "dueAt": "2025-07-01T00:00:00.000Z"
  }'
```

## Error Codes

| Status            | Message                                                            | Condition                                                               |
| ----------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------- |
| `400 Bad Request` | `serviceId is required.`                                           | `serviceId` was omitted.                                                |
| `400 Bad Request` | `paymentPlanId is required.`                                       | `paymentPlanId` was omitted.                                            |
| `400 Bad Request` | `userId is required.`                                              | `userId` was omitted.                                                   |
| `400 Bad Request` | `amount is required.`                                              | `amount` was omitted.                                                   |
| `400 Bad Request` | `Invoices cannot be created as PAID without a real payment event.` | `status` was set to `PAID`.                                             |
| `400 Bad Request` | `status must be one of: DRAFT, OPEN, PAID, VOID, EXPIRED.`         | An unrecognized status value was provided.                              |
| `404 Not Found`   | `Payment plan was not found for the service.`                      | The plan does not exist or does not belong to the specified service.    |
| `404 Not Found`   | `Referenced database record was not found.`                        | The `userId` was not found.                                             |
| `404 Not Found`   | `Subscription was not found for the service and user.`             | The `subscriptionId` does not belong to the specified service and user. |

<Warning>
  You cannot create an invoice with `status: "PAID"`. An invoice is only marked `PAID` automatically after a confirmed settlement is recorded against it.
</Warning>
