# Mask-only usage

Using the Siper /mask endpoint directly. Transform options, batch requests, category filtering, and pattern lists.

You can also use masking without a language model, as a step in your own pipeline. The `/mask` endpoint takes text and returns the masked text together with a detection report that shows what was found in which range.

Diagram: input text goes to the /mask endpoint; the response returns the masked text together with the detection report.

You authorize requests with the virtual key you generate in the panel, sent in the `Authorization: Bearer` header; it is the same key you use for Gateway calls. `/mask` calls are also subject to request limits and the audit trail.

Body errors (missing or malformed requests) and authentication errors are returned in the Gateway’s error format; field validation details may arrive in the masking service’s own format.

## First call

```bash
curl https://gw-tr.gurubase.io/mask \
  -H "Authorization: Bearer $SANAL_ANAHTAR" \
  -H "Content-Type: application/json" \
  -d '{"text": "Ahmet Yılmaz, TCKN 10000000382, İstanbul'\''da yaşıyor."}'
```

```json
{
  "masked_text": "<PERSON_1>, TCKN <TCKN_1>, İstanbul'da yaşıyor.",
  "transform": "placeholder",
  "spans": [
    { "category": "person", "start": 0, "end": 12, "score": 0.85 },
    { "category": "tckn", "start": 19, "end": 30, "score": 1.0 }
  ],
  "timings_ms": { "total": 27.58 }
}
```

`masked_text` is the masked text; direct masking endpoints use raw category names in placeholders ([Concepts](/docs/en/concepts/)). The `spans` list gives, for each detection, the category, the character range in the input text (`start`, `end`), and the confidence score (`score`). `timings_ms.total` is the total processing time.

## Transform options

The `transform` field determines the shape of the masked text; the default is `placeholder`.

| Value | Behavior |
| --- | --- |
| `placeholder` | Replaces the value with a numbered placeholder such as `<PERSON_1>`; you can still see how many values of each category appeared. |
| `mask` | Covers the characters with a fill character; length is preserved. You choose the fill character with `mask_char`, the default is `#`. |

## Batch requests

You send multiple texts to the `/mask/batch` endpoint in a single request; the `results` array is returned in the same order as the input. For text that exceeds the length limit, `/mask` returns 413. On `/mask/batch`, this limit is applied to the combined total text.

```bash
curl https://gw-tr.gurubase.io/mask/batch \
  -H "Authorization: Bearer $SANAL_ANAHTAR" \
  -H "Content-Type: application/json" \
  -d '{
    "texts": [
      "Ahmet Yılmaz aradı.",
      "IBAN: TR12 0001 0000 0000 0000 0000 01"
    ]
  }'
```

## Category filtering

The default behavior is to mask all 26 categories. You narrow the scope with the `categories` field: you pick a `preset`, and if needed the `enable` list adds categories to the set while `disable` removes them. Category keys are the same as the `category` values in the report (such as `person`, `tckn`, `saglik`).

| Preset | Scope |
| --- | --- |
| `ALL` | All categories; same as the default behavior. |
| `KVKK` | Full coverage under KVKK (Turkey’s personal data protection law); the same set as `ALL`. |
| `KVKK_SENSITIVE` | Only the nine special categories under Article 6. |
| `IDENTITY` | Only person and address. |
| `IDENTIFIERS` | Only number- and code-style identifiers (such as TCKN, IBAN, phone). |

```json
{
  "text": "...",
  "categories": { "preset": "KVKK_SENSITIVE" }
}
```

For the full list of categories and the Article 6 distinction, see [Categories](/docs/en/categories/).

## Pattern lists

With two list fields, you add your own rules to the masking decision. Both take a list of regular expressions (Python `re` syntax); an invalid pattern returns 422.

- `allow_patterns`: if the surface text of a detected span matches a pattern, that span is not masked. Useful for fixed values that are not personal data; for example, you do not want your shared support address or your organization’s name to be masked.
- `block_patterns`: every piece of text that matches a pattern is masked, even if the model did not detect it. Use it to lock in organization-specific registry, file, or customer number formats. If you pass a plain string, the category is `custom`; with a `{"pattern": ..., "category": ...}` object you assign a category. A match that overlaps an existing detection is skipped; the detection wins.

```json
{
  "text": "...",
  "allow_patterns": ["destek@kurum\\.example", "\\bDemo Kurum\\b"],
  "block_patterns": [
    "\\bMST-\\d{6}\\b",
    { "pattern": "\\bSICIL-\\d{6}\\b", "category": "custom" }
  ]
}
```

For the placeholder format and the language distinction, see [Concepts](/docs/en/concepts/). To use the same masking inside a chat flow, see [Gateway integration](/docs/en/guides/gateway-integration/).
