> This page is for Gateway.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.merge.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.merge.dev/_mcp/server.

# Update Classifier

PATCH https://api-gateway.merge.dev/v1/classifiers/{classifier_id}
Content-Type: application/json

Update the fields you send. Sending `examples` replaces them and rebuilds the
classifier in the background (`status` `building`); policies keep using the
previous build until the new one is ready.

Reference: https://docs.merge.dev/merge-gateway/management-api/routing-policies/update-routing-classifier

## Authentication

- `Authorization` header (bearer token, required) — A management key (`mgmt_...`), sent as `Authorization: Bearer <key>`. Reading /v1/routing-policies also accepts the organization's gateway API keys; writing there needs a management key.

## Request

### Path parameters

- `classifier_id` (string, required) — The classifier's `id`.

### Body (application/json)

This endpoint expects a ClassifierV1Update.

- `description` (string, optional, nullable) — What the classifier is for. Send "" to clear it. Omit, or send null, to keep the current value.
- `examples` (list of ClassifierExampleV1, optional, nullable) — Labeled prompts: what your requests look like and how complex each one is, from 0 (simple) to 1 (complex). Scores further from 0.5 count more. The classifier is ready once at least 3 are below 0.5 and 3 are at or above it. Omit, or send null, to keep the current value.
- `name` (string, optional, nullable) — Unique within the organization. Omit, or send null, to keep the current value.

## Response

### 200

The updated classifier

- `build_error` (string, required, nullable) — Why the last build failed, when `status` is `failed`.
- `created_at` (datetime, required)
- `description` (string, required, nullable) — What the classifier is for.
- `examples` (list of ClassifierExampleV1, required) — Labeled prompts: what your requests look like and how complex each one is, from 0 (simple) to 1 (complex). Scores further from 0.5 count more. The classifier is ready once at least 3 are below 0.5 and 3 are at or above it.
- `has_readout` (boolean, required) — Whether routers that score with the difficulty readout use it too. Classifiers saved before readouts get one when their examples are next updated.
- `id` (string, required) — Send as a routing policy's `complexity_classifier_id` to use it.
- `is_ready` (boolean, required) — Whether it has a build that scores requests (also true while a rebuild runs). A policy using a classifier that isn't ready scores with the built-in scorer.
- `name` (string, required) — Unique within the organization.
- `quality_report` (ClassifierQualityV1, required, nullable) — null until the classifier is ready.
- `status` (enum, required) — `building` while the classifier builds in the background after a save (a few seconds to a minute), then `ready`, or `not_enough_examples` when either side of 0.5 has fewer than 3 examples, or `failed`. While a rebuild runs, policies keep using the previous build.
  - Allowed values: `building`, `ready`, `not_enough_examples`, `failed`
- `updated_at` (datetime, required)

## Errors

### 401 Unauthorized Error

The key is missing or invalid.

- `detail` (ErrorResponseDetail, required) — A message, or an object with a `code` to branch on and a `message`.

### 403 Forbidden Error

The key lacks the scope this route needs, or the change is not allowed.

- `detail` (ErrorResponseDetail, required) — A message, or an object with a `code` to branch on and a `message`.

### 404 Not Found Error

The resource does not exist in the key's organization.

- `detail` (ErrorResponseDetail, required) — A message, or an object with a `code` to branch on and a `message`.

### 409 Conflict Error

The request conflicts with the current state.

- `detail` (ErrorResponseDetail, required) — A message, or an object with a `code` to branch on and a `message`.

### 422 Unprocessable Entity Error

Validation Error

- `detail` (list of ValidationError, optional)

## Types

### ClassifierExampleV1

A labeled prompt.

- `complexity` (double, required) — How complex it is: 0 is simple, 1 is complex.
- `prompt` (string, required) — A prompt like the ones you send.

### ClassifierQualityV1

How well the classifier separates its own examples, measured when it was built. Each example is scored by the classifier rebuilt without it, so accuracy reflects prompts it hasn't seen. The built-in scorer's results on the same examples are the baseline.

- `accuracy` (double, required) — Share of examples scored on the right side of 0.5, from 0 to 1.
- `auc` (double, required, nullable) — Chance a complex example outscores a simple one, from 0 to 1.
- `examples` (integer, required) — Examples measured.
- `flagged_examples` (list of FlaggedExampleV1, required) — Up to 10 examples scored on the wrong side of their label: mislabeled, or unlike the rest of their side.
- `generic_accuracy` (double, required, nullable) — `accuracy` of the built-in scorer on the same examples.
- `generic_auc` (double, required, nullable) — `auc` of the built-in scorer on the same examples.
- `one_sided_terms` (OneSidedTermsV1, required) — Terms only one side uses.
- `warnings` (list of string, required) — What to change, if anything.

### ErrorResponseDetail

A message, or an object with a `code` to branch on and a `message`.

- string
- ErrorDetail: ErrorDetail

### ValidationError

- `loc` (list of ValidationErrorLocItems, required)
- `msg` (string, required)
- `type` (string, required)
- `ctx` (ValidationErrorCtx, optional)
- `input` (any, optional)

### FlaggedExampleV1

- `complexity` (double, required) — The example's label.
- `index` (integer, required) — The example's position in `examples`, from 0.
- `prompt` (string, required) — The example's prompt, cut to 200 characters.
- `score` (double, required) — Its score from the classifier rebuilt without it.

### OneSidedTermsV1

- `complex` (list of string, required) — Terms only complex examples use. A simple request that mentions one may be scored complex; add simple examples that use them.
- `simple` (list of string, required) — Terms only simple examples use. A complex request that mentions one may be scored simple; add complex examples that use them.

### ErrorDetail

A structured error. Some carry extra fields, like `count`.

- `code` (string, required) — A stable code to branch on, like `payment_method_required`.
- `message` (string, required) — A human-readable explanation.

### ValidationErrorLocItems

- string
- integer

### ValidationErrorCtx

## Examples

**Request**

```json
{
  "description": "Finance team, including FP&A."
}
```

**Response**

```json
{
  "build_error": null,
  "created_at": "2026-06-02T17:04:00Z",
  "description": "What counts as complex for the finance team.",
  "examples": [
    {
      "complexity": 0.05,
      "prompt": "What was our ARR at the end of Q3?"
    },
    {
      "complexity": 0.1,
      "prompt": "Who owns the intercompany elimination entries this quarter?"
    },
    {
      "complexity": 0.05,
      "prompt": "Send me the link to the FY26 opex budget."
    },
    {
      "complexity": 0.95,
      "prompt": "Reconcile Q3 deferred revenue against the billing schedules and explain every variance over $5k."
    },
    {
      "complexity": 0.9,
      "prompt": "Build the ARR bridge from Q2 to Q3 and tie it back to the GAAP revenue waterfall."
    },
    {
      "complexity": 0.95,
      "prompt": "Walk through the ASC 606 treatment of a 3-year ramp deal with a free first quarter."
    }
  ],
  "has_readout": true,
  "id": "5d7f9b1c-3e5a-4c7e-9a1b-6c8e0a2c4e69",
  "is_ready": true,
  "name": "Finance requests",
  "quality_report": {
    "accuracy": 1,
    "auc": 1,
    "examples": 6,
    "flagged_examples": [],
    "generic_accuracy": 0.83,
    "generic_auc": 0.89,
    "one_sided_terms": {
      "complex": [
        "revenue"
      ],
      "simple": []
    },
    "warnings": [
      "Add more examples: 10 or more on each side give steadier scores"
    ]
  },
  "status": "ready",
  "updated_at": "2026-09-14T09:30:00Z"
}
```

**SDK Code**

```python
import requests

url = "https://api-gateway.merge.dev/v1/classifiers/classifier_id"

payload = { "description": "Finance team, including FP&A." }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.patch(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api-gateway.merge.dev/v1/classifiers/classifier_id';
const options = {
  method: 'PATCH',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"description":"Finance team, including FP&A."}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api-gateway.merge.dev/v1/classifiers/classifier_id"

	payload := strings.NewReader("{\n  \"description\": \"Finance team, including FP&A.\"\n}")

	req, _ := http.NewRequest("PATCH", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api-gateway.merge.dev/v1/classifiers/classifier_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"description\": \"Finance team, including FP&A.\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://api-gateway.merge.dev/v1/classifiers/classifier_id")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"description\": \"Finance team, including FP&A.\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://api-gateway.merge.dev/v1/classifiers/classifier_id', [
  'body' => '{
  "description": "Finance team, including FP&A."
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api-gateway.merge.dev/v1/classifiers/classifier_id");
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"description\": \"Finance team, including FP&A.\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["description": "Finance team, including FP&A."] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api-gateway.merge.dev/v1/classifiers/classifier_id")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```