API
WoolKey can generate passwords and passphrases for your scripts, tools, and AI agents — the same generator the website uses, reachable over HTTP.
Do I need an API key?
Yes. Every generation request needs a key.
Send it as an X-Api-Key header. Without it the API replies
401 Unauthorized and generates nothing.
The read-only endpoints below — the health check, the description, and the spec — work without a key, so an agent can look up how the API works before it has one.
How to get a key
Keys are issued individually, on request. You get your own rather than a shared one, so usage stays traceable to a single key and any one key can be revoked without disturbing anybody else.
Ask for a key.
Get in touch through CoolerSheep with a line about
what you plan to use it for, and you'll be sent one. There is nothing to install, register,
or configure at your end — a key and the X-Api-Key header is the whole setup.
Treat the key like a password. Keep it in an environment variable or a password manager, never in client-side JavaScript, a public repository, or a screenshot. Anyone holding it can use your quota. Need to replace one? Ask for a new key and update your clients — the old one stops working, and there is nothing else to invalidate.
Quick start
Three steps from nothing to a generated password.
-
Check the API is up
No key needed for this one.
curl https://api.woolkey.com/healthYou should get back
{"status":"ok", ...}. -
Put your key in a variable
So it never ends up in your shell history or pasted into a chat.
export WOOLKEY_KEY="your-key-here" -
Generate a password
curl -X POST https://api.woolkey.com/generate \ -H "Content-Type: application/json" \ -H "X-Api-Key: $WOOLKEY_KEY" \ -d '{"mode":"password","options":{"length":24,"includeSymbols":true}}'The password comes back in the
valuefield.
Endpoints
Base URL: https://api.woolkey.com
/health Is the API up? No key needed./generate Describes every option and limit. No key needed./openapi.json Machine-readable spec. No key needed./generate Generates credentials. Key required.Making a request
Send POST to /generate with a JSON body. Only mode
is required — leave anything else out and a sensible default is used.
| Field | Type | Default | What it does |
|---|---|---|---|
mode | string | required | "password" or "passphrase" |
count | number | 1 | How many to generate at once, up to 20 |
options | object | {} | Settings for the chosen mode, below |
Options for mode: "password"
| Option | Default | What it does |
|---|---|---|
length | 24 | How many characters, from 8 to 128 |
includeLowercase | true | Use a–z |
includeUppercase | true | Use A–Z |
includeNumbers | true | Use 0–9 |
includeSymbols | false | Use !@#$%^&*()-_=+[]{};:,.? |
avoidAmbiguous | false | Leave out 0O1Il5S8B, which are easy to misread |
excludedCharacters | "" | Any other characters to avoid, e.g. "&$" |
Options for mode: "passphrase"
| Option | Default | What it does |
|---|---|---|
wordCount | 4 | How many words, from 4 to 8 |
separator | "hyphen" | "hyphen", "underscore", "dot" or "space" |
capitalize | false | Capitalise each word |
addNumber | false | Add a two-digit number on the end |
Ask for something out of range and you get a clear error rather than a silent
substitution. Requesting length: 200 returns
"options.length must be between 8 and 128" — it will never hand back a
24-character password and let you believe it is 200.
What you get back
{
"mode": "password",
"count": 1,
"value": "EXAMPLE-your-password-appears-here",
"entropy": { "bits": 149.95, "label": "Excellent", "level": 4 },
"metadata": { "entropyMode": "system", "poolSize": 76, "length": 24 },
"results": [ { "value": "...", "entropy": {...}, "metadata": {...} } ]
}
value— the generated password or passphrase. This is the part you want.entropy.bits— how hard it is to guess. Higher is better.entropy.label— the same number in words: Weak, Fair, Strong, Very strong, Excellent.results— one entry per credential. When you ask for several, they are all here.
If you only ever ask for one credential, read value and ignore
results — the top-level fields always mirror the first result.
Generating several at once
Set count to get a batch in a single request, which also uses only one of your
rate-limit slots instead of twenty.
curl -X POST https://api.woolkey.com/generate \
-H "Content-Type: application/json" \
-H "X-Api-Key: $WOOLKEY_KEY" \
-d '{"mode":"password","count":5,"options":{"length":32}}'
More examples
Passphrase
curl -X POST https://api.woolkey.com/generate \
-H "Content-Type: application/json" \
-H "X-Api-Key: $WOOLKEY_KEY" \
-d '{"mode":"passphrase","options":{"wordCount":6,"capitalize":true}}'
Gives you something like Eagle-Newer-Shock-Folio-Depot-Taste.
JavaScript
const res = await fetch('https://api.woolkey.com/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.WOOLKEY_KEY,
},
body: JSON.stringify({
mode: 'password',
options: { length: 24, includeSymbols: true },
}),
});
if (!res.ok) throw new Error((await res.json()).error);
const { value } = await res.json();
Python
import os, requests
res = requests.post(
"https://api.woolkey.com/generate",
headers={"X-Api-Key": os.environ["WOOLKEY_KEY"]},
json={"mode": "password", "options": {"length": 24, "includeSymbols": True}},
timeout=10,
)
res.raise_for_status()
password = res.json()["value"]
Postman
Don't build the requests by hand — import the ready-made collection. It arrives with every request filled in, documented, and with tests that check the responses.
Fastest: import by link
In Postman: Import → Link → paste this → Continue.
https://api.woolkey.com/woolkey.postman_collection.json
Then set your key: open the collection → Variables → paste it into
apiKey under Current value. That column stays on your machine, so
the key is not included if you later export or share the collection.
That's it. Hit Send on 1. Health check to confirm it works, then 3. Generate a password.
Or download the files
Drag either file onto the Postman window to import it.
baseUrl and a masked apiKey
Both files download straight from this site — no Postman account, and nothing published to a public workspace.
What's in the collection
| Request | Needs a key | What it shows |
|---|---|---|
| 1. Health check | No | Confirms the API is reachable before you worry about your key |
| 2. Describe the API | No | Every option and limit this server supports |
| 3. Generate a password | Yes | The main request, with all options laid out |
| 4. Generate a passphrase | Yes | Word-based credentials |
| 5. Generate a batch | Yes | Up to 20 at once from a single request |
| 6. Rejected request | Yes | Meant to fail — shows input being rejected, not silently altered |
The collection never saves a generated password into a Postman variable. Those are written to disk, and a password generator that leaves copies lying around would rather defeat the point. Copy what you need from the response straight into your password manager.
By hand
If you would rather set it up yourself: method POST, URL
https://api.woolkey.com/generate, headers
Content-Type: application/json and X-Api-Key: your-key, then
body → raw → JSON with any of the bodies above. Importing
openapi.json the same way works too, though it produces bare requests with no
tests or examples.
Connecting an AI agent
The API is designed so an agent can work it out on its own. Point it at the description endpoint and it learns every mode, option, default, and limit without you writing a schema:
curl https://api.woolkey.com/generate
For a tool definition, hand the agent the POST /generate schema from
openapi.json. Then:
- Keep the key in an environment variable, not in the tool definition itself.
- Tell the agent to treat
valueas a secret — not to print it, log it, or write it into a transcript. - Read the
errorandfieldfields on a failure; they say exactly what to fix.
When something goes wrong
Errors always come back as JSON, and name the field at fault where there is one:
{ "error": "options.length must be between 8 and 128",
"status": 400,
"field": "options.length" }
| Code | Meaning | What to do |
|---|---|---|
400 | Something in your request is wrong | Read error and field |
401 | Key missing or wrong | Check the X-Api-Key header |
413 | Request body over 16 KB | Send a smaller body |
429 | Too many requests | Wait the number of seconds in Retry-After |
503 | No key configured on the server | Nothing you can fix from the client — let the operator know |
Rate limits
20 requests per minute from one IP address. Every reply tells you where you stand:
X-RateLimit-Remaining— requests left in this minuteX-RateLimit-Reset— seconds until the count resetsRetry-After— on a429, how long to wait
Need a lot of credentials? Use count — one request for twenty passwords instead
of twenty requests.
What happens to what you generate
Nothing is stored. WoolKey generates the value, sends it to you, and keeps no copy — not in a database, not in a log file. There is no history to look up and nothing for us to lose. Saving it is your side of the job; send it straight to your password manager.
Requests are served over HTTPS and responses are marked no-store, so browsers
and proxies are told not to keep a copy either. See Security for the
full picture.
In-browser alternative
If your agent drives a real browser rather than speaking HTTP, this page's generator is
available directly on the WoolKey home page as window.WoolKeyAPI —
no key, no network request, nothing leaves the browser.
// Run this on the WoolKey home page
const result = window.WoolKeyAPI.generate({
mode: 'password',
count: 3,
options: { length: 24, includeSymbols: true },
});
if (!result.ok) throw new Error(result.error);
result.data.results.map(r => r.value);
It takes the same options as the HTTP endpoint and returns the same numbers, so you can swap
between the two. window.WoolKeyAPI.describe() lists everything available, and
generate() returns { ok: false, error } instead of throwing, which is
easier to handle from an automation script.
Reference
- openapi.json — full machine-readable specification
- api/generate — live description of this server's current limits
- Postman collection — six ready-made requests
- Postman environment — optional key holder
