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

# Match & Map

> Match extracted values against a list of known values, and optionally replace them.

The **Match & Map** formatter compares an extracted value against a list of values you provide, and replaces it with the value you have mapped it to. Use it to normalize messy values — supplier names, product codes, departments — or to restrict a field to a known set of values.

It is useful in two ways:

* **Match and map** — the document says `coca cola`, your system needs `The Coca-Cola Company`.
* **Match only** — you only want to accept values that exist in your list, and leave them as they are.

Both are configured with the same mapping, described below.

## Mapping format

A mapping is a **JSON array** of objects. Each object has a `from` and an optional `to`:

```json theme={null}
[
  { "from": "coca cola", "to": "The Coca-Cola Company" },
  { "from": "Coca-Cola Co", "to": "The Coca-Cola Company" },
  { "from": "pepsico inc", "to": "PepsiCo, Inc." }
]
```

* **`from`** is the value to look for in the document. Rows without a `from` are ignored.
* **`to`** is the value the field is set to when the row matches. It is optional — leave it out and the field keeps the `from` value, which is how you build a match-only list:

```json theme={null}
[
  { "from": "Invoice" },
  { "from": "Credit note" },
  { "from": "Receipt" }
]
```

Several rows may point at the same `to`, as in the first example — that is how you fold many spellings into one canonical value. You can also mix mapped and unmapped rows in the same list.

## Providing the mapping

<Tabs>
  <Tab title="Table">
    Edit the **From** and **To** columns directly in the formatter. This is the simplest option when the list is short and changes rarely.
  </Tab>

  <Tab title="CSV">
    Use **Import from CSV** and pick which column is `from` and which is `to`. The file is read once at import and turned into a mapping — later changes to the CSV file have no effect.
  </Tab>

  <Tab title="URL">
    Use **Connect with URL** to fetch the mapping from your own endpoint every time a document is processed. See [Connecting a URL](#connecting-a-url).
  </Tab>
</Tabs>

## Connecting a URL

When you connect a URL, Cradl AI calls your endpoint each time a document is processed and uses the response as the mapping. This keeps the list in sync with your own system — a supplier register or product catalogue — without re-importing anything.

In **Connect with URL** you set the endpoint and choose `GET` or `POST`. While a URL is connected the mapping table is read-only, since the endpoint is the source of truth.

### Expected response

Your endpoint must answer with a success status and a JSON body that is **the mapping array itself** — the same format as above, with nothing wrapped around it.

```http theme={null}
HTTP/1.1 200 OK
Content-Type: application/json

[
  { "from": "coca cola", "to": "The Coca-Cola Company" },
  { "from": "Coca-Cola Co", "to": "The Coca-Cola Company" },
  { "from": "pepsico inc", "to": "PepsiCo, Inc." }
]
```

<Warning>
  A wrapped response does **not** work. The body must be the array, not an object containing it:

  ```json theme={null}
  { "data": [{ "from": "coca cola", "to": "The Coca-Cola Company" }] }
  ```

  Neither does an object keyed by value:

  ```json theme={null}
  { "coca cola": "The Coca-Cola Company" }
  ```
</Warning>

You can check your endpoint with:

```bash theme={null}
curl -s <YOUR-MAPPING-URL> | head -c 200
```

The output should start with `[` and the first object should have a `from` key.

<Note>
  The endpoint is called on every document, so it needs to be publicly reachable and reasonably fast. The dialog takes a URL and an HTTP method only, so the endpoint cannot require custom authentication headers. If the endpoint returns an error status, or something that is not a mapping array, the field is left empty and the formatter reports an error — which sends the document to human review rather than silently writing a wrong value.
</Note>

## Fuzzy matching

By default a value must match a `from` exactly. Turn on **fuzzy matching** to also accept small differences, measured as [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) — the number of single-character edits needed to turn one string into the other.

* **Threshold** — how many edits are allowed. `0` means exact match. Enabling fuzzy matching in the app starts at `1`, and you can raise it.
* **Ignore case and locale** — when on, differences in capitalization and accents cost nothing: `Coca Cola` and `COCA COLA` are both distance `0` from `coca cola`, and `Nestlé` is distance `0` from `nestle`.

With a threshold of `1` and case differences ignored, a `from` of `foo` matches `foo`, `Foo`, `fo` and `foo6`, but not `foobar`.

<Tip>
  Raise the threshold carefully. A high threshold on short values makes unrelated entries match — with a threshold of `3`, `cat` matches almost any three-letter word.
</Tip>

## What the formatter does

The formatter reads the extracted value, or the raw value if the field has not been formatted yet, and then:

| Situation | Field value | Result |
| - | - | - |
| The extracted value is empty | Empty | No message |
| The mapping is empty or could not be loaded | Empty | Error: `Mapping is empty` |
| No row is within the threshold | Empty | Error: `No mapping match found` |
| Exactly one row matches | The row's `to`, or its `from` if `to` is not set | No message |
| Several rows match | The closest row's value. On a tie, the row listed first wins | Warning listing how many rows matched |

An error leaves the field empty and prevents the document from being automated, so it goes to human review. A warning does not block automation — it just records that the match was ambiguous, which usually means the mapping has near-duplicate `from` values worth cleaning up.
