---
title: "Test mode and Live mode"
description: "Keep development data separate from approved production operations."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs-staging.affinityrx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Test mode and Live mode

Test mode and Live mode keep patient records, orders, webhook endpoints, and signing secrets separate. API keys select one mode.

Team membership, prescriber credentials, and practice locations are shared between modes for the same practice.
Changes to these shared records apply in both modes.

## Test mode

Use Test mode while you build and verify the integration.
Platforms can sign up and begin Test integration immediately, without an invitation.

- Use only synthetic patients, providers, prescriptions, addresses, and contact data.
- Route orders only to the Affinity simulator.
- Verify retries, failures, and webhook replay before you request Live access.
- Confirm that mode-scoped resources report `livemode: false`.

Test mode must not contact a real pharmacy or create a real payment.

## Live mode

Use Live mode only after Affinity approves the required organization access.

- Store the Live API key separately from the Test API key.
- Use current patient and provider authorization.
- Read the current catalog before you create an order.
- Treat catalog availability as time-sensitive.
- Keep controlled substances disabled.

Platform Live access requires explicit Affinity approval. An approved platform can manage Live access for practices it owns.
An Affinity-issued practice invitation can also grant Live access through onboarding.
Keys with `orders:sign` can sign and submit for an authorized clinician without an Affinity login.
The integration collects signing intent. Affinity checks authority and records the exact versions.

## Manage practice Live access

Your platform must have current Live approval. Use its Live API key with `practices:write`.
Affinity checks the practice ownership link for every update. Knowing a practice ID does not grant access.
Your platform cannot change another platform's practice or an unowned practice.

### Enable access during creation

For `POST /v1/practices`, add `liveEnabled: true` to the practice creation body.
Include the required name, address, and practice attestations described in the [API reference](/api/).

| Create field                    | Result                                               |
| ------------------------------- | ---------------------------------------------------- |
| `liveEnabled: true`             | Creates an active practice with Live access enabled. |
| `liveEnabled: false` or omitted | Creates the practice without Live access.            |

Creation records your platform as the practice owner. Platform approval alone does not automatically enable every new practice.
If `externalId` already identifies a practice, creation returns that practice without changing its Live access.
Use Update practice to change existing access.

### Enable or disable existing access

Send `PATCH /v1/practices/{practiceId}` with `liveEnabled: true` to enable access or `false` to disable it.
For example, disable access from your backend:

```bash
curl --request PATCH \
  --url "https://api.affinityrx.com/v1/practices/$AFFINITY_PRACTICE_ID" \
  --header "Authorization: Bearer $AFFINITY_LIVE_API_KEY" \
  --header "Affinity-Version: 2026-09-28" \
  --header "Content-Type: application/json" \
  --data '{"liveEnabled":false}'
```

Set `AFFINITY_PRACTICE_ID` to the public practice ID returned by the API.
Omitting `liveEnabled` from an update preserves the current access setting.

Idempotency keys are optional for practice creation and updates. Supply one when you need safe retries of the same request.

Read `liveEnabled` in the response to confirm whether Live access is enabled.
It is `false` after disablement and for Test practices.
`livemode` identifies the resource's mode; a Live practice can have `liveEnabled: false`.

### Access restrictions

- Test requests cannot set `liveEnabled`, including `false`. Omit this field when creating or updating Test practices.
- A platform without current Live approval cannot enable or disable practice Live access.
- An explicit Affinity Admin Live decision takes precedence, including an approval or disablement.
- Platforms cannot change Live access for suspended or archived practices.

Denied requests return `403`. An Admin-controlled practice returns `practice_live_access_admin_controlled`.
Contact Affinity to change an Admin decision. Repeating practice creation does not override it.

Live access does not replace clinician authority checks, prescription validation, pharmacy eligibility, or billing requirements.
Enabling Live access does not convert Test data into Live data.

## Billing in each mode

Test mode simulates payment profiles and invoice settlement without charging a real payment method.
Live orders require the payer's billing account to meet its payment terms.
For platform-managed orders, the platform is the payer, including when a provider signs in Clinic.

Configure Live billing separately. See [Billing and payments](/guides/billing/) for setup and blocked-order recovery.

## Change modes

Change the API key and the mode configuration together. Restart the process after the change.

Run a read-only account request first. Confirm the returned mode before you permit a mutation.

## Simulate pharmacy responses

Open a Test order in Clinic or Platform to use **Test controls**.
You need permission to manage orders.

Choose a scenario before you submit the order or before pharmacy processing starts.

| Scenario               | Result                                                                          |
| ---------------------- | ------------------------------------------------------------------------------- |
| Successful fulfillment | The pharmacy accepts, processes, ships, and delivers the order.                 |
| Pharmacy rejection     | The pharmacy rejects the submitted order because the medication is unavailable. |
| Cancellation declined  | Fulfillment progresses normally. The pharmacy declines a cancellation request.  |

Automatic progression runs in background workers. Initial pharmacy acceptance can take several
minutes after submission while the order is queued and simulation is initialized. Each subsequent
step becomes eligible after one minute and runs when a worker next processes it; this is not a
one-minute completion guarantee. Use Manual mode to request a specific response without waiting
for automatic progression.
Tracking numbers start with `TEST-` and do not identify real shipments.

Select **Manual** to pause progression. Use the available actions to trigger pharmacy responses.
Manual actions apply to every fulfillment in the order. Each fulfillment must permit the selected action.

To test cancellation, use the normal order cancellation action first.
The request remains pending until the simulator approves or declines it.
In Manual mode, choose **Approve cancellation** or **Decline cancellation** in Test controls.
A shipped or delivered fulfillment cannot be canceled.
The simulated cutoff does not describe any real pharmacy's cancellation policy.

### API controls

Use a Test API key with `orders:write`.
Read the controls with `GET /v1/orders/{orderId}/test-simulation`.
Configure them with `PUT /v1/orders/{orderId}/test-simulation` and an `Idempotency-Key` header.

To hold an order before submission, send:

```json
{
  "mode": "manual",
  "scenario": "successful"
}
```

After submission completes, read `availableActions` to find valid pharmacy responses.
For example, queue acceptance with:

```json
{
  "mode": "manual",
  "scenario": "successful",
  "action": "accept"
}
```

The response reports `pendingAction` until the worker processes the event.
If the order changes before processing, `lastError` explains why the event could not run.
Refresh the controls before you retry.

Supported actions are `accept`, `process`, `ship`, `deliver`, `reject`, `confirm_cancellation`, and `decline_cancellation`.
Scenario values are `successful`, `pharmacy_rejection`, and `cancellation_declined`.

Simulation uses the normal order history and Test webhook delivery path.
A pharmacy rejection produces `order.blocked`. Cancellation decisions produce `cancellation.confirmed` or `cancellation.rejected`.
Live credentials cannot read or change Test controls.

Source: https://docs-staging.affinityrx.com/guides/test-and-live-mode/index.mdx
