> 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.

# Data loss prevention

> Gateway scans prompts against built-in and custom DLP rules before sending them to the vendor, then notifies, redacts, or blocks. Rules are managed in the dashboard.

Data loss prevention (DLP) scans each prompt against your enabled rules before it reaches the vendor, then records, redacts, or blocks matches, to keep PII and secrets out of vendor traffic or meet a customer DPA. DLP doesn't scan responses; for leaked credentials in responses, use the [prompt injection output check](/merge-gateway/security/prompt-injection-protection).

## Turn on rules

Manage rules under **Security → DLP** in the [dashboard](https://gateway.merge.dev/security/rules) or with [`/v1/dlp-rules`](/merge-gateway/management-api/security-rules/list-dlp-rules). Every rule, built-in included, starts disabled. Changing rules needs Manage organization settings, and every change is recorded in the [audit trail](/merge-gateway/security/audit-trail). Built-in rules can be toggled and given a different action, but not edited or deleted.

| Category | Entity              | Default action |
| -------- | ------------------- | -------------- |
| Global   | `CREDIT_CARD`       | Redact         |
| Global   | `CRYPTO`            | Redact         |
| Global   | `DATE_TIME`         | Notify         |
| Global   | `EMAIL_ADDRESS`     | Redact         |
| Global   | `IBAN_CODE`         | Redact         |
| Global   | `IP_ADDRESS`        | Notify         |
| Global   | `LOCATION`          | Notify         |
| Global   | `PERSON`            | Notify         |
| Global   | `PHONE_NUMBER`      | Redact         |
| Global   | `URL`               | Notify         |
| USA      | `US_BANK_NUMBER`    | Redact         |
| USA      | `US_DRIVER_LICENSE` | Redact         |
| USA      | `US_ITIN`           | Redact         |
| USA      | `US_PASSPORT`       | Redact         |
| USA      | `US_SSN`            | Redact         |

## Custom rules

Custom rules match data such as internal IDs, codenames, or your own key formats. Each needs a unique name and at least one matcher, and starts enabled.

| Field    | Limit                                                          |
| -------- | -------------------------------------------------------------- |
| Name     | 80 characters, unique in the organization                      |
| Pattern  | A Python regex of up to 500 characters, validated on save      |
| Keywords | Up to 50 case-insensitive strings of up to 100 characters each |

## Actions

| Action     | Effect                                                                              |
| ---------- | ----------------------------------------------------------------------------------- |
| **Notify** | Records the match and sends the prompt unchanged                                    |
| **Redact** | Replaces each match with a placeholder such as `<US_SSN>` before the prompt is sent |
| **Block**  | Rejects the request with HTTP 422                                                   |

```json
{
  "error": {
    "type": "invalid_request_error",
    "message": "Request blocked by DLP policy.",
    "code": "blocked_by_dlp_policy"
  }
}
```

On a streaming request, the 422 body has `type: "blocked_by_dlp_policy"`, so match on `code`. If scanning is unavailable or takes over 250 ms, the request proceeds unscanned with `status: "error"`.

## See results on a response

Set `include_guardrails_metadata: true` in the body, or the `include-guardrails-metadata: true` header, to get `guardrails.dlp` on the response, including a blocked 422. It reports entity types and counts, never matched values.

```json
"guardrails": {
  "dlp": {
    "status": "redacted",
    "action": "redact",
    "finding_count": 2,
    "entity_counts": { "EMAIL_ADDRESS": 1, "US_SSN": 1 },
    "action_counts": { "REDACT": 2 },
    "rule_ids": ["6f1c2a8e-4b7d-4e0a-9c3f-2d8b1a7e5f60"]
  }
}
```

`status` is one of `clean`, `flagged`, `redacted`, `blocked`, `skipped` (with a `skipped_reason` such as `no_enabled_rules`), or `error`. `action` is `none`, `notify`, `redact`, or `block`.

## Test rules

**Security → DLP tester** runs up to 50,000 characters against your enabled rules and lists each hit's entity, action, matched text, and offsets. It uses regex approximations, so it never reports `PERSON`, `LOCATION`, `US_PASSPORT`, `US_DRIVER_LICENSE`, or `US_ITIN`, which live traffic does detect. Confirm those with a real request and guardrails metadata.

## Alerts

Every match appears under **Security → Alerts** with the entity, action, model, and customer ID when present, alongside prompt injection detections.

## Override per project or customer

[Projects](/merge-gateway/automation/projects-api/guardrails) and [customers](/merge-gateway/embedded-routing-stack/guardrails) can override the action per entity type; for a project, use [`PUT /v1/projects/{id}/dlp-settings`](/merge-gateway/management-api/security-rules/update-project-dlp-settings).

## Next steps

#### [Prompt injection protection](/merge-gateway/security/prompt-injection-protection)

Block injection attempts before they reach the model

#### [Per-customer restrictions](/merge-gateway/security/per-customer-restrictions)

Block or pin models and providers for specific customers

#### [Zero data retention](/merge-gateway/security/zero-data-retention)

Route only to vendors with zero data retention agreements