# POST /api/public/orders/{orderId}/refund

> Refund Order

The order must be in a state where it can be refunded. Acceptable states are:
**Created**, **Pending** and **Completed**.

A refund of a completed order that was paid by card or Swish can be refused because the order's claim has been
sold and transferred to a buyer. The response then carries a machine-readable `errorCode`:

- **400** `claim_transferred`: the payment is not refunded through the API, and retrying will not change that.
Contact Rivr.
- **409** `claim_check_unavailable`: whether the payment belongs to the buyer could not be checked right now, and
nothing was refunded. Retry.

A **409** with `order_changed` means that the order changed meanwhile: send the same request again. A **409** with
`payment_in_progress` means that another payment is in progress: send the request again once that payment has
finished or been abandoned, and follow the order with `GET /api/public/orders/{orderId}`.

A **404** with `order_not_found` means that no order with this id is available to the API key, and nothing was
refunded. Check that the request uses the API key issued for the merchant that owns the order.

**Retrying safely.** Send an `Idempotency-Key` header (a new UUID for every refund) to make the request safe to
retry. The key must be a random value and must not contain personal data. It is scoped to your API client (and the
merchant, when the token is issued for one; or the merchant alone, for a token issued with merchant credentials
only) and to this endpoint. The first response with a 2xx status is stored for 24 hours, and a request with the same
key and the same order and body gets that response again, with the header `Idempotent-Replayed: true`, instead of a
second refund. A response that refused the refund (4xx) is not stored, so the same key can be retried once the
cause is fixed. With the header, the response can also carry these `errorCode` values, always with `propertyName`
`Idempotency-Key`:

- **400** `idempotency_key_invalid`: the header is not a single value of 1 to 255 printable ASCII characters, or
the token identifies neither an API client nor a merchant. Nothing was done.
- **409** `idempotency_in_progress`: a request with the same key is still being processed. Retry shortly with the
same key. If Rivr was interrupted while processing it, this answer can last for up to 24 hours; if it persists
for more than a few minutes, check the order before you retry with a new key.
- **422** `idempotency_mismatch`: the key was already used for another order or another body. Nothing was done.
Use a new key.
- **500** `idempotency_outcome_unknown`: the request failed after the refund may have been started. The same key
gives this answer again for 24 hours. Check the order before you retry with a new key.
- **503** `idempotency_unavailable`: the key could not be checked, and nothing was done. Retry with the same key.

Without the header the endpoint behaves exactly as before. Partial refunds are not available in this API.

- Surface: `/api/public` · operationId `refundOrder` · Group: Order
- Authorisation: Token with scope `public:orders:write`
- Organisation key: needs the capabilities `orders:manage` + `customers:read` on the clinic, all together
- The spec: https://developers.rivr.io/openapi/api-public.json
- The spec's introduction: https://developers.rivr.io/reference/api-public.md
- Page in the portal: https://developers.rivr.io/reference/api-public/refundOrder

The examples target the sandbox (`https://api.test.rivr.io`) and need test credentials.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orderId` | path | string | yes | The identifier of the order to refund. |
| `Idempotency-Key` | header | string | no | Optional. A key of 1 to 255 printable ASCII characters, unique for every refund (a UUID is recommended). Retrying with the same key and the same request returns the stored response instead of refunding again. Stored for 24 hours. |

## Responses

### 204

No Content

### 400

The order cannot be refunded, and retrying will not change that: `claim_transferred`, `payment_pending` (a Medical
Finance disbursement or a bank payment reference that can still receive funds), `order_locked_for_refund` (the order
is locked against refunds) or `order_not_refundable` (the order's status cannot be refunded; `message` says which).
With an Idempotency-Key header also `idempotency_key_invalid`. A rule in Rivr that refuses the refund gives
`request_rejected` with the reason in `message`.

Error codes: [request_rejected](https://developers.rivr.io/errors/request_rejected.md), [payment_pending](https://developers.rivr.io/errors/payment_pending.md), [claim_transferred](https://developers.rivr.io/errors/claim_transferred.md), [order_locked_for_refund](https://developers.rivr.io/errors/order_locked_for_refund.md), [order_not_refundable](https://developers.rivr.io/errors/order_not_refundable.md), [idempotency_key_invalid](https://developers.rivr.io/errors/idempotency_key_invalid.md)

`application/json`

```json
{
  "propertyName": "HasIrreversibleMedicalFinanceDraw",
  "message": "The order has a Medical Finance disbursement in progress and cannot be cancelled. A disbursement cannot be reversed — contact Medical Finance to stop it.",
  "errorCode": "payment_pending",
  "code": "payment_pending",
  "type": "https://developers.rivr.io/errors/payment_pending"
}
```

### 401

The token is missing (`token_missing`), not valid (`token_invalid`), expired (`token_expired`) or could not be
checked (`authentication_unavailable`).

Error codes: [token_missing](https://developers.rivr.io/errors/token_missing.md), [token_invalid](https://developers.rivr.io/errors/token_invalid.md), [token_expired](https://developers.rivr.io/errors/token_expired.md), [authentication_unavailable](https://developers.rivr.io/errors/authentication_unavailable.md)

`application/json`

```json
{
  "title": "Unauthorized",
  "status": 401,
  "detail": "Invalid Authorization Header",
  "propertyName": null,
  "message": "The request has no valid Authorization header. Send the token in the Authorization header, after Bearer.",
  "errorCode": "token_missing",
  "code": "token_missing",
  "type": "https://developers.rivr.io/errors/token_missing"
}
```

### 403

The token lacks the scope (`invalid_scope`), is a rivr-auth token that is not a clinic token
(`clinic_token_required`), or the order belongs to another merchant on the same platform (`merchant_mismatch`). The
body also carries `error` and `error_description`, as before.

Error codes: [invalid_scope](https://developers.rivr.io/errors/invalid_scope.md), [clinic_token_required](https://developers.rivr.io/errors/clinic_token_required.md), [merchant_mismatch](https://developers.rivr.io/errors/merchant_mismatch.md)

`application/json`

```json
{
  "error": "invalid_scope",
  "error_description": "The scope(s) 'public:orders:write' is required.",
  "propertyName": null,
  "message": "The scope(s) 'public:orders:write' is required.",
  "errorCode": "invalid_scope",
  "code": "invalid_scope",
  "type": "https://developers.rivr.io/errors/invalid_scope"
}
```

### 404

No order with this id is available to the API key: `order_not_found`. Nothing was refunded.

Error codes: [order_not_found](https://developers.rivr.io/errors/order_not_found.md)

`application/json`

```json
{
  "propertyName": "orderId",
  "message": "The order was not found",
  "errorCode": "order_not_found",
  "code": "order_not_found",
  "type": "https://developers.rivr.io/errors/order_not_found"
}
```

### 409

The same request can succeed later: `payment_in_progress`, `order_changed` or `claim_check_unavailable`; with an
Idempotency-Key header also `idempotency_in_progress`.

Error codes: [payment_in_progress](https://developers.rivr.io/errors/payment_in_progress.md), [order_changed](https://developers.rivr.io/errors/order_changed.md), [claim_check_unavailable](https://developers.rivr.io/errors/claim_check_unavailable.md), [idempotency_in_progress](https://developers.rivr.io/errors/idempotency_in_progress.md)

`application/json`

```json
{
  "propertyName": "HasInFlightTerminalPaymentAttempt",
  "message": "A terminal payment attempt is in flight for this order and it cannot be cancelled right now. Retry once the attempt has completed or failed.",
  "errorCode": "payment_in_progress",
  "code": "payment_in_progress",
  "type": "https://developers.rivr.io/errors/payment_in_progress"
}
```

### 422

With an Idempotency-Key header: `idempotency_mismatch`.

Error codes: [idempotency_mismatch](https://developers.rivr.io/errors/idempotency_mismatch.md)

`application/json`

```json
{
  "propertyName": "Idempotency-Key",
  "message": "The Idempotency-Key has already been used for a different request (another order or another request body). Nothing was done. Use a new key for every new request.",
  "errorCode": "idempotency_mismatch",
  "code": "idempotency_mismatch",
  "type": "https://developers.rivr.io/errors/idempotency_mismatch"
}
```

### 500

With an Idempotency-Key header: `idempotency_outcome_unknown`; the same key gives this answer again for 24 hours. Without the header: `internal_error`, something unexpected failed. In both cases check the order before you retry.

Error codes: [idempotency_outcome_unknown](https://developers.rivr.io/errors/idempotency_outcome_unknown.md), [internal_error](https://developers.rivr.io/errors/internal_error.md)

`application/json`

```json
{
  "propertyName": "Idempotency-Key",
  "message": "The request failed after the change may have been made, so its outcome is unknown. The request is not repeated for this Idempotency-Key. Check the order or subscription before you retry with a new key.",
  "errorCode": "idempotency_outcome_unknown",
  "code": "idempotency_outcome_unknown",
  "type": "https://developers.rivr.io/errors/idempotency_outcome_unknown"
}
```

### 503

With an Idempotency-Key header: `idempotency_unavailable`. Without the header the endpoint does not return 503 itself.

Error codes: [idempotency_unavailable](https://developers.rivr.io/errors/idempotency_unavailable.md)

`application/json`

```json
{
  "propertyName": "Idempotency-Key",
  "message": "The Idempotency-Key could not be checked right now, so nothing was done. Retry the request with the same key.",
  "errorCode": "idempotency_unavailable",
  "code": "idempotency_unavailable",
  "type": "https://developers.rivr.io/errors/idempotency_unavailable"
}
```

## Example request

```bash
curl -X POST https://api.test.rivr.io/api/public/orders/da4316b7-e2f4-42b0-b0a8-1ed6c24f9738/refund \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"
```
