# Referència de l'API de contrasenyes · password.es

> Tots els paràmetres de POST /v1/generate, cada camp de la resposta, els codis d'error i els límits d'api.password.es. Amb un exemple en curl que funciona.

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

---

# Referència de l'API de contrasenyes

La referència d'`api.password.es`: cada paràmetre, cada camp de la resposta, cada codi d'error i els límits. Els exemples s'enganxen en un terminal tal com estan.

Si el que busques és què és això, per a qui i quan *no* convé fer-lo servir, comença per [la pàgina de l'API](https://password.es/ca/api/).

## Els endpoints

Tot penja de `https://api.password.es`. Dos responen i un encara no — i aquest ho diu en la seva pròpia resposta.

- POST/v1/generate Genera una o diverses contrasenyes i en torna l'anàlisi.
- GET/openapi.json La descripció de l'API, en OpenAPI 3.1.
- POST/mcp Servidor MCP per a assistents. Una eina: `generate_password`.
- POST/v1/check 501 Encara no existeix. L'error explica què falta i on anar mentrestant.

## Generar una contrasenya

El cos és opcional: sense ell surten 16 caràcters amb els quatre tipus activats. Amb ell, el que demanis.

La petició

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

La resposta

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

## Els paràmetres

Tots opcionals. La taula va en anglès i és idèntica en les divuit llengües, a propòsit: qui integra una API escriu els noms de camp tal com s'escriuen, i divuit traduccions d'`exclude_ambiguous` serien deute, no abast.

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

## Què vol dir cada número

La mateixa idea: la referència en anglès, l'explicació al costat. Cap d'aquests números és nou — surten tots del mateix motor que dibuixa el mesurador de la portada.

- 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 llengua de la resposta

Per defecte respon en anglès, que és el que espera qui integra sense dir res. Es canvia de tres maneres, i si no coincideixen guanya la primera: `?lang=` a l'URL, `"lang"` al cos i la capçalera `Accept-Language`.

Aquí hi ha una asimetria que convé saber: **els missatges existeixen en anglès i castellà; els enllaços, en les divuit llengües del lloc.** Demanar alemany et dona els enllaços en alemany i els missatges encara en anglès.

La petició

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

La resposta

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

No cal endevinar-ho: cada resposta declara a `_meta.lang` què s'ha aplicat a cada meitat. I una llengua que no existeix no és un error — cau a l'anglès, i `_meta.lang` ho diu.

## Comprovar una contrasenya: encara no

`/v1/check` torna `501`. No és un error ni un descuit: hi és a propòsit, i la resposta explica què falta i on anar mentrestant. El `checker_url` apunta al comprovador del lloc en la llengua que hagis demanat.

La petició

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

La resposta

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

## Els errors

Tots tenen la mateixa forma: un `error` curt per al codi, un `message` en prosa —que és el que un assistent d'IA llegeix al seu usuari—, de vegades el `field` que l'ha provocat, un `docs` i el mateix `_meta` de sempre.

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

## Els límits

Un de sol, i és el que s'aplica de veritat: **60 peticions per minut i per IP**. No cal creure's aquesta pàgina: el número viatja en cada resposta, dins de `_meta.limits.burst`.

En passar-se'n, la resposta és un `429` amb `Retry-After` i capçaleres `RateLimit-*`, més un missatge en prosa que diu què fer. No porta cap enllaç a registre ni a preus, perquè no hi ha registre ni preus.

A `_meta` hi veuràs també un bloc `quota` amb els dos valors a `null`. Hi és a propòsit: és el forat reservat per quan existeixin els comptes, i va buit perquè avui ningú no compta peticions per dia. Un límit anunciat i no fet complir és pitjor que no anunciar-ne cap.

## El servidor MCP

MCP és el protocol amb què assistents com Claude o ChatGPT fan servir eines externes. Connecta aquesta adreça al teu assistent i podrà generar contrasenyes amb aquests mateixos números en comptes d'inventar-se'ls. Sense registre i sense clau, amb el mateix límit de 60 peticions per minut.

És un servidor **sense estat**, i convé saber-ho si véns d'altres servidors MCP: el POST es respon amb JSON i no s'obre cap stream, `Mcp-Session-Id` no s'emet ni s'espera, una notificació es respon amb `202` i sense cos, i el GET retorna `405`. L'especificació 2025-06-18 ho permet explícitament.

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

Publica **una sola eina**, `generate_password`, amb els mateixos paràmetres de la taula de dalt més `lang`. No hi ha `check_password_strength` i no n'hi haurà mentre `/v1/check` no existeixi: una eina que sempre retorna error no és una eina, és una promesa trencada dins del catàleg d'un assistent.

L'avís que això és un antipatró viatja en la descripció de l'eina i en cada resultat. És deliberat: és el que l'assistent acaba llegint a qui ha demanat la contrasenya.

## La documentació que llegeixen les màquines

A més d'aquesta pàgina hi ha una descripció en **OpenAPI 3.1**, i aquesta sí que està publicada: [api.password.es/openapi.json](https://api.password.es/openapi.json). És el que llegeix un generador de clients, un editor amb autocompleció o un agent que vulgui saber quins camps existeixen sense que ningú l'hi digui. Descriu els mateixos paràmetres de la taula de dalt, els codis d'error i el perquè del `quota` buit.
