# Référence de l'API de mots de passe · password.es

> Tous les paramètres de POST /v1/generate, chaque champ de la réponse, les codes d'erreur et les limites d'api.password.es. Avec un exemple curl qui marche.

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

---

# Référence de l'API de mots de passe

La référence d'`api.password.es` : chaque paramètre, chaque champ de la réponse, chaque code d'erreur et les limites. Les exemples se collent tels quels dans un terminal.

Si vous cherchez ce que c'est, pour qui et quand il vaut mieux *ne pas* l'utiliser, commencez par [la page de l'API](https://password.es/fr/api/).

## Les endpoints

Tout dépend de `https://api.password.es`. Deux répondent et un pas encore — et celui-là le dit dans sa propre réponse.

- POST/v1/generate Génère un ou plusieurs mots de passe et renvoie leur analyse.
- GET/openapi.json La description de l'API, en OpenAPI 3.1.
- POST/mcp Serveur MCP pour assistants. Un outil : `generate_password`.
- POST/v1/check 501 N'existe pas encore. L'erreur dit ce qui manque et où aller en attendant.

## Générer un mot de passe

Le corps est facultatif : sans lui, vous obtenez 16 caractères avec les quatre types activés. Avec lui, ce que vous demandez.

La requête

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

La réponse

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

## Les paramètres

Tous facultatifs. Le tableau est en anglais et identique dans les dix-huit langues, à dessein : celui qui intègre une API tape les noms de champ tels qu'ils s'écrivent, et dix-huit traductions d'`exclude_ambiguous` seraient une dette, pas une portée.

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

## Ce que veut dire chaque chiffre

Même principe : la référence en anglais, l'explication à côté. Aucun de ces chiffres n'est nouveau — ils sortent tous du même moteur qui dessine la jauge de la page d'accueil.

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

## La langue de la réponse

Par défaut elle répond en anglais, ce qu'attend quelqu'un qui intègre sans rien préciser. Trois façons d'en changer, et en cas de désaccord la première l'emporte : `?lang=` dans l'URL, `"lang"` dans le corps, et l'en-tête `Accept-Language`.

Il y a ici une asymétrie qu'il vaut mieux connaître : **les messages existent en anglais et en espagnol ; les liens, dans les dix-huit langues du site.** Demander l'allemand donne des liens en allemand et des messages toujours en anglais.

La requête

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

La réponse

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

Pas besoin de deviner : chaque réponse déclare dans `_meta.lang` ce qui a été appliqué à chaque moitié. Et une langue qui n'existe pas n'est pas une erreur — elle retombe sur l'anglais, et `_meta.lang` le dit.

## Vérifier un mot de passe : pas encore

`/v1/check` renvoie `501`. Ce n'est ni un bug ni un oubli : c'est voulu, et la réponse explique ce qui manque et où aller en attendant. `checker_url` pointe vers le vérificateur du site dans la langue demandée.

La requête

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

La réponse

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

## Les erreurs

Elles ont toutes la même forme : un `error` court pour le code, un `message` en clair —c'est ce qu'un assistant d'IA lit à son utilisateur—, parfois le `field` qui l'a provoqué, un `docs` et le même `_meta` que d'habitude.

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

## Les limites

Une seule, et c'est celle qui s'applique vraiment : **60 requêtes par minute et par IP**. Pas besoin de croire cette page : le nombre voyage dans chaque réponse, dans `_meta.limits.burst`.

En cas de dépassement, la réponse est un `429` avec `Retry-After` et des en-têtes `RateLimit-*`, plus un message en clair qui dit quoi faire. Il ne contient aucun lien vers une inscription ou des tarifs, parce qu'il n'y a ni inscription ni tarifs.

Dans `_meta`, on trouve aussi un bloc `quota` dont les deux valeurs sont à `null`. C'est voulu : c'est la place réservée pour le jour où les comptes existeront, et elle est vide parce qu'aujourd'hui personne ne compte les requêtes par jour. Une limite annoncée et non appliquée est pire que pas de limite annoncée du tout.

## Le serveur MCP

MCP est le protocole avec lequel des assistants comme Claude ou ChatGPT utilisent des outils externes. Connectez cette adresse à votre assistant et il générera des mots de passe avec ces mêmes chiffres au lieu de les inventer. Sans inscription et sans clé, avec la même limite de 60 requêtes par minute.

C'est un serveur **sans état**, et il vaut mieux le savoir si vous venez d'autres serveurs MCP : le POST reçoit une réponse JSON sans ouvrir de flux, `Mcp-Session-Id` n'est ni émis ni attendu, une notification reçoit `202` sans corps, et le GET renvoie `405`. La spécification 2025-06-18 l'autorise explicitement.

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

Il publie **un seul outil**, `generate_password`, avec les mêmes paramètres que le tableau ci-dessus plus `lang`. Il n'y a pas de `check_password_strength` et il n'y en aura pas tant que `/v1/check` n'existera pas : un outil qui renvoie toujours une erreur n'est pas un outil, c'est une promesse rompue dans le catalogue d'un assistant.

L'avertissement disant que c'est un antipatron voyage dans la description de l'outil et dans chaque résultat. C'est délibéré : c'est ce que l'assistant finit par lire à celui qui a demandé le mot de passe.

## La documentation que lisent les machines

En plus de cette page, il existe une description en **OpenAPI 3.1**, et celle-là est bien publiée : [api.password.es/openapi.json](https://api.password.es/openapi.json). C'est ce que lit un générateur de clients, un éditeur avec autocomplétion ou un agent qui veut savoir quels champs existent sans que personne le lui dise. Elle décrit les mêmes paramètres que le tableau ci-dessus, les codes d'erreur et la raison du `quota` vide.
