{
  "openapi": "3.1.1",
  "info": {
    "title": "Password & Passphrase Generator API",
    "version": "1.0.0",
    "summary": "Strong random passwords and passphrases, made in your browser, with exact entropy.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://passwordgenerator.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Strong random passwords and passphrases, made in your browser, with exact entropy.",
        "description": "Generates random passwords (length, character sets, no look-alike characters, at least one of each class) or passphrases from a 2048-word list with separators and capitalisation. Shows the exact entropy in bits and how long guessing would take. With JavaScript on, everything is generated locally in your browser.\n\nMethodology:\n- Random password: every character is drawn uniformly from the selected sets with an unbiased random integer (rejection sampling, no modulo bias). \"At least one of each set\" regenerates the whole password until the rule holds, which keeps all valid passwords equally likely.\n- Entropy is exact: log2 of the number of possible passwords. With \"at least one of each set\" the count is computed by inclusion–exclusion, so it is slightly lower than length × log2(pool size).\n- Passphrase: words are drawn uniformly from a bundled list of 2048 common English words (4–8 letters), so each word adds exactly 11 bits. Random capitalisation adds 1 bit per word; an appended digit adds log2(10 × words) bits.\n- Guessing times assume the attacker knows exactly how the password was generated (the worst case) and finds it on average after trying half of all possibilities.\n- In the browser, passwords are generated locally with crypto.getRandomValues and never sent anywhere. Without JavaScript (and via the API/MCP), the server generates them with Node.js crypto.randomInt and sends them back over HTTPS without storing them.\n\nUse a password manager and a different password for every account. Seeded output is for demos only.",
        "tags": [
          "crypto"
        ],
        "x-mcp-tool": "password_generator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PasswordGeneratorInput"
              },
              "examples": {
                "example1": {
                  "summary": "5 passwords, 20 characters, all sets (demo seed)",
                  "value": {
                    "mode": "password",
                    "length": 20,
                    "count": 5,
                    "seed": "demo"
                  }
                },
                "example2": {
                  "summary": "6-word passphrase, Title Case, with a digit (demo seed)",
                  "value": {
                    "mode": "passphrase",
                    "words": 6,
                    "capitalization": "title",
                    "includeNumber": true,
                    "count": 3,
                    "seed": "demo"
                  }
                },
                "example3": {
                  "summary": "12 characters, letters and digits, no look-alikes (demo seed)",
                  "value": {
                    "mode": "password",
                    "length": 12,
                    "charsets": [
                      "lower",
                      "upper",
                      "digits"
                    ],
                    "excludeAmbiguous": true,
                    "count": 3,
                    "seed": "example"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PasswordGeneratorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "PasswordGeneratorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "mode": {
            "title": "Type",
            "type": "string",
            "enum": [
              "password",
              "passphrase"
            ],
            "default": "password"
          },
          "length": {
            "title": "Password length",
            "description": "Random password only. 16+ characters are recommended; 20+ for important accounts.",
            "type": "integer",
            "minimum": 4,
            "maximum": 128,
            "default": 20,
            "x-unit": "characters"
          },
          "charsets": {
            "title": "Character sets",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "lower",
                "upper",
                "digits",
                "symbols"
              ]
            },
            "default": [
              "lower",
              "upper",
              "digits",
              "symbols"
            ]
          },
          "excludeAmbiguous": {
            "title": "Avoid look-alike characters (I l 1 O 0 o | ` ' \")",
            "type": "boolean",
            "default": false
          },
          "requireEach": {
            "title": "Include at least one character from each selected set",
            "type": "boolean",
            "default": true
          },
          "words": {
            "title": "Number of words",
            "description": "Passphrase only. Each word adds 11 bits of entropy.",
            "type": "integer",
            "minimum": 3,
            "maximum": 20,
            "default": 6
          },
          "separator": {
            "title": "Word separator",
            "type": "string",
            "enum": [
              "hyphen",
              "space",
              "period",
              "underscore",
              "none"
            ],
            "default": "hyphen"
          },
          "capitalization": {
            "title": "Capitalisation",
            "type": "string",
            "enum": [
              "lower",
              "title",
              "upper",
              "random"
            ],
            "default": "lower"
          },
          "includeNumber": {
            "title": "Append a random digit to one random word",
            "type": "boolean",
            "default": false
          },
          "count": {
            "title": "How many",
            "type": "integer",
            "minimum": 1,
            "maximum": 20,
            "default": 5
          },
          "seed": {
            "title": "Demo seed (optional, makes output reproducible — never for real passwords)",
            "description": "Leave empty for real use. With a seed, anyone who knows it can regenerate the same passwords.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": []
      },
      "PasswordGeneratorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "mode",
              "passwords",
              "entropyBits",
              "strength",
              "poolSize",
              "length",
              "words",
              "wordlist",
              "seeded",
              "crackTimes"
            ],
            "properties": {
              "mode": {
                "type": "string",
                "enum": [
                  "password",
                  "passphrase"
                ]
              },
              "passwords": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "entropyBits": {
                "type": "number",
                "description": "Entropy of each generated password in bits (log2 of the number of equally likely outputs)."
              },
              "strength": {
                "type": "string",
                "enum": [
                  "weak",
                  "fair",
                  "strong",
                  "very strong"
                ]
              },
              "poolSize": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Characters in the pool (password mode)."
              },
              "length": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "words": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "wordlist": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "required": [
                  "id",
                  "size"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "size": {
                    "type": "integer"
                  }
                }
              },
              "seeded": {
                "type": "boolean"
              },
              "crackTimes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "scenario",
                    "guessesPerSecond",
                    "averageSeconds"
                  ],
                  "properties": {
                    "scenario": {
                      "type": "string"
                    },
                    "guessesPerSecond": {
                      "type": "number"
                    },
                    "averageSeconds": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}