# Referenz der Passwort-API · password.es

> Alle Parameter von POST /v1/generate, jedes Feld der Antwort, die Fehlercodes und die Grenzen von api.password.es. Mit einem curl-Beispiel, das funktioniert.

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

---

# Referenz der Passwort-API

Die Referenz zu `api.password.es`: jeder Parameter, jedes Feld der Antwort, jeder Fehlercode und die Grenzen. Die Beispiele lassen sich so, wie sie dastehen, ins Terminal einfügen.

Wenn du wissen willst, was das ist, für wen und wann man es besser *nicht* benutzt, fang bei [der API-Seite](https://password.es/de/api/) an.

## Die Endpunkte

Alles hängt an `https://api.password.es`. Zwei antworten und einer noch nicht — und der eine sagt es in seiner eigenen Antwort.

- POST/v1/generate Erzeugt ein oder mehrere Passwörter und gibt ihre Analyse zurück.
- GET/openapi.json Die Beschreibung der API, in OpenAPI 3.1.
- POST/mcp MCP-Server für Assistenten. Ein Werkzeug: `generate_password`.
- POST/v1/check 501 Gibt es noch nicht. Der Fehler sagt, was fehlt und wohin man solange geht.

## Ein Passwort erzeugen

Der Body ist optional: ohne ihn bekommst du 16 Zeichen mit allen vier Zeichenarten. Mit ihm das, was du verlangst.

Die Anfrage

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

Die Antwort

```
{
  "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/"
  }
}
```

## Die Parameter

Alle optional. Die Tabelle steht auf Englisch und ist in allen achtzehn Sprachen identisch, mit Absicht: wer eine API einbindet, tippt die Feldnamen genau so, wie sie geschrieben sind, und achtzehn Übersetzungen von `exclude_ambiguous` wären Schuld, nicht Umfang.

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

## Was jede Zahl bedeutet

Dasselbe: die Referenz auf Englisch, die Erklärung daneben. Keine dieser Zahlen ist neu — sie kommen alle aus demselben Motor, der auf der Startseite die Anzeige zeichnet.

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

## Die Sprache der Antwort

Standardmäßig antwortet sie auf Englisch — das erwartet, wer ohne weitere Angabe einbindet. Drei Wege, das zu ändern, und bei Widerspruch gewinnt der erste: `?lang=` in der URL, `"lang"` im Body und der Header `Accept-Language`.

Hier gibt es eine Schieflage, die man kennen sollte: **die Meldungen gibt es auf Englisch und Spanisch; die Links in allen achtzehn Sprachen der Website.** Wer Deutsch verlangt, bekommt deutsche Links und Meldungen weiterhin auf Englisch.

Die Anfrage

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

Die Antwort

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

Raten muss man nicht: jede Antwort erklärt in `_meta.lang`, was auf welche Hälfte angewandt wurde. Und eine Sprache, die es nicht gibt, ist kein Fehler — sie fällt auf Englisch zurück, und `_meta.lang` sagt es.

## Ein Passwort prüfen: noch nicht

`/v1/check` gibt `501` zurück. Weder Bug noch Versehen: es ist Absicht, und die Antwort erklärt, was fehlt und wohin man solange geht. `checker_url` zeigt auf den Checker der Website in der angeforderten Sprache.

Die Anfrage

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

Die Antwort

```
{
  "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" }
}
```

## Die Fehler

Alle haben dieselbe Form: ein kurzer `error` als Code, ein `message` in Klartext —das ist es, was ein KI-Assistent seinem Nutzer vorliest—, manchmal das `field`, das ihn ausgelöst hat, ein `docs` und dasselbe `_meta` wie immer.

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

## Die Grenzen

Eine, und es ist die, die wirklich durchgesetzt wird: **60 Anfragen pro Minute und IP**. Man muss dieser Seite nicht glauben: die Zahl reist in jeder Antwort mit, in `_meta.limits.burst`.

Wer darüber hinausgeht, bekommt einen `429` mit `Retry-After` und `RateLimit-*`-Headern, dazu eine Nachricht in Klartext, die sagt, was zu tun ist. Sie enthält keinen Link auf Registrierung oder Preise, weil es weder Registrierung noch Preise gibt.

In `_meta` steht außerdem ein Block `quota`, beide Werte auf `null`. Das ist Absicht: der reservierte Platz für den Tag, an dem es Konten gibt — leer, weil heute niemand Anfragen pro Tag zählt. Eine angekündigte und nicht durchgesetzte Grenze ist schlimmer, als gar keine anzukündigen.

## Der MCP-Server

MCP ist das Protokoll, mit dem Assistenten wie Claude oder ChatGPT externe Werkzeuge nutzen. Verbinde diese Adresse mit deinem Assistenten, und er erzeugt Passwörter mit genau diesen Zahlen, statt sie zu erfinden. Ohne Registrierung, ohne Schlüssel und mit demselben Limit von 60 Anfragen pro Minute.

Es ist ein **zustandsloser** Server, und das ist wichtig zu wissen, wenn du von anderen MCP-Servern kommst: Der POST wird mit JSON beantwortet, ohne Stream, `Mcp-Session-Id` wird weder gesendet noch erwartet, eine Notification erhält `202` ohne Body, und der GET liefert `405`. Die Spezifikation 2025-06-18 erlaubt das ausdrücklich.

```
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 veröffentlicht **ein einziges Werkzeug**, `generate_password`, mit denselben Parametern wie in der Tabelle oben plus `lang`. Es gibt kein `check_password_strength` und wird keines geben, solange `/v1/check` nicht existiert: Ein Werkzeug, das immer einen Fehler zurückgibt, ist kein Werkzeug, sondern ein gebrochenes Versprechen im Katalog eines Assistenten.

Der Hinweis, dass dies ein Antipattern ist, reist in der Werkzeugbeschreibung und in jedem Ergebnis mit. Das ist Absicht: Es ist das, was der Assistent demjenigen vorliest, der nach dem Passwort gefragt hat.

## Die Dokumentation, die Maschinen lesen

Neben dieser Seite gibt es eine **OpenAPI-3.1**-Beschreibung, und die ist veröffentlicht: [api.password.es/openapi.json](https://api.password.es/openapi.json). Sie ist das, was ein Client-Generator, ein Editor mit Autovervollständigung oder ein Agent liest, um zu erfahren, welche Felder es gibt, ohne dass es ihm jemand sagt. Sie beschreibt dieselben Parameter wie die Tabelle oben, die Fehlercodes und den Grund für das leere `quota`.
