Getting started

Bastion is a password audit API. It evaluates passwords and returns strength scores, crack time estimates, entropy, and real breach data.

The base URL for the native API is:

https://bastion.eande171.workers.dev

Free tier access

Native keys are for the free tier. They allow you to use all endpoints with a limit of 100 requests per day. If you need higher limits, use the RapidAPI listing.

Your first request

Register for a native key using your email. The email is hashed immediately before storage and is only used if you need to regenerate your key. You can also register here.

const res = await fetch("https://bastion.eande171.workers.dev/v1/keys/register", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: "you@example.com" }) }); const { api_key, regen_token } = await res.json();
curl -X POST https://bastion.eande171.workers.dev/v1/keys/register \ -H "Content-Type: application/json" \ -d '{"email": "you@example.com"}'
Store your api_key and regen_token securely. The regeneration token cannot be recovered after registration.

Then evaluate a password using your new key:

const res = await fetch("https://bastion.eande171.workers.dev/v1/evaluate", { method: "POST", headers: { "Authorization": "Bearer bsn_live_...", "Content-Type": "application/json" }, body: JSON.stringify({ password: "hunter2" }) }); const result = await res.json();
curl -X POST https://bastion.eande171.workers.dev/v1/evaluate \ -H "Authorization: Bearer bsn_live_..." \ -H "Content-Type: application/json" \ -d '{"password": "hunter2"}'

Authentication

Native API keys must be passed in the Authorization header using the Bearer scheme:

Authorization: Bearer bsn_live_...
PrefixPurpose
bsn_live_Live API key - used for authenticated requests
bsn_regen_Regeneration token - used to issue a new key if one is compromised
If you're accessing Bastion via RapidAPI, authentication is handled automatically by RapidAPI's proxy. You do not need to set an Authorization header.

Endpoint reference

POST /v1/evaluate
๐Ÿ”‘ Requires authentication

Evaluates a password and returns a full audit result including strength score, crack times, entropy, breach status, and feedback.

Query parameters

ParameterTypeDefaultDescription
hibpstringtrueSet to false to skip the HaveIBeenPwned breach check. breached and breach_count will be null in the response.

Request body

{ "password": "hunter2" }

Response

{ "score": 1, "strength": "Weak", "entropy_bits": 12.972441366563533, "crack_times": { "online_throttled": "3 days", "online_unthrottled": "13 minutes", "offline_slow_hash": "less than a second", "offline_fast_hash": "less than a second" }, "breached": true, "breach_count": 65744, "warning": "This is a very common password.", "suggestions": ["Add another word or two. Uncommon words are better."] }
FieldDescription
score0 (Very Weak) to 4 (Very Strong)
strengthHuman-readable label corresponding to the score
entropy_bitsPassword entropy in bits
crack_timesEstimated time to crack under four attack scenarios - throttled online, unthrottled online, slow offline hash, and fast offline hash
breachedWhether the password appears in known breaches. null if hibp=false
breach_countNumber of times seen in known breaches. null if hibp=false
warningA specific weakness warning, or null for stronger passwords
suggestionsImprovement suggestions, or null for stronger passwords
POST /v1/keys/register
No authentication required

Registers a new API key. Each email address can only be registered once. The email is hashed immediately before storage.

Request body

{ "email": "you@example.com" }

Response

{ "api_key": "bsn_live_...", "regen_token": "bsn_regen_..." }
Store both values securely. This regeneration token cannot be recovered after this response.
POST /v1/keys/regenerate
No authentication required

Invalidates the current API key and issues a new one. Useful if a key is compromised. A new regeneration token is also issued.

Request body

{ "email": "you@example.com", "regen_token": "bsn_regen_..." }

Response

{ "api_key": "bsn_live_...", "regen_token": "bsn_regen_..." }
The old key is immediately invalidated. Store the new regeneration token. If it is lost, the key cannot be regenerated.
GET /v1/keys/usage
๐Ÿ”‘ Requires authentication

Returns current usage statistics for the authenticated key. Free tier keys are capped at 100 requests per day.

Response

{ "tier": "Free", "usage": 42, "limit": 100, "hard_limit": null, "reset_at": 1234567890000 }

reset_at is a Unix timestamp in milliseconds. hard_limit is null if no hard cap has been set.

Note: hard_limit is only applicable to paid tiers using native keys (which don't currently exist).
The endpoint to alter hard_limit does exist but is not publicly documented.

Error reference

All errors return a JSON body with an appropriate HTTP status code. Handle them using res.json(). The error field is a stable machine-readable code; the message field is human-readable.

Error CodeStatusMessage
MISSING_AUTH_HEADER401No Authorization header provided.
INVALID_AUTH_HEADER401Authorization header is not in the correct format.
INVALID_API_KEY401Key does not have a valid bsn_live_ prefix.
API_KEY_NOT_FOUND401Key is valid but not registered.
INVALID_EMAIL400Email is not in a valid format.
EMAIL_ALREADY_EXISTS400Email is already registered.
INVALID_REGEN_TOKEN401Provided regeneration token is invalid.
RATE_LIMIT_EXCEEDED429API rate limit exceeded.
DEMO_LIMIT_EXCEEDED429Demo limit reached. Sign up for a free API key.
HARD_LIMIT_EXCEEDED429User-defined hard limit exceeded.
HARD_LIMIT_TOO_LOW400Provided hard limit is below the usage limit.
INVALID_JSON_BODY400Request body is missing or malformed.
PASSWORD_EMPTY400Password cannot be empty.
PASSWORD_TOO_LONG400Password cannot exceed 128 characters.
PAID_TIER_NOT_IMPLEMENTED501Features for paid tiers are not implemented yet.

Code examples

Evaluate a password

const res = await fetch("https://bastion.eande171.workers.dev/v1/evaluate", { method: "POST", headers: { "Authorization": "Bearer bsn_live_...", "Content-Type": "application/json" }, body: JSON.stringify({ password: "correct-horse-battery-staple" }) }); if (!res.ok) { const { error, message } = await res.json(); console.error(error, message); } else { const result = await res.json(); console.log(result); }
curl -X POST https://bastion.eande171.workers.dev/v1/evaluate \ -H "Authorization: Bearer bsn_live_..." \ -H "Content-Type: application/json" \ -d '{"password": "correct-horse-battery-staple"}'

Skip the breach check

const res = await fetch("https://bastion.eande171.workers.dev/v1/evaluate?hibp=false", { method: "POST", headers: { "Authorization": "Bearer bsn_live_...", "Content-Type": "application/json" }, body: JSON.stringify({ password: "correct-horse-battery-staple" }) });
curl -X POST "https://bastion.eande171.workers.dev/v1/evaluate?hibp=false" \ -H "Authorization: Bearer bsn_live_..." \ -H "Content-Type: application/json" \ -d '{"password": "correct-horse-battery-staple"}'

Regenerate a key

const res = await fetch("https://bastion.eande171.workers.dev/v1/keys/regenerate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: "you@example.com", regen_token: "bsn_regen_..." }) }); const { api_key, regen_token } = await res.json();
curl -X POST https://bastion.eande171.workers.dev/v1/keys/regenerate \ -H "Content-Type: application/json" \ -d '{"email": "you@example.com", "regen_token": "bsn_regen_..."}'

Check usage

const res = await fetch("https://bastion.eande171.workers.dev/v1/keys/usage", { headers: { "Authorization": "Bearer bsn_live_..." } }); const { tier, usage, limit, reset_at } = await res.json(); console.log(`${usage} / ${limit} requests used`);
curl https://bastion.eande171.workers.dev/v1/keys/usage \ -H "Authorization: Bearer bsn_live_..."