# Dokumentacja API haseł · password.es

> Wszystkie parametry POST /v1/generate, każde pole odpowiedzi, kody błędów i limity api.password.es. Z działającym przykładem w curl.

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

---

# Dokumentacja API haseł

Dokumentacja `api.password.es`: każdy parametr, każde pole odpowiedzi, każdy kod błędu i limity. Przykłady wkleja się do terminala tak, jak stoją.

Jeśli szukasz tego, czym to jest, dla kogo i kiedy lepiej go *nie* używać, zacznij od [strony API](https://password.es/pl/api/).

## Endpointy

Wszystko wisi pod `https://api.password.es`. Dwa odpowiadają, a jeden jeszcze nie — i ten mówi to we własnej odpowiedzi.

- POST/v1/generate Tworzy jedno lub kilka haseł i zwraca ich analizę.
- GET/openapi.json Opis API w formacie OpenAPI 3.1.
- POST/mcp Serwer MCP dla asystentów. Jedno narzędzie: `generate_password`.
- POST/v1/check 501 Jeszcze nie istnieje. Błąd mówi, czego brakuje i gdzie iść w międzyczasie.

## Tworzenie hasła

Ciało jest opcjonalne: bez niego wychodzi 16 znaków ze wszystkimi czterema rodzajami. Z nim — to, o co poprosisz.

Żądanie

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

Odpowiedź

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

## Parametry

Wszystkie opcjonalne. Tabela jest po angielsku i identyczna we wszystkich osiemnastu językach, celowo: kto wpina API, wpisuje nazwy pól dokładnie tak, jak się je pisze, a osiemnaście tłumaczeń `exclude_ambiguous` byłoby długiem, nie zakresem.

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

## Co znaczy każda liczba

Ta sama zasada: referencja po angielsku, wyjaśnienie obok. Żadna z tych liczb nie jest nowa — wszystkie wychodzą z tego samego silnika, który rysuje wskaźnik na stronie głównej.

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

## Język odpowiedzi

Domyślnie odpowiada po angielsku, bo tego oczekuje ktoś, kto wpina API bez słowa. Zmienia się to na trzy sposoby, a przy rozbieżności wygrywa pierwszy: `?lang=` w URL, `"lang"` w ciele i nagłówek `Accept-Language`.

Jest tu asymetria, o której warto wiedzieć: **komunikaty istnieją po angielsku i hiszpańsku; odnośniki — we wszystkich osiemnastu językach serwisu.** Poproszenie o niemiecki daje niemieckie odnośniki i komunikaty wciąż po angielsku.

Żądanie

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

Odpowiedź

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

Nie trzeba zgadywać: każda odpowiedź deklaruje w `_meta.lang`, co zastosowano do której połowy. A język, którego nie ma, nie jest błędem — spada do angielskiego, i `_meta.lang` to mówi.

## Sprawdzanie hasła: jeszcze nie

`/v1/check` zwraca `501`. To nie błąd ani przeoczenie: tak ma być, a odpowiedź tłumaczy, czego brakuje i gdzie iść w międzyczasie. `checker_url` wskazuje na sprawdzanie na stronie w języku, o który poprosiłeś.

Żądanie

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

Odpowiedź

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

## Błędy

Wszystkie mają ten sam kształt: krótki `error` jako kod, `message` zwykłym językiem —to właśnie czyta asystent AI swojemu użytkownikowi—, czasem `field`, które go wywołało, `docs` i to samo `_meta` co zawsze.

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

## Limity

Jeden, i to ten, który naprawdę jest egzekwowany: **60 żądań na minutę na adres IP**. Nie trzeba wierzyć tej stronie: liczba podróżuje w każdej odpowiedzi, w `_meta.limits.burst`.

Po przekroczeniu odpowiedzią jest `429` z `Retry-After` i nagłówkami `RateLimit-*` oraz komunikat zwykłym językiem, co robić. Nie ma w nim odnośnika do rejestracji ani do cennika, bo nie ma rejestracji ani cennika.

W `_meta` zobaczysz też blok `quota` z obiema wartościami na `null`. Tak jest celowo: to miejsce zarezerwowane na czas, gdy pojawią się konta, i jest puste, bo dziś nikt nie liczy żądań na dobę. Limit ogłoszony i nieegzekwowany jest gorszy niż nieogłoszenie żadnego.

## Serwer MCP

MCP to protokół, którym asystenci tacy jak Claude czy ChatGPT korzystają z zewnętrznych narzędzi. Podłącz ten adres do swojego asystenta, a będzie generował hasła z dokładnie tymi liczbami, zamiast je wymyślać. Bez rejestracji i bez klucza, z tym samym limitem 60 żądań na minutę.

To serwer **bezstanowy**, i warto o tym wiedzieć, jeśli przychodzisz z innych serwerów MCP: na POST odpowiada JSON-em i nie otwiera strumienia, `Mcp-Session-Id` nie jest wysyłany ani oczekiwany, powiadomienie dostaje `202` bez treści, a GET zwraca `405`. Specyfikacja 2025-06-18 wprost na to pozwala.

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

Publikuje **jedno narzędzie**, `generate_password`, z tymi samymi parametrami co tabela powyżej plus `lang`. Nie ma `check_password_strength` i nie będzie, dopóki nie istnieje `/v1/check`: narzędzie, które zawsze zwraca błąd, nie jest narzędziem — to złamana obietnica w katalogu asystenta.

Ostrzeżenie, że to antywzorzec, podróżuje w opisie narzędzia i w każdym wyniku. To celowe: to właśnie asystent odczyta osobie, która poprosiła o hasło.

## Dokumentacja, którą czytają maszyny

Poza tą stroną istnieje opis w **OpenAPI 3.1**, i ten jest opublikowany: [api.password.es/openapi.json](https://api.password.es/openapi.json). To właśnie czyta generator klientów, edytor z podpowiadaniem albo agent, który chce się dowiedzieć, jakie pola istnieją, bez pytania kogokolwiek. Opisuje te same parametry co tabela powyżej, kody błędów i powód pustego `quota`.
