> ## 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/settlements — Submit a USDC Settlement

> POST /api/v1/settlements — submits a USDC settlement for an invoice. Returns CONFIRMED with transaction details after on-chain receipt is verified.

Submitting a settlement closes an invoice by recording proof of USDC payment on Arc. You provide the invoice ID, a unique reference hash, and the payer and merchant wallet addresses. Retempo submits the transaction, waits for an on-chain receipt and a `SettlementRecorded` event, then returns the settlement as `CONFIRMED`. The associated invoice is automatically marked `PAID` at the same time.

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

## Request Body

<ParamField body="invoiceId" type="string" required>
  The ID of the invoice this settlement closes.
</ParamField>

<ParamField body="referenceHash" type="string" required>
  A unique 32-byte identifier for this settlement, encoded as a hex string — `0x` followed by exactly 64 hex characters (e.g. `0xabcdef12...`). You generate this value and use it to deduplicate submissions. Submissions with a malformed hash are rejected with `400`.
</ParamField>

<ParamField body="payerAddress" type="string" required>
  The EVM wallet address of the payer. Must be a valid, non-zero checksummed address.
</ParamField>

<ParamField body="merchantAddress" type="string" required>
  The EVM wallet address of the merchant. Must be a valid, non-zero checksummed address.
</ParamField>

<ParamField body="payerId" type="string">
  The Retempo user ID of the payer. If provided, it must match the `userId` on the invoice. If omitted, defaults to the invoice's `userId`.
</ParamField>

<ParamField body="merchantId" type="string">
  The Retempo user ID of the merchant. If provided, it must match the `ownerId` of the associated service. If omitted, defaults to the service owner.
</ParamField>

<ParamField body="amount" type="string | number">
  The settlement amount as a decimal string or number. If omitted, Retempo uses the invoice amount. Must be a non-negative decimal.
</ParamField>

<ParamField body="currency" type="string">
  The currency of the settlement. Defaults to the invoice currency if omitted.
</ParamField>

<ParamField body="recordedAt" type="string">
  An ISO 8601 datetime string for when the settlement occurred. Defaults to the time of the API call if omitted.
</ParamField>

## Response

A successful settlement returns HTTP `201 Created` with both a `settlement` object and a `chain` object containing the on-chain transaction details.

<ResponseField name="settlement" type="object">
  The confirmed settlement record with related objects.

  <Expandable title="settlement fields">
    <ResponseField name="id" type="string">Unique identifier for the settlement.</ResponseField>
    <ResponseField name="invoiceId" type="string">ID of the closed invoice.</ResponseField>
    <ResponseField name="serviceId" type="string">ID of the associated service.</ResponseField>
    <ResponseField name="payerId" type="string">Retempo user ID of the payer.</ResponseField>
    <ResponseField name="merchantId" type="string">Retempo user ID of the merchant.</ResponseField>
    <ResponseField name="amount" type="string">Settled amount as a decimal string with six decimal places.</ResponseField>
    <ResponseField name="currency" type="string">Currency of the settlement.</ResponseField>
    <ResponseField name="referenceHash" type="string">The reference hash you supplied.</ResponseField>
    <ResponseField name="transactionHash" type="string">The on-chain transaction hash.</ResponseField>
    <ResponseField name="status" type="string">`CONFIRMED` once the on-chain receipt is verified, or `FAILED` if the transaction did not succeed.</ResponseField>
    <ResponseField name="recordedAt" type="string">Datetime the settlement was recorded.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 datetime the settlement was created.</ResponseField>
    <ResponseField name="invoice" type="object">Nested invoice object.</ResponseField>
    <ResponseField name="service" type="object">Nested service object.</ResponseField>
    <ResponseField name="payer" type="object">Nested payer user object.</ResponseField>
    <ResponseField name="merchant" type="object">Nested merchant user object.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="chain" type="object">
  On-chain transaction details returned alongside the settlement.

  <Expandable title="chain fields">
    <ResponseField name="transactionHash" type="string">The on-chain transaction hash.</ResponseField>
    <ResponseField name="receiptStatus" type="string">Receipt status — `success` when confirmed.</ResponseField>
    <ResponseField name="eventObserved" type="boolean">`true` when the `SettlementRecorded` event was detected in the transaction receipt.</ResponseField>
    <ResponseField name="executor" type="string">The execution method used — `direct` or `circle`.</ResponseField>
    <ResponseField name="circleTransactionId" type="string | null">Circle transaction identifier when the `circle` executor was used, otherwise absent.</ResponseField>
    <ResponseField name="circleTransactionState" type="string | null">Circle transaction state when applicable — e.g. `COMPLETE`. Otherwise absent.</ResponseField>
  </Expandable>
</ResponseField>

### 201 — Settlement confirmed

```json theme={null}
{
  "settlement": {
    "id": "clz1settle222",
    "invoiceId": "clz1invoice999",
    "serviceId": "clz1abc2def3ghi4",
    "payerId": "clz1user111",
    "merchantId": "clz1owner123",
    "amount": "49.000000",
    "currency": "USDC",
    "referenceHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "transactionHash": "0x9f8e7d6c5b4a392817263544536271819f0e1d2c3b4a5968...",
    "status": "CONFIRMED",
    "recordedAt": "2025-06-01T10:20:00.000Z",
    "createdAt": "2025-06-01T10:20:00.000Z",
    "invoice": {
      "id": "clz1invoice999",
      "status": "PAID",
      "amount": "49.000000",
      "currency": "USDC",
      "paidAt": "2025-06-01T10:20:00.000Z"
    },
    "service": {
      "id": "clz1abc2def3ghi4",
      "name": "DataStream Pro"
    },
    "payer": {
      "id": "clz1user111",
      "email": "subscriber@example.com"
    },
    "merchant": {
      "id": "clz1owner123",
      "email": "owner@datastreampro.com"
    }
  },
  "chain": {
    "transactionHash": "0x9f8e7d6c5b4a392817263544536271819f0e1d2c3b4a5968...",
    "receiptStatus": "success",
    "eventObserved": true,
    "executor": "direct",
    "circleTransactionId": null,
    "circleTransactionState": null
  }
}
```

## Example Request

```bash theme={null}
curl -X POST https://api.retempo.xyz/api/v1/settlements \
  -H "Content-Type: application/json" \
  -d '{
    "invoiceId": "clz1invoice999",
    "referenceHash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
    "payerAddress": "0x1234567890abcdef1234567890abcdef12345678",
    "merchantAddress": "0xabcdef1234567890abcdef1234567890abcdef12",
    "amount": "49.000000"
  }'
```

## Error Codes

| Status                      | Message                                             | Condition                                                         |
| --------------------------- | --------------------------------------------------- | ----------------------------------------------------------------- |
| `400 Bad Request`           | `invoiceId is required.`                            | `invoiceId` was omitted.                                          |
| `400 Bad Request`           | `referenceHash is required.`                        | `referenceHash` was omitted.                                      |
| `400 Bad Request`           | `referenceHash must be a 32-byte hex value.`        | The hash is not `0x` + exactly 64 hex characters.                 |
| `400 Bad Request`           | `payerAddress must be a valid address.`             | `payerAddress` is missing or is not a valid EVM address.          |
| `400 Bad Request`           | `merchantAddress must be a valid address.`          | `merchantAddress` is missing or is not a valid EVM address.       |
| `400 Bad Request`           | `Settlement payer must match the invoice user.`     | The provided `payerId` does not match the invoice's `userId`.     |
| `400 Bad Request`           | `Settlement merchant must match the service owner.` | The provided `merchantId` does not match the service's `ownerId`. |
| `404 Not Found`             | `Referenced database record was not found.`         | The `invoiceId` was not found.                                    |
| `500 Internal Server Error` | *(error message)*                                   | The on-chain transaction failed or could not be verified.         |

## Idempotency

Settlements are idempotent on the combination of `invoiceId` and `referenceHash`. If you submit a settlement with the same pair and a matching settlement already exists in `CONFIRMED` status, Retempo returns `200` with the existing settlement record instead of creating a duplicate. Use this behavior to safely retry on network failures without risk of double-charging.

<Warning>
  The `referenceHash` must be exactly 32 bytes as a hex string — `0x` followed by exactly 64 hex characters. Submissions with a malformed hash are rejected immediately with a `400` error and the message `"referenceHash must be a 32-byte hex value."`.
</Warning>

<Note>
  A settlement is marked `CONFIRMED` only after a real on-chain transaction receipt and `SettlementRecorded` event are observed. The endpoint does not return until that verification is complete. If verification fails, the settlement is recorded as `FAILED` and a `500` is returned.
</Note>
