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

# Update Routing Rule

> Change, pause, or re-prioritize an existing redirect or proxy rule

```
PATCH /functions/v1/domains/{domainId}/routing-rules/{ruleId}
```

<Info>
  **Beta.** The routing rules endpoints are new and their response shapes may
  still change.
</Info>

Updates one [routing rule](/dashboard/routing-rules). Send only the fields you want to change; anything you leave out stays as it is. The change takes effect right away.

You need the `owner` or `manager` role on the rule's domain. Viewers get `403 forbidden`.

<Warning>
  Always call this endpoint from a **server-side environment** (backend API, serverless function, build script, etc.). Never include your API key in client-side code — it will be visible to anyone inspecting your frontend.
</Warning>

<Info>
  Programmatic (API key) access requires the **Pro plan and above** — requests
  from Starter accounts return `403 plan_upgrade_required`.
</Info>

## Request

### Headers

| Header          | Required | Description                    |
| --------------- | -------- | ------------------------------ |
| `Authorization` | Yes      | `Bearer hado_sk_your_key_here` |
| `Content-Type`  | Yes      | `application/json`             |

### Path Parameters

| Parameter  | Type   | Required | Description                                                                                          |
| ---------- | ------ | -------- | ---------------------------------------------------------------------------------------------------- |
| `domainId` | string | Yes      | The ID of the domain the rule belongs to, from [List Domains](/api-reference/endpoint/list-domains). |
| `ruleId`   | string | Yes      | The rule to update, from [List Routing Rules](/api-reference/endpoint/list-routing-rules).           |

### Body Parameters

All fields are optional. Send only the ones you want to change.

| Parameter      | Type           | Required | Description                                                           |
| -------------- | -------------- | -------- | --------------------------------------------------------------------- |
| `sourcePath`   | string         | No       | New path pattern. Must start with `/`.                                |
| `targetUrl`    | string         | No       | New destination.                                                      |
| `ruleType`     | string         | No       | `redirect` or `proxy`.                                                |
| `redirectCode` | number         | No       | `301` or `302`. Redirects only.                                       |
| `priority`     | integer        | No       | Higher numbers are checked first.                                     |
| `isActive`     | boolean        | No       | `false` pauses the rule without deleting it; `true` turns it back on. |
| `notes`        | string \| null | No       | New notes. Send `null` or `""` to clear them.                         |

Each field follows the same rules as [Create Routing Rule](/api-reference/endpoint/create-routing-rule#body-parameters), including the [source path patterns](/api-reference/endpoint/create-routing-rule#source-path-patterns) and [target checks](/api-reference/endpoint/create-routing-rule#targets). You can't move a rule to a different domain; create a new rule on the other domain instead. The domain comes from the URL, so leave `domainId` out of the body (sending a different one returns `400`).

### Changing the rule type

When you change `ruleType`, the rule's target is checked again against the new type, and the status code is reset:

| Change           | `targetUrl`                                                                                                                   | `redirectCode`                       |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| redirect → proxy | Must be a full URL that's allowed as a proxy target. Send a new `targetUrl` in the same request if the current one is a path. | Cleared to `null`.                   |
| proxy → redirect | Kept, unless you send a new one.                                                                                              | Set to `301`, unless you send `302`. |

### Example Request

Pause a rule:

```bash theme={null}
curl -X PATCH https://api.hadoseo.com/functions/v1/domains/11111111-1111-1111-1111-111111111111/routing-rules/cccccccc-cccc-cccc-cccc-cccccccccccc \
  -H "Authorization: Bearer hado_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "isActive": false
  }'
```

## Response

### Success (200)

```json theme={null}
{
  "rule": {
    "ruleId": "cccccccc-cccc-cccc-cccc-cccccccccccc",
    "domainId": "11111111-1111-1111-1111-111111111111",
    "sourcePath": "/old-blog/*",
    "targetUrl": "/blog",
    "ruleType": "redirect",
    "redirectCode": 301,
    "priority": 0,
    "isActive": false,
    "notes": "Blog moved in the 2026 redesign",
    "createdAt": "2026-09-25T10:00:00.000Z",
    "updatedAt": "2026-09-25T10:05:00.000Z"
  },
  "cacheInvalidated": true
}
```

| Field              | Type    | Description                                                                                                                                       |
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rule`             | object  | The rule after your changes. See [The rule object](/api-reference/endpoint/list-routing-rules#the-rule-object).                                   |
| `cacheInvalidated` | boolean | `true` when the change is live right away. If `false`, the change is saved but may take a few minutes to start applying. You don't need to retry. |

### Error Responses

| Status | Body                                                                     | Description                                                                                                                                                   |
| ------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `{ "error": "invalid_request", "message": "..." }`                       | The `domainId` or `ruleId` in the path isn't a valid ID, or a field is invalid. The `message` explains which.                                                 |
| 401    | `{ "error": "invalid_api_key" }`                                         | API key is missing, invalid, or revoked.                                                                                                                      |
| 403    | `{ "error": "plan_upgrade_required" }`                                   | Programmatic access requires the Pro plan or above.                                                                                                           |
| 403    | `{ "error": "forbidden" }`                                               | You have `viewer` access to this rule's domain. Changing rules needs `owner` or `manager`.                                                                    |
| 404    | `{ "error": "domain_not_found" }`                                        | The domain in the path doesn't exist or your account can't access it.                                                                                         |
| 404    | `{ "error": "rule_not_found" }`                                          | No rule with this ID on this domain.                                                                                                                          |
| 409    | `{ "error": "duplicate_source_path" }`                                   | Another rule on this domain already uses the new `sourcePath`.                                                                                                |
| 429    | `{ "error": "rate_limit_exceeded_monthly", "usage": 300, "limit": 300 }` | Rate limit exceeded. The code is `rate_limit_exceeded_monthly` or `rate_limit_exceeded_per_minute` — match on the `rate_limit_exceeded` prefix to catch both. |

## Examples

### Switch a temporary redirect to permanent

```bash theme={null}
curl -X PATCH https://api.hadoseo.com/functions/v1/domains/11111111-1111-1111-1111-111111111111/routing-rules/cccccccc-cccc-cccc-cccc-cccccccccccc \
  -H "Authorization: Bearer hado_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "redirectCode": 301
  }'
```

### Turn a redirect into a proxy

```bash theme={null}
curl -X PATCH https://api.hadoseo.com/functions/v1/domains/11111111-1111-1111-1111-111111111111/routing-rules/cccccccc-cccc-cccc-cccc-cccccccccccc \
  -H "Authorization: Bearer hado_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "ruleType": "proxy",
    "targetUrl": "https://cms.example.net/blog"
  }'
```
