# Update redemption order status

Move one redemption order to another status, and optionally return the trader's coins when the new status is a refund.

- Endpoint: `PUT https://api.returning.ai/v1/redemption-transactions/status`
- Section: Store and rewards / Rewards and redemptions
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `updateRedemptionTransactionStatus` (Shown in the dashboard as "Update Redemption Transaction Status")
- Retries: No Idempotency-Key; read history first
- Guide: hand-written
- Verified: live, 2026-09-27
- Last updated: 26 Sep 2026
- Web page: https://docs.returning.ai/api-reference/rewards-and-redemptions/update-redemption-order-status

## When to use this

- Your team has fulfilled a reward, and the order should show `Completed`.
- A reward can't be delivered, and the trader should get their coins back.
- Your fulfilment system tracks its own progress and mirrors each step onto the order.

**Instead:** Use [Create redemption order status](https://docs.returning.ai/api-reference/rewards-and-redemptions/create-redemption-order-status.md) instead when you need a status your community doesn't have yet.

**Refunds:** Send `refundCoins` as `true` the first time you move an order to a refunded status. Once an order has been in any refunded status, a later coin refund credits nothing.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `updateRedemptionTransactionStatus`

Use a Community API key with `updateRedemptionTransactionStatus`, and keep it on your server. The key decides the community, so you can only change orders and use statuses in that community.

## Behaviour

You can move an order from any status to any active status in your community; there are no transition rules. Every successful call adds an entry to the order's status history, even when the status is unchanged. The one exception is a repeated refund to the same status. This call doesn't email the trader.

A refund happens only when `refundCoins` is `true` and the new status is in the refunded category. It credits the order's `price` in coins to the trader, recorded in their coin history as a refund. It also returns the voucher to the product's stock if the voucher hasn't expired. If the voucher can't be restocked, the coins are still refunded.

An order is refunded at most once. If it has ever been in a refunded status, even one set without `refundCoins`, a later refund returns `credited: 0` and `alreadyRefunded: true`. Moving an order out of a refunded status doesn't take the coins back. If two requests change the same order at once, only one can credit coins, and the status that finishes last is kept.

## Request

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with `updateRedemptionTransactionStatus`. (`Bearer <API_KEY>`) |
| `Content-Type` | `string` | Yes | Request body format. (`application/json`) |

### Body

Send the order ID (`ORD...`) as `transactionId`. This is the order's `redemptionId` from the order lists, not its internal `_id`. Get status IDs from [List redemption statuses](https://docs.returning.ai/api-reference/rewards-and-redemptions/list-redemption-statuses.md). The field is `statusID` with a capital `ID`. Unknown fields are ignored.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `transactionId` | `string` | Yes | The order ID (`ORD...`) from `redemptionId` in the order lists. Not the order's internal `_id`. (Order ID in your community) |
| `statusID` | `string` | Yes | ID of an active status in your community. Spelled `statusID`; `statusId` is rejected. (Status ID in your community) |
| `refundCoins` | `boolean` | No | `true` returns the order's coins to the trader. Only allowed when the status is in the refunded category. (Boolean; default `false`) |
| `remark` | `string` | No | A note saved with the change and shown in the order's status history. Defaults to `Updated by API`. (Up to 500 characters) |

### Example request

```bash
curl --request PUT \
  --url https://api.returning.ai/v1/redemption-transactions/status \
  --header 'Authorization: Bearer <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "transactionId": "ORD20269268300418273",
    "statusID": "66f000000000000000000402",
    "refundCoins": true,
    "remark": "Reward out of stock"
  }'
```

## Response

A `200` returns the order's new status. When you sent `refundCoins: true`, `data.refund` says whether coins moved: check `credited` and `alreadyRefunded`, not just the `code`.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `status` | `string` | always | Result of the request. (`success`) |
| `message` | `string` | always | Human-readable summary. Do not branch on it. |
| `data` | `object` | always | The order's new status. |
| `data.transactionId` | `string` | always | The order ID you sent. |
| `data.status` | `object` | always | The order's new status. |
| `data.status._id` | `string` | always | Status ID. |
| `data.status.name` | `string` | always | Status name. |
| `data.status.category` | `string` | always | The status category. (`new_purchase`, `in_progress`, `completed` or `refunded`) |
| `data.status.color` | `string` | always | Display color, a hex code. |
| `data.statusID` | `string` | always | The status ID you sent. |
| `data.refund` | `object` | when refundcoins is true | What happened to the coins. Present when you sent `refundCoins: true`. |
| `data.refund.requested` | `boolean` | - | Always `true`. |
| `data.refund.credited` | `number` | - | Coins credited to the trader by this call. `0` when the order was already refunded. |
| `data.refund.alreadyRefunded` | `boolean` | - | `true` when no coins moved because the order had already been refunded. |
| `code` | `string` | always | `REDEMPTION_TRANSACTION_REFUNDED` when you sent `refundCoins: true`, otherwise `REDEMPTION_TRANSACTION_STATUS_UPDATED`. (`REDEMPTION_TRANSACTION_REFUNDED` or `REDEMPTION_TRANSACTION_STATUS_UPDATED`) |

### Example response (200)

```json
{
  "status": "success",
  "code": "REDEMPTION_TRANSACTION_REFUNDED",
  "message": "Transaction status updated successfully",
  "data": {
    "transactionId": "ORD20269268300418273",
    "statusID": "66f000000000000000000402",
    "status": {
      "_id": "66f000000000000000000402",
      "name": "Refunded",
      "category": "refunded",
      "color": "#EB5757"
    },
    "refund": {
      "requested": true,
      "credited": 500,
      "alreadyRefunded": false
    }
  }
}
```

## Errors

401 and 403 responses, and the authentication errors `404 COMMUNITY_NOT_FOUND` and `500 AUTHENTICATION_FAILED`, carry the code in `meta.code`; every other error carries it in `code`. A `400` or `404` changes nothing. A `500` may come after the status has already changed.

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | `VALIDATION_FAILED` | A field is missing or has the wrong type. `detail` names it. Check the `statusID` spelling and send `refundCoins` as a JSON boolean. |
| 400 | `REDEMPTION_REQUEST_INVALID` | `refundCoins` is `true` but the status isn't in the refunded category. Nothing changed. Pick a refunded status, or send `refundCoins: false`. |
| 401 | `AUTHENTICATION_REQUIRED` | The key is missing, invalid or expired. Send `Authorization: Bearer <API_KEY>` with a current Community API key. |
| 403 | `API_KEY_PERMISSION_DENIED` | The key lacks `updateRedemptionTransactionStatus`, or it is a personal key. Use a Community API key and add the permission in Settings > Integration > API Keys. |

### Fix the data

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `REDEMPTION_TRANSACTION_NOT_FOUND` | Nothing changed. `message` says which: `Transaction not found` (use the `ORD...` order ID from the order list, not `_id`) or `Status not found or inactive` (the status is switched off). |
| 404 | `COMMUNITY_NOT_FOUND` | The community this key belongs to no longer exists. Contact Returning.AI support. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 500 | `INTERNAL_ERROR` | The update failed, or `statusID` is not a status in your community. Check the ID with [List redemption statuses](https://docs.returning.ai/api-reference/rewards-and-redemptions/list-redemption-statuses.md). The status may already have changed, so read the status history before you retry. |
| 500 | `AUTHENTICATION_FAILED` | The key could not be checked. Retry with backoff; nothing changed. |

**Retries:** This endpoint doesn't accept an `Idempotency-Key`. Repeating a status change is harmless, but each repeat adds another history entry. A repeated refund that already succeeded returns `credited: 0`. After a timeout or a `500`, read the order's status history and, for refunds, the trader's coins with Get User Data before you send it again. Over the [rate limit](https://docs.returning.ai/how-it-works.md#rate-limits), requests return `429`; wait for the window to reset, then retry.

## Next step

- [Get redemption order status history](https://docs.returning.ai/api-reference/rewards-and-redemptions/get-redemption-order-status-history.md): `POST /v1/redemption-transactions/transaction-history`. Confirm the change was recorded, with your `remark`, in the order's status history.
- [After a refund, check the trader's coins with Get User Data](https://docs.returning.ai/api-reference/users/get-user-data.md): `POST /v1/users/info`.
