# Referentie van de wachtwoord-API · password.es

> Alle parameters van POST /v1/generate, elk veld van het antwoord, de foutcodes en de limieten van api.password.es. Met een curl-voorbeeld dat werkt.

password.es · Original: https://password.es/nl/api/docs/

---

# Referentie van de wachtwoord-API

De referentie van `api.password.es`: elke parameter, elk veld van het antwoord, elke foutcode en de limieten. De voorbeelden plak je zo in een terminal.

Als je wilt weten wat dit is, voor wie en wanneer je het beter *niet* gebruikt, begin dan bij [de API-pagina](https://password.es/nl/api/).

## De endpoints

Alles hangt onder `https://api.password.es`. Twee antwoorden en één nog niet — en die ene zegt het zelf in zijn antwoord.

- POST/v1/generate Genereert een of meer wachtwoorden en geeft hun analyse terug.
- GET/openapi.json De beschrijving van de API, in OpenAPI 3.1.
- POST/mcp MCP-server voor assistenten. Eén tool: `generate_password`.
- POST/v1/check 501 Bestaat nog niet. De fout vertelt wat er ontbreekt en waar je intussen terechtkunt.

## Een wachtwoord maken

De body is optioneel: zonder body krijg je 16 tekens met alle vier de soorten aan. Met body, wat je vraagt.

Het verzoek

```
curl -X POST https://api.password.es/v1/generate \
  -H 'content-type: application/json' \
  -d '{"length":20,"exclude_ambiguous":true}'
```

Het antwoord

```
{
  "passwords": [
    "P#f.aK+w4pcsx]}Gx;*>"
  ],
  "analysis": {
    "length": 20,
    "pool": 83,
    "bits": 127.50078862693852,
    "log10_guesses": 38.08053185185735,
    "crack_time_log10_seconds": 26.08053185185735,
    "crack_time": {
      "value": "3.8 × 10¹⁸",
      "unit": "years"
    },
    "level": 4,
    "level_scale": "time",
    "ceiling": false
  },
  "notice": "Generated on someone else's machine, which is a security antipattern even though we store nothing. For a password you will actually use, the generator at https://password.es/en/ runs entirely in your browser and sends nothing.",
  "_meta": {
    "plan": "anonymous",
    "lang": {
      "messages": "en",
      "links": "en"
    },
    "limits": {
      "burst": {
        "limit": 60,
        "window_seconds": 60
      }
    },
    "quota": {
      "limit": null,
      "remaining": null,
      "reset": "2026-09-01T00:00:00.000Z"
    },
    "docs": "https://password.es/api/"
  }
}
```

## De parameters

Allemaal optioneel. De tabel staat in het Engels en is in alle achttien talen identiek, met opzet: wie een API inbouwt typt de veldnamen precies zoals ze geschreven staan, en achttien vertalingen van `exclude_ambiguous` zouden schuld zijn, geen bereik.

- Field
- Type
- Default
- Notes
- length
- integer 4–64
- 16
- How many characters. The same range as the generator on this site.
- count
- integer 1–20
- 1
- How many passwords to return. `passwords` is always an array, including with `count` 1.
- lower
- boolean
- true
- Include a–z (26 characters).
- upper
- boolean
- true
- Include A–Z (26 characters).
- digits
- boolean
- true
- Include 0–9 (10 characters).
- symbols
- boolean
- true
- Include `~!@#$%^&*()_+-=[]{};:,./<>?` — the same 27 as the slider on the home page, no more.
- exclude_ambiguous
- boolean
- false
- Drops `0 O 1 I l | o`. Six of them in practice, not seven: `|` is not in the symbol set to begin with. That is why `pool` reads 83 above instead of 89.
- no_repeats
- boolean
- false
- Avoids adjacent repeated characters. Not an absolute guarantee: it retries ten times, exactly as the web generator does. At length 64 that lets a repeat through about 0.1% of the time.
- lang
- string
- `en`
- Which language to answer in. One of the site's eighteen. Also accepted as `?lang=` in the URL, which wins over this field; without either, `Accept-Language` is read. An unknown value is not an error — it falls back to English. See the section below: messages exist in English and Spanish, links in all eighteen.

## Wat elk getal betekent

Hetzelfde idee: de referentie in het Engels, de uitleg ernaast. Geen van deze getallen is nieuw — ze komen allemaal uit dezelfde motor die de meter op de startpagina tekent.

- Field
- Notes
- passwords
- An array of strings, always — including with `count` 1.
- analysis.length
- How many characters came back.
- analysis.pool
- The size of the alphabet the password was drawn from.
- analysis.bits
- `H = L·log2(N)`, the same formula as the home page. With `no_repeats` it becomes `log2(N)+(L-1)·log2(N-1)`.
- analysis.log10_guesses
- The expected work, as a base-10 logarithm: half the keyspace.
- analysis.crack_time_log10_seconds
- At 10^12 guesses/s, offline, fast hash. The same attack model as the rest of the site.
- analysis.crack_time
- The same figure in words. `unit` follows the answer language: `years`, `años`…
- analysis.level
- 0–4. The same scale as the checker, ever since the site unified the two it used to have.
- analysis.level_scale
- `"time"`. Says where the level came from, so that a future divergence is visible instead of having to be inferred by comparing numbers.
- analysis.ceiling
- `false`: the server generated the password, so the figure is exact and not a ceiling. The same flag the checker uses.
- notice
- The antipattern warning, in every single response.
- _meta.plan
- `"anonymous"`. The only lane there is; the others arrive with accounts.
- _meta.lang
- `{ "messages", "links" }` — which language each half actually came back in. They can differ, and that is why the API says so instead of leaving you to guess.
- _meta.limits.burst
- The rate limit actually enforced: `limit` requests per `window_seconds`.
- _meta.quota
- The reserved daily-quota slot. `limit` and `remaining` are `null` because nobody counts daily requests yet.
- _meta.docs
- A link back to the documentation.

## De taal van het antwoord

Standaard antwoordt het in het Engels, wat iemand verwacht die zonder iets te zeggen integreert. Drie manieren om dat te veranderen, en de eerste wint als ze elkaar tegenspreken: `?lang=` in de URL, `"lang"` in de body, en de header `Accept-Language`.

Er zit hier een scheefheid die je moet weten: **de berichten bestaan in het Engels en het Spaans; de links, in alle achttien talen van de site.** Duits vragen geeft je Duitse links en berichten nog steeds in het Engels.

Het verzoek

```
curl -X POST 'https://api.password.es/v1/generate?lang=de' \
  -H 'content-type: application/json' \
  -d '{"length":20}'
```

Het antwoord

```
"_meta": {
  "lang": { "messages": "en", "links": "de" }
}
```

Je hoeft niet te gissen: elk antwoord zegt in `_meta.lang` wat er op elke helft is toegepast. En een taal die niet bestaat is geen fout — hij valt terug op Engels, en `_meta.lang` zegt dat.

## Een wachtwoord controleren: nog niet

`/v1/check` geeft `501` terug. Het is geen bug en geen vergissing: het is opzet, en het antwoord legt uit wat er ontbreekt en waar je intussen terechtkunt. `checker_url` wijst naar de checker van de site in de taal die je vroeg.

Het verzoek

```
curl -X POST https://api.password.es/v1/check \
  -H 'content-type: application/json' \
  -d '{"password":"x"}'
```

Het antwoord

```
{
  "error": "not_implemented",
  "message": "/v1/check does not exist yet. Returning the same numbers as the password.es checker requires its very same pattern engine, and that costs between 11 ms and 3.6 s of CPU per request depending on the input: it is waiting on a plan cap decision and on a length cap. Meanwhile the web checker does exactly this in your browser, sending nothing: https://password.es/en/checker/",
  "checker_url": "https://password.es/en/checker/",
  "docs": "https://password.es/api/",
  "_meta": { "…": "igual que arriba" }
}
```

## De fouten

Ze hebben allemaal dezelfde vorm: een korte `error` als code, een `message` in gewone taal —dat is wat een AI-assistent aan zijn gebruiker voorleest—, soms het `field` dat het veroorzaakte, een `docs` en dezelfde `_meta` als altijd.

- HTTP
- error
- Notes
- 400
- `invalid_length`
- `length` outside 4–64. `field` names it.
- 400
- `invalid_count`
- `count` outside 1–20. `field` names it.
- 400
- `empty_alphabet`
- All four character types turned off, so there is no alphabet to draw from. No `field`: it is the combination, not one parameter.
- 400
- `unknown_parameter`
- A parameter this endpoint does not accept. `field` gives the offending name.
- 429
- `rate_limited`
- Over 60 requests in a minute. Carries `Retry-After` and `RateLimit-*` headers, and `limit` / `window_seconds` in the body.
- 501
- `not_implemented`
- Only from `/v1/check`. Carries `checker_url`, pointing at the web checker in the answer language.

## De limieten

Eén, en het is de enige die echt wordt afgedwongen: **60 verzoeken per minuut per IP**. Je hoeft deze pagina niet te geloven: het getal reist mee in elk antwoord, in `_meta.limits.burst`.

Ga je eroverheen, dan is het antwoord een `429` met `Retry-After` en `RateLimit-*`-headers, plus een bericht in gewone taal dat zegt wat je moet doen. Er staat geen link naar registratie of prijzen in, want die zijn er niet.

In `_meta` zie je ook een blok `quota` met beide waarden op `null`. Dat is opzet: het is de gereserveerde plek voor als er accounts zijn, en hij is leeg omdat vandaag niemand verzoeken per dag telt. Een limiet die je aankondigt maar niet afdwingt is erger dan er geen aankondigen.

## De MCP-server

MCP is het protocol waarmee assistenten als Claude of ChatGPT externe tools gebruiken. Verbind dit adres met je assistent en die genereert wachtwoorden met precies deze cijfers in plaats van ze te verzinnen. Zonder registratie en zonder sleutel, met dezelfde limiet van 60 verzoeken per minuut.

Het is een **stateless** server, goed om te weten als je van andere MCP-servers komt: de POST wordt met JSON beantwoord en er wordt geen stream geopend, `Mcp-Session-Id` wordt niet verstuurd of verwacht, een notificatie krijgt `202` zonder body, en de GET geeft `405`. De specificatie 2025-06-18 staat dit expliciet toe.

```
curl -X POST https://api.password.es/mcp \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"generate_password",
                 "arguments":{"length":20,"lang":"es"}}}'
```

Er is **één tool**, `generate_password`, met dezelfde parameters als de tabel hierboven plus `lang`. Er is geen `check_password_strength` en die komt er niet zolang `/v1/check` niet bestaat: een tool die altijd een fout teruggeeft is geen tool, maar een gebroken belofte in de catalogus van een assistent.

De waarschuwing dat dit een antipatroon is, reist mee in de toolbeschrijving en in elk resultaat. Dat is bewust: het is wat de assistent uiteindelijk voorleest aan wie om het wachtwoord vroeg.

## De documentatie die machines lezen

Naast deze pagina is er een **OpenAPI 3.1**-beschrijving, en die is wél gepubliceerd: [api.password.es/openapi.json](https://api.password.es/openapi.json). Dat is wat een clientgenerator, een editor met autocompletion of een agent leest om te weten welke velden bestaan zonder dat iemand het vertelt. Hij beschrijft dezelfde parameters als de tabel hierboven, de foutcodes en waarom `quota` leeg is.
