# GET /api/public/onboarding-links/{id}

> Retrieve onboarding link

The current status of one onboarding.

The endpoint to poll: call it when you want to know whether the clinic has moved on, or when you show your own
status page.

- Surface: `/api/public` · operationId `getOnboardingLink` · Group: OnboardingLinks
- Authorisation: Token with scope `public:onboarding:read`
- Organisation key: can't reach this route: the key check answers 403 `route_not_available`. Use a platform token for it.
- 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/getOnboardingLink

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

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | yes |  |

## Responses

### 200

OK

`application/json`

**Response fields**

| Field | Type | Description |
| --- | --- | --- |
| `id` | string (uuid) | Your stable handle on the onboarding. Keep it: it is the key for the status lookups, and it stays the same when the clinic changes email address or gets a new link. |
| `organisationNumber` | string | The clinic's organisation number as Rivr normalises it: a Swedish number as `NNNNNN-NNNN`, with a hyphen, and a Norwegian number as nine digits. |
| `companyName` | string | The company name stored on the onboarding, for recognising it in a list. `null` when none is known. (nullable) |
| `url` | string | The link the clinic should open. Set as long as it can be opened, and `null` when the onboarding is signed, expired or revoked, because there is nothing to open then. Show it to a signed-in user in your own interface; do not forward it by email. (nullable) |
| `expiresAt` | string (date-time) | When the link stops working. After that, `POST /onboarding-links/{id}/refresh` gives a new link with the same id and a new expiry time. (nullable) |
| `status` | string | Where the clinic is in the onboarding. One of `pending` (the link is issued but the clinic has not opened it), `opened` (the clinic has opened the link but not finished signing), `signed` (the agreement is signed with BankID and the merchant exists; a short step while the payment setup is prepared), `in_review` (the payment provider is reviewing, or waiting for something in `requirements`), `active` (the setup is complete; send orders once `chargesEnabled` is true), `expired` (the link expired before the clinic signed; `refresh` gives a new one) or `revoked` (cancelled by Rivr or by you, and final: create a new onboarding instead). |
| `requirements` | string[] | What remains before the clinic can take payments, as short texts in the clinic's language (Swedish or Norwegian) for showing to a person. They are not stable values: do not program against them. Empty when nothing is pending. Meaningful when `status` is `in_review`, and when it is `active` and `chargesEnabled` is false, where it only says that Rivr is reviewing the details. |
| `chargesEnabled` | boolean | The clinic can take payments. This is the signal to start sending orders for `merchantId`, not `status`. Rivr's counterpart to Stripe's `charges_enabled`. False before signing. After signing it follows the same rule that Rivr's payment flows use to let a payment through, so an order created while the flag is true does not bounce because the clinic is not ready. When Rivr cannot decide at the moment, the flag is false, never true on a guess. |
| `payoutsEnabled` | boolean | The payment provider allows payouts to the clinic's bank account: the payout capability is both allowed and verified. Rivr's counterpart to Stripe's `payouts_enabled`. For information only: it does not decide which orders you can send. |
| `merchantId` | string (uuid) | The clinic's merchant id, created when the agreement was signed. Use it as `merchant_id` when you request a merchant token, and as `merchantId` when you create orders for the clinic. `null` until the agreement is signed. (nullable) |
| `createdAt` | string (date-time) | When the onboarding was created. |
| `signedAt` | string (date-time) | When the agreement was signed with BankID and the merchant was created. (nullable) |
| `emailSent` | boolean | True when Rivr emailed the link to the clinic on your behalf (`sendEmail`). False when you got the link to show yourself. |

**Example**

```json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "organisationNumber": "string",
  "companyName": "string",
  "url": "string",
  "expiresAt": "2026-10-18T09:00:00Z",
  "status": "string",
  "requirements": [
    "string"
  ],
  "chargesEnabled": false,
  "payoutsEnabled": false,
  "merchantId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "createdAt": "2026-10-18T09:00:00Z",
  "signedAt": "2026-10-18T09:00:00Z",
  "emailSent": false
}
```

### 401

The token is missing (`token_missing`), not valid (`token_invalid`) or expired (`token_expired`), or it is not a
platform token, for example a merchant token (`platform_token_required`).

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), [platform_token_required](https://developers.rivr.io/errors/platform_token_required.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`). The body also carries `error` and `error_description`, as before.

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

`application/json`

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

### 404

There is no onboarding with the id that belongs to your platform (`onboarding_link_not_found`). An id that is not a
UUID matches no route and gets `route_not_found`.

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

`application/json`

```json
{
  "propertyName": "id",
  "message": "There is no onboarding with this id for your platform.",
  "errorCode": "onboarding_link_not_found",
  "code": "onboarding_link_not_found",
  "type": "https://developers.rivr.io/errors/onboarding_link_not_found"
}
```

### 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/onboarding-links/3fa85f64-5717-4562-b3fc-2c963f66afa6 \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```
