# POST /api/public/orders/{orderId}/send-to-device

> Send Order to Device

Pushes the order to one of the merchant's Rivr devices (tablets) so the customer can pay on it —
the same action as "Send to terminal" in the Rivr portal. The order must be in status **Created**.
The device must be registered to the merchant that owns the order and be online; list the merchant's
devices and their online status with `GET /api/public/devices`. Delivery to the device is
asynchronous, and the payment result is reported the usual way (order status and the order callback).

**Retrying safely.** Without a header, a request that is sent again pushes the order to the device again. Send an
`Idempotency-Key` header (a new UUID for every send) to make a retry safe. 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`, and the device does not get the order a second time. A response
that refused the request (4xx) is not stored, so the same key can be retried once the cause is gone, for example
when the device was offline. 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, another device or another body.
Nothing was done. Use a new key.
- **500** `idempotency_outcome_unknown`: the request failed after the order may have been sent to the device. The
same key gives this answer again for 24 hours. Check the order and the device 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.

- Surface: `/api/public` · operationId `sendOrderToDevice` · 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/sendOrderToDevice

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 send. |
| `Idempotency-Key` | header | string | no | Optional. A key of 1 to 255 printable ASCII characters, unique for every send (a UUID is recommended). Retrying with the same key and the same request returns the stored response instead of sending the order to the device again. Stored for 24 hours. |

## Request body (`application/json`, optional)

The device to send the order to, as a JSON body.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `deviceId` | string (uuid) | – | The identifier of the device to send the order to. Use `GET /api/public/devices` to list the merchant's devices and their online status. |

**Example**

```json
{
  "deviceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
```

## Responses

### 202

Accepted

### 400

The order cannot be sent: the order id is not a UUID, `deviceId` is missing, the order is not in status
**Created**, or no device with the id is registered to the merchant. The body is an error object with
`propertyName` and `message`, and the `code` `order_id_invalid`, `device_id_required`, `order_not_sendable` or
`device_not_found`. With an Idempotency-Key header also `idempotency_key_invalid`. A request that cannot be read is rejected before the operation runs, with a validation problem instead: malformed JSON, a value of the wrong type or an empty body. It carries the `code` `request_invalid`, `type`, `message`, `title`, `status`, `errors` (the messages per field) and `traceId`.

Error codes: [request_invalid](https://developers.rivr.io/errors/request_invalid.md), [order_id_invalid](https://developers.rivr.io/errors/order_id_invalid.md), [device_id_required](https://developers.rivr.io/errors/device_id_required.md), [order_not_sendable](https://developers.rivr.io/errors/order_not_sendable.md), [device_not_found](https://developers.rivr.io/errors/device_not_found.md), [idempotency_key_invalid](https://developers.rivr.io/errors/idempotency_key_invalid.md)

`application/json`

```json
{
  "propertyName": "DeviceId",
  "message": "The deviceId is required",
  "errorCode": "device_id_required",
  "code": "device_id_required",
  "type": "https://developers.rivr.io/errors/device_id_required"
}
```

### 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`.

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 device is offline: `device_offline`. Retry when it is online. With an Idempotency-Key header also
`idempotency_in_progress`.

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

`application/json`

```json
{
  "propertyName": "DeviceId",
  "message": "The device is offline and cannot receive the order right now. Retry when it is online.",
  "errorCode": "device_offline",
  "code": "device_offline",
  "type": "https://developers.rivr.io/errors/device_offline"
}
```

### 415

The body is not sent as `application/json`: `unsupported_media_type`.

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

`application/json`

```json
{
  "type": "https://developers.rivr.io/errors/unsupported_media_type",
  "title": "Unsupported Media Type",
  "status": 415,
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-00",
  "code": "unsupported_media_type",
  "message": "The body's Content-Type is not one the operation reads. Send the body as application/json."
}
```

### 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 and the device 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/send-to-device \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "deviceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'
```
