# Natural Language Search

Ask for compromised credentials in plain English. `GET /breaches/ask` interprets your question - the domain, sources, time window, and order - and runs the standard Data Breaches search, returning the same structured records as `/breaches`.

Use it for investigations, analyst tooling, and chat assistants, or to find the right `/breaches` filters quickly. For automated pipelines that need fixed, repeatable parameters, call [`/breaches`](data-breach-endpoints) directly.

## Request

`GET`

```bash
https://api.webz.io/breaches/ask?q=YOUR_QUESTION
```

| Parameter | Required | Description |
| --- | --- | --- |
| `q` | Yes | Your question, up to 500 characters. Name one domain or one full email address. |
| `dry_run` | No | `true` returns the interpreted search without running it. Default `false`. |

### Authentication

Send your Webz.io API token as a Bearer header:

```http
Authorization: Bearer YOUR_TOKEN
```

The `token` query parameter also works, as on every other Data Breaches endpoint. The header is recommended: URLs are often recorded in proxy logs and command history. Your account needs the Data Breaches permission and authorization for the domain you ask about - see [Errors, Rate Limits & Credits](data-breach-errors-limits).

## Preview with `dry_run`

Check how a question is understood before running it:

```bash
curl --get 'https://api.webz.io/breaches/ask' \
  --header "Authorization: Bearer YOUR_TOKEN" \
  --data-urlencode 'q=Which example.com employees had credentials exposed in the last 30 days, newest first?' \
  --data-urlencode 'dry_run=true'
```

```json
{
  "interpretedQuery": "/breaches?email_domain=example.com&order_by=desc&sort_by=crawled&crawled_from=1790294400000",
  "params": {
    "email_domain": "example.com",
    "order_by": "desc",
    "sort_by": "crawled",
    "crawled_from": 1790294400000
  }
}
```

`interpretedQuery` is the equivalent `/breaches` call, without your token. If it is not what you meant, rephrase and preview again. A preview never runs the search and costs no credit.

> [!TIP]
> Use the preview as a query builder: `interpretedQuery` plus your token is a repeatable `/breaches` request for your automation.

## Run a search

Omit `dry_run` to run the interpreted search:

```bash
curl --get --include 'https://api.webz.io/breaches/ask' \
  --header "Authorization: Bearer YOUR_TOKEN" \
  --data-urlencode 'q=Show the latest leaked logins to example.com from infostealers in the last 60 days'
```

The `X-Interpreted-Query` header shows the `/breaches` query that produced the results, token excluded:

```http
HTTP/1.1 200 OK
X-Interpreted-Query: /breaches?login_domain=example.com&data_type=infostealer&order_by=desc&sort_by=crawled&crawled_from=1787702400000
```

The body is the standard [Response Format](data-breach-response-format), up to 100 records per page:

```json
{
  "records": [ ... ],
  "totalResults": 412,
  "moreResultsAvailable": 312,
  "next": "/breaches?login_domain=example.com&data_type=infostealer&order_by=desc&sort_by=crawled&crawled_from=1787702400000&token=YOUR_TOKEN&next=CURSOR",
  "requestsLeft": 988,
  "totalResultsVerified": true
}
```

## What you can specify

Every question names one domain or one email address. Beyond that, include any of the following:

- **Who** - employee accounts (email addresses at the domain) or customer accounts (credentials used to sign in to the domain, subdomains included).
- **Sources** - data breaches, infostealer logs, or both. Both are searched unless the question restricts them.
- **Credential details** - records that contain a password, or a specific password type.
- **Service** - a service category or application, such as VPN access.
- **Time window** - by collection date or by breach/infection date, within the last 365 days. Without a period, the search covers the last 365 days.
- **Order** - newest or oldest first (oldest first by default).
- **A specific breach** - by name, matched against the [Breach Catalog](data-breach-catalog).

Example questions:

- Which example.com employees had credentials exposed in the last 30 days, newest first?
- Show the latest infostealer records with logins to example.com from the last 60 days.
- Show example.com accounts with plaintext passwords from data breaches collected this year.
- Show VPN logins to example.com from devices infected in the last six months, by infection date.

## Pagination

`next` in the response is a ready-made `/breaches` URL. Append it to `https://api.webz.io` and call it as-is, exactly as in [Pagination](data-breach-pagination) for a direct search. Do not send `next` back through `/breaches/ask`: the question is interpreted once, and paging continues through `/breaches`.

> [!WARNING]
> `next` carries your API token, even when you authenticated with the Bearer header. Treat it as a credential - keep it out of logs, tickets, and screenshots.

## Credits and rate limits

| Call | Credits |
| --- | --- |
| Preview (`dry_run=true`) | 0 |
| Question that needs clarification (`400`) | 0 |
| Search that runs, including one with 0 results | 1 |
| Each `next` page | 1 |

`requestsLeft` in every search response shows your balance. The per-token rate limit of about 1 request per second applies to the search, as on `/breaches`.

Interpreting a question takes longer than a direct `/breaches` call. For high-volume or latency-sensitive workloads, resolve the question once with `dry_run` and reuse the resulting `/breaches` query.

## When the question cannot be run

If the question is missing something, or asks for what the API cannot do, the endpoint returns `400` with a plain-language explanation instead of guessing. The wording varies; for example:

```json
{
  "errorCode": 400,
  "errors": ["Which domain or email address should be searched?"]
}
```

Common reasons:

- No domain or email address in the question, or more than one domain - search one at a time.
- A time range older than 365 days - natural language search covers the last year only. For older data, use `/breaches` with `raw=true`; see [Time Range](data-breach-time-range).
- A named breach that is unknown or matches several catalog entries - the message lists the candidates. Specify one and retry.

Rephrase and retry; a clarification costs no credit. Other errors follow the Data Breaches conventions - `400` for a blank `q` or one over 500 characters, `401` for a missing token or no Data Breaches permission, `403` for an unauthorized domain, `404` for an unknown token, `429` for the rate limit or no credits. See [Errors, Rate Limits & Credits](data-breach-errors-limits).

## Limits

- One domain or one full email address per question.
- `q` is at most 500 characters.
- Searches cover the last 365 days. Raw mode is not available here.
- `q` is the whole search: other `/breaches` parameters on the request are ignored.
- No `next` or page-size parameter - page through `/breaches`.
- Up to 100 records per page.

## Privacy

- Your question is sent to an external language-model service to be interpreted. Your API token and the returned records are not - the service only sees the text of `q`.
- `q` travels in the URL and may appear in access logs. Keep passwords, tokens, and personal data out of it unless they are what you are searching for, such as an email address.
- Results come straight from the Data Breaches index. Nothing in a record is generated or altered by AI.

## Related documentation

- [Quickstart](data-breach-quickstart)
- [Search Scope](data-breach-scope)
- [Filters](data-breach-filters)
- [Response Format](data-breach-response-format)
- [Pagination](data-breach-pagination)
- [Errors, Rate Limits & Credits](data-breach-errors-limits)

