# Referência da API de palavras-passe · password.es

> Todos os parâmetros de POST /v1/generate, cada campo da resposta, os códigos de erro e os limites de api.password.es. Com um exemplo em curl que funciona.

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

---

# Referência da API de palavras-passe

A referência de `api.password.es`: cada parâmetro, cada campo da resposta, cada código de erro e os limites. Os exemplos colam-se num terminal tal como estão.

Se o que procuras é o que isto é, para quem e quando *não* convém usá-lo, começa por [a página da API](https://password.es/pt/api/).

## Os endpoints

Tudo pende de `https://api.password.es`. Dois respondem e um ainda não — e esse di-lo na sua própria resposta.

- POST/v1/generate Gera uma ou várias palavras-passe e devolve a sua análise.
- GET/openapi.json A descrição da API, em OpenAPI 3.1.
- POST/mcp Servidor MCP para assistentes. Uma ferramenta: `generate_password`.
- POST/v1/check 501 Ainda não existe. O erro explica o que falta e para onde ir entretanto.

## Gerar uma palavra-passe

O corpo é opcional: sem ele saem 16 caracteres com os quatro tipos activos. Com ele, o que pedires.

O pedido

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

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

## Os parâmetros

Todos opcionais. A tabela vai em inglês e é idêntica nas dezoito línguas, de propósito: quem integra uma API escreve os nomes dos campos tal como se escrevem, e dezoito traduções de `exclude_ambiguous` seriam dívida, não âmbito.

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

## O que significa cada número

A mesma ideia: a referência em inglês, a explicação ao lado. Nenhum destes números é novo — saem todos do mesmo motor que desenha o medidor da página inicial.

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

## A língua da resposta

Por omissão responde em inglês, que é o que espera quem integra sem dizer nada. Muda-se de três formas, e se houver desacordo ganha a primeira: `?lang=` no URL, `"lang"` no corpo e o cabeçalho `Accept-Language`.

Há aqui uma assimetria que convém saber: **as mensagens existem em inglês e espanhol; as ligações, nas dezoito línguas do sítio.** Pedir alemão dá-te ligações em alemão e mensagens ainda em inglês.

O pedido

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

A resposta

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

Não é preciso adivinhar: cada resposta declara em `_meta.lang` o que foi aplicado a cada metade. E uma língua que não existe não é um erro — cai para inglês, e `_meta.lang` di-lo.

## Verificar uma palavra-passe: ainda não

`/v1/check` devolve `501`. Não é um erro nem um esquecimento: é de propósito, e a resposta explica o que falta e para onde ir entretanto. O `checker_url` aponta para o verificador do sítio na língua que pediste.

O pedido

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

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

## Os erros

Têm todos a mesma forma: um `error` curto para o código, uma `message` em prosa —é o que um assistente de IA lê ao seu utilizador—, às vezes o `field` que o provocou, um `docs` e o mesmo `_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.

## Os limites

Um só, e é o que se aplica de verdade: **60 pedidos por minuto e por IP**. Não é preciso acreditar nesta página: o número viaja em cada resposta, dentro de `_meta.limits.burst`.

Ao passar disso, a resposta é um `429` com `Retry-After` e cabeçalhos `RateLimit-*`, mais uma mensagem em prosa que diz o que fazer. Não leva ligação para registo nem para preços, porque não há registo nem preços.

Em `_meta` verás ainda um bloco `quota` com os dois valores a `null`. Está assim de propósito: é o espaço reservado para quando existirem contas, e vai vazio porque hoje ninguém conta pedidos por dia. Um limite anunciado e não feito cumprir é pior do que não anunciar nenhum.

## O servidor MCP

MCP é o protocolo com que assistentes como o Claude ou o ChatGPT usam ferramentas externas. Liga este endereço ao teu assistente e ele gerará palavras-passe com estes mesmos números em vez de as inventar. Sem registo e sem chave, com o mesmo limite de 60 pedidos por minuto.

É um servidor **sem estado**, e convém sabê-lo se vens de outros servidores MCP: o POST é respondido com JSON e não se abre nenhum stream, `Mcp-Session-Id` não é emitido nem esperado, uma notificação recebe `202` sem corpo, e o GET devolve `405`. A especificação 2025-06-18 permite-o explicitamente.

```
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 **uma única ferramenta**, `generate_password`, com os mesmos parâmetros da tabela acima mais `lang`. Não há `check_password_strength` e não haverá enquanto `/v1/check` não existir: uma ferramenta que devolve sempre erro não é uma ferramenta, é uma promessa quebrada dentro do catálogo de um assistente.

O aviso de que isto é um antipadrão viaja na descrição da ferramenta e em cada resultado. É deliberado: é o que o assistente acaba por ler a quem pediu a palavra-passe.

## A documentação que as máquinas lêem

Além desta página há uma descrição em **OpenAPI 3.1**, e essa sim está publicada: [api.password.es/openapi.json](https://api.password.es/openapi.json). É o que lê um gerador de clientes, um editor com preenchimento automático ou um agente que queira saber que campos existem sem que ninguém lho conte. Descreve os mesmos parâmetros da tabela acima, os códigos de erro e o porquê do `quota` vazio.
