# Set a brand's processor connections

> The processor_connections.routing.update operation: PATCH /api/v1/processor_routing/{brandId} in the REST API and the processor_connections_routing_update tool in the MCP server.

Sets which of the legal entity's processor connections a brand's checkouts use (spec §15.4): the `primary`,
and optionally a `secondary` that takes new checkouts while the primary is degraded (marked by an operator, or
automatically after repeated failed requests to the processor). Both must be connections of the entity in the
request's mode that aren't disconnected; several brands may share one. A secondary needs a plan with the
secondary processor feature (`processors.secondary`); `secondary: null` removes it. Sessions that already
started and subscriptions keep the connection they use (saved payment methods belong to their processor).

Pass `expectedVersion` (the brand's `version`) to refuse the change if the brand changed meanwhile.

## At a glance

- **REST:** `PATCH /api/v1/processor_routing/{brandId}`
- **MCP tool:** `processor_connections_routing_update`
- **Operation ID:** `processor_connections.routing.update`
- **Scope:** Legal entity
- **Permission:** `processors:admin`
- **Risk tier:** `write`
- **Dry run:** Supported (send `Ownrecord-Dry-Run: true`)
- **Idempotency:** `Idempotency-Key` optional
- **Modes:** Test and live
- **Authentication:** API key with the `processors:admin` scope
- **Since:** M13

## Request

### Path parameters

| Field     | Type       | Description |
| --------- | ---------- | ----------- |
| `brandId` | `brd_…` ID |             |

### Body

A JSON object (`Content-Type: application/json`):

| Field             | Type                 | Required | Description |
| ----------------- | -------------------- | -------- | ----------- |
| `primary`         | `pcon_…` ID          | Yes      |             |
| `secondary`       | `pcon_…` ID or null  | No       |             |
| `expectedVersion` | integer (at least 1) | No       |             |

## Response

`200 OK` with a JSON object:

| Field           | Type                                                                                               | Description |
| --------------- | -------------------------------------------------------------------------------------------------- | ----------- |
| `object`        | `"processor_routing"`                                                                              |             |
| `brandId`       | `brd_…` ID                                                                                         |             |
| `brandName`     | string                                                                                             |             |
| `livemode`      | boolean                                                                                            |             |
| `primary`       | object or null                                                                                     |             |
| `secondary`     | object or null                                                                                     |             |
| `serving`       | object or null                                                                                     |             |
| `servingReason` | one of `primary`, `secondary`, `degraded_primary`, `degraded_secondary`, `only_connection` or null |             |

## Examples

### Stripe as primary, Mollie as failover

```http
PATCH /api/v1/processor_routing/brd_01m4ttwd3veh9apbewxhfbgr1a
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "primary": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
  "secondary": "pcon_01m4vyt4mxe0s9zzk90373z6p9"
}
```

Response (`200`):

```json
{
  "object": "processor_routing",
  "brandId": "brd_01m4ttwd3veh9apbewxhfbgr1a",
  "brandName": "Acme",
  "livemode": false,
  "primary": {
    "id": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
    "label": "Stripe",
    "processor": "stripe",
    "status": "active",
    "statusReason": null
  },
  "secondary": {
    "id": "pcon_01m4vyt4mxe0s9zzk90373z6p9",
    "label": "Mollie",
    "processor": "mollie",
    "status": "active",
    "statusReason": null
  },
  "serving": {
    "id": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
    "label": "Stripe",
    "processor": "stripe",
    "status": "active",
    "statusReason": null
  },
  "servingReason": "primary"
}
```

## Errors

| Code                                                                                                                   | HTTP status | When                                                                                               | What to do                                                                                                                                         |
| ---------------------------------------------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found)                               | 404         | No such brand of the entity, or no such connection of the entity in this mode.                     | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.                                               |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed)                                 | 400         | The primary and the secondary are the same connection.                                             | Fix the fields listed in `details.issues` and send the request again.                                                                              |
| [`processor_connection_disconnected`](https://ownrecord.io/docs/reference/errors.md#processor_connection_disconnected) | 409         | A connection is disconnected.                                                                      | Connect the processor again, or use another connection of the entity.                                                                              |
| [`entitlement_required`](https://ownrecord.io/docs/reference/errors.md#entitlement_required)                           | 403         | A secondary connection on a plan without the secondary processor feature (`processors.secondary`). | Upgrade the organization's plan, or remove something to get back under the limit.                                                                  |
| [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict)                                   | 409         | The brand changed since `expectedVersion`.                                                         | Fetch the object again and retry the change.                                                                                                       |
| [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required)                                       | 400         | The request names no legal entity.                                                                 | Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (`details.required_scope`). |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied)                                 | 403         | You can't manage processor connections here.                                                       | Ask an organization owner or admin for a role or scope that allows this action.                                                                    |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`invalid_json`](https://ownrecord.io/docs/reference/errors.md#invalid_json), [`unsupported_media_type`](https://ownrecord.io/docs/reference/errors.md#unsupported_media_type), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused), [`idempotency_in_progress`](https://ownrecord.io/docs/reference/errors.md#idempotency_in_progress), [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required), [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected), [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired), [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval), [`approval_policy_denied`](https://ownrecord.io/docs/reference/errors.md#approval_policy_denied), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
