# GET /api/public/orders/{orderId}

> Retrieve Order

If the order is not found, the HTTP status 204 is returned.

- Surface: `/api/public` · operationId `getOrder` · Group: Order
- Authorisation: Token with scope `public:orders:read`
- Organisation key: needs the capabilities `orders:read` + `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/getOrder

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 retrieve. |

## Responses

### 200

OK

`application/json`

**Response fields**

| Field | Type | Description |
| --- | --- | --- |
| `id` | string (uuid) |  |
| `createdDate` | string (date-time) |  |
| `modifiedDate` | string (date-time) |  |
| `version` | integer (int32) | (nullable) |
| `merchantId` | string (uuid) |  |
| `shortId` | string | (nullable) |
| `checkoutUrl` | string | The patient-facing checkout URL for this order. It is the same entry link Rivr sends by text message, so it resolves to whichever checkout the merchant is on, and to My Pages once the order is paid. Send the patient here to pay in the browser, for example while booking. Null when the order has no short id yet, which is the case only for orders created before short ids existed. Do not build the URL yourself, and do not cache it across environments: the host differs per environment. (nullable) |
| `merchantName` | string | (nullable) |
| `currencyCode` | string |  |
| `customer` | PublicApiCommonCustomer |  |
| `customer.id` | string (uuid) |  |
| `customer.createdDate` | string (date-time) |  |
| `customer.modifiedDate` | string (date-time) |  |
| `customer.version` | integer (int32) | (nullable) |
| `customer.personalNumber` | string | (nullable) |
| `customer.firstName` | string | (nullable) |
| `customer.lastName` | string | (nullable) |
| `customer.name` | string | Display name: `firstName` and `lastName` joined with a space. Empty parts are skipped, so a customer with a single name does not get a leading or trailing space (for example `"Acme "`). `null` when both are empty. (nullable) |
| `customer.email` | string | (nullable) |
| `customer.phone` | string | (nullable) |
| `customer.address` | PublicApiAddress |  |
| `customer.address.street` | string | (nullable) |
| `customer.address.street2` | string | (nullable) |
| `customer.address.postalCode` | string | (nullable) |
| `customer.address.city` | string | (nullable) |
| `customer.address.country` | string | (nullable) |
| `orderLines` | OrderLinePublic[] |  |
| `orderLines[].description` | string | The name of the product or service |
| `orderLines[].quantity` | number (double) | The quantity of the product or service |
| `orderLines[].unitPriceExclVat` | number (double) | The price of one unit of the product or service, excluding VAT |
| `orderLines[].vatPercentage` | integer (int32) | The VAT rate of the product or service (0, 6, 12 or 25) |
| `orderLines[].discountExclVat` | number (double) | Optional discount amount excluding VAT applied to this line. The discount is subtracted from the line total (`unitPriceExclVat * quantity`) before VAT is calculated. |
| `orderLines[].isEncrypted` | boolean |  |
| `orderLines[].unitPriceInclVat` | number (double) |  |
| `orderLines[].amountInclVat` | number (double) |  |
| `orderLines[].amountExclVat` | number (double) |  |
| `amount` | number (double) |  |
| `amountExclVat` | number (double) |  |
| `vatAmount` | number (double) |  |
| `reference` | string | (nullable) |
| `ocr` | string | (nullable) |
| `paymentMethod` | PaymentMethodPublic | (Values: 0 = NotPaid, 1 = Card, 2 = Swish, 3 = Invoice, 4 = Instalment, 5 = Vipps, 6 = Trustly, 7 = Direct, 8 = Unknown) |
| `status` | OrderStatus | (Values: 0 = None, 1 = Created, 2 = Pending, 4 = Completed, 8 = Refunded, 32 = Cancelled) |
| `success` | boolean |  |
| `callbackUrl` | string | (nullable) |
| `checkoutHints` | PublicApiCheckoutHint[] | The hints stored on the order. Each hint has a `type` and a `value`; the description of a hint says what each type means. |
| `checkoutHints[].type` | PublicApiCheckoutHintType | The checkout hint type as a string, written in PascalCase (for example `Device`). What `value` must hold for each type is described on the `value` field of the hint. (Values: Device, Redirect, DisableNotifications, AdvancePayment, AutoCancelInSeconds, ChargeStoredCard, DisableDescriptionEncryption, CancelRedirect) |
| `checkoutHints[].value` | string | The value of the hint. What it must hold depends on `type`. Types are written here as they are sent in a request. A value that does not follow its rule has no effect, as if the hint was not sent, except where the rule says that the order is rejected. - `device`: the `id` (a UUID) of one of the merchant's devices, as listed by `GET /api/public/devices`. When the order is created, Rivr sends it to that device if the device is online, so that the patient can pay on it. A value that is not a UUID is ignored, and so is the id of a device that is not one of the merchant's (an unknown id, or a device of another merchant): the order is then never sent to that device, and the merchant's own devices are used as if the hint was not sent. - `redirect`: an absolute `https` URL. When the order has been paid, the Rivr checkout sends the patient's browser to this URL with `rivr_status=completed` added to the query. If the order also has a `cancelRedirect` hint, a payment that is still pending (for example when the patient chose an invoice) sends the patient here with `rivr_status=pending`. The parameter is only a hint about what to show; learn the outcome from the order callback. Use `https`. A plain `http` URL is let through when the order is created, but the checkout redirects only to `https` URLs and to `http` URLs on localhost (`localhost`, `127.0.0.1` or `[::1]`). A value that is missing, relative or of another scheme is rejected with HTTP 422 and the code `checkout_hint_redirect_invalid`. - `disableNotifications`: `true` (read as a boolean, so letter case does not matter). Any other value, or none, leaves notifications on. With `true`, Rivr does not send the payment link by SMS or by email, the reminder SMS, the payment confirmation email or the SMS about a refund. Two messages are not affected: the receipt SMS after a payment on a payment terminal (sent when Rivr has no email address to send the receipt to, or when the patient already got an SMS for the order), and the cancellation SMS to a patient who already got an SMS for the order. - `advancePayment`: the value is not read, so any value or none has the same effect. Rivr marks the order as an advance payment in its settlement data (the order's row in the settlement gets the metadata key `AdvancePayment` with the value `true`) and leaves it out of the Nets payment file of the settlement. - `autoCancelInSeconds`: a positive whole number of seconds, for example `1800`. When that time has passed since the order was created, or since it was restarted, Rivr cancels the order if it is still unpaid (status `Created`) and can still be cancelled. Otherwise it is left as it is. A value that is not a whole number is ignored. - `chargeStoredCard`: leave the value out, or send `true`; only the value `false` switches the hint off. When the order is created, the Rivr checkout tries to charge a card that the patient has saved at this clinic. A card saved at another clinic is never used. The payment link is sent as usual unless `disableNotifications` is also set; if there is no usable saved card, or the charge cannot be made, the patient pays through that link. Only the Rivr checkout acts on this hint. - `disableDescriptionEncryption`: `true` (read as a boolean, so letter case does not matter). Any other value, or none, leaves encryption as it is configured. With `true`, Rivr stores the order line descriptions of this order, and of an invoice that Rivr later creates from the order, in plain text. Without it, a merchant that Rivr has set up to encrypt descriptions gets them encrypted, with a generic label shown in their place. It makes no difference for a merchant that does not encrypt descriptions. - `cancelRedirect`: an absolute `https` URL. The patient is sent here when the payment did not happen: the patient cancelled in the checkout, the order was already cancelled when the patient opened the payment link, or the checkout session expired. `rivr_status=cancelled` or `rivr_status=expired` is added to the query, as a hint only. A value that is missing, is not an absolute `https` URL, or is an `http` URL other than one on localhost outside production (`localhost`, `127.0.0.1` or `[::1]`) is rejected with HTTP 422 and the code `checkout_hint_cancel_redirect_invalid`. (nullable) |
| `metadata` | map<string, string> |  |
| `receipts` | OrderReceiptInfo[] |  |
| `receipts[].id` | string (uuid) |  |
| `receipts[].date` | string (date-time) |  |
| `receipts[].paymentMethod` | PaymentMethodPublic | (Values: 0 = NotPaid, 1 = Card, 2 = Swish, 3 = Invoice, 4 = Instalment, 5 = Vipps, 6 = Trustly, 7 = Direct, 8 = Unknown) |
| `receipts[].receiptFormat` | ReceiptFormat | (Values: 0 = None, 1 = Json, 2 = Pdf) |

**Example**

```json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "createdDate": "2026-10-18T09:00:00Z",
  "modifiedDate": "2026-10-18T09:00:00Z",
  "version": 0,
  "merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "shortId": "string",
  "checkoutUrl": "https://rivr.io/o/a1b2c3",
  "merchantName": "string",
  "currencyCode": "string",
  "customer": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "createdDate": "2026-10-18T09:00:00Z",
    "modifiedDate": "2026-10-18T09:00:00Z",
    "version": 0,
    "personalNumber": "string",
    "firstName": "string",
    "lastName": "string",
    "name": "string",
    "email": "string",
    "phone": "string",
    "address": {
      "street": "string",
      "street2": "string",
      "postalCode": "string",
      "city": "string",
      "country": "string"
    }
  },
  "orderLines": [
    {
      "description": "Product 1",
      "quantity": 1,
      "unitPriceExclVat": 2500,
      "vatPercentage": 25,
      "discountExclVat": 0,
      "isEncrypted": false,
      "unitPriceInclVat": 0,
      "amountInclVat": 0,
      "amountExclVat": 0
    }
  ],
  "amount": 0,
  "amountExclVat": 0,
  "vatAmount": 0,
  "reference": "string",
  "ocr": "string",
  "paymentMethod": 1,
  "status": 1,
  "success": false,
  "callbackUrl": "string",
  "checkoutHints": [
    {
      "type": "Device",
      "value": "string"
    }
  ],
  "metadata": {
    "key": "string"
  },
  "receipts": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "date": "2026-10-18T09:00:00Z",
      "paymentMethod": 1,
      "receiptFormat": 1
    }
  ]
}
```

### 204

The order is not found.

### 400

The order id is not a UUID: `order_id_invalid`, with `propertyName` `orderId`.

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

`application/json`

```json
{
  "propertyName": "orderId",
  "message": "The orderId is not a valid Guid",
  "errorCode": "order_id_invalid",
  "code": "order_id_invalid",
  "type": "https://developers.rivr.io/errors/order_id_invalid"
}
```

### 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:read' is required.",
  "propertyName": null,
  "message": "The scope(s) 'public:orders:read' is required.",
  "errorCode": "invalid_scope",
  "code": "invalid_scope",
  "type": "https://developers.rivr.io/errors/invalid_scope"
}
```

### 500

Something unexpected failed: `internal_error`.

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

`application/json`

```json
{
  "propertyName": null,
  "message": "Something unexpected failed at Rivr, and whether the request was carried out is not known. Check the order or what the request was about before you retry.",
  "errorCode": "internal_error",
  "code": "internal_error",
  "type": "https://developers.rivr.io/errors/internal_error"
}
```

## Example request

```bash
curl -X GET https://api.test.rivr.io/api/public/orders/da4316b7-e2f4-42b0-b0a8-1ed6c24f9738 \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```
