Free 2FA API for Developers

Add TOTP two-factor authentication to any app with three JSON endpoints. Free forever - Create an account, generate a key, start calling. CORS enabled.

Running WordPress? Don't use this API for it - Install our free plugin instead. It verifies codes locally on your own server, so your logins never depend on anyone else's uptime. WordPress plugin
4
Endpoints
$0
Forever
RFC 6238
Standard TOTP

Quick Start

0. Get your free API key

Every request needs a key so we can keep the service free and abuse-free. Creating one takes about fifteen seconds:

  1. Open the account page and sign in with Google (or create a vault passphrase - Either works).
  2. In the sidebar, click Generate key under "2FA API key".
  3. Send it on every call as Authorization: Bearer pgn_live_… (X-API-Key and ?api_key= also work).

Keep it server-side. The key identifies your app, so treat it like any other credential and rotate it from the same panel if it ever leaks. Rotation takes effect immediately.

1. Create a secret for a user

curl -H "Authorization: Bearer $PGN_API_KEY" \
  "https://passwordgenerator.now/api/2fa/secret?issuer=MyApp&account=user@example.com"
{
  "secret": "JBSWY3DPEHPK3PXPJBSWY3DPEHPK3PXP",
  "otpauth_url": "otpauth://totp/MyApp:user@example.com?secret=…&issuer=MyApp",
  "qr_data_uri": "data:image/png;base64,…",
  "current_code": "492039",
  "period": 30, "digits": 6, "algorithm": "SHA1"
}

Show the user qr_data_uri (or /api/2fa/qr?secret=…&issuer=MyApp&account=… as a PNG URL), have them scan it with any authenticator app, and store secret encrypted in your database.

2. Verify codes at login

curl -X POST https://passwordgenerator.now/api/2fa/verify \
  -H "Authorization: Bearer $PGN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"secret": "JBSWY3DPEHPK3PXP…", "code": "492039"}'

# → {"valid": true}

Optional window parameter (default 1, max 4) accepts codes from adjacent 30-second windows to tolerate clock drift. Call this from your backend so the secret never reaches the browser.

All Endpoints

EndpointMethodPurpose
/api/2fa/secretGET / POSTNew base32 secret + otpauth URL + QR data-URI. Params: issuer, account
/api/2fa/codeGET / POSTCurrent 6-digit code for a secret + seconds remaining. Params: secret
/api/2fa/verifyPOSTVerify a code. Params: secret, code, optional window
/api/2fa/qrGETQR code as a PNG image. Params: secret, issuer, account

Code Examples

JavaScript (Node or backend fetch)

// Enrolment
const auth = {'Authorization': 'Bearer ' + process.env.PGN_API_KEY};
const res = await fetch('https://passwordgenerator.now/api/2fa/secret?issuer=MyApp&account=' + email, {headers: auth});
const {secret, qr_data_uri} = await res.json();
// … show qr_data_uri, save secret …

// Login verification
const check = await fetch('https://passwordgenerator.now/api/2fa/verify', {
  method: 'POST',
  headers: Object.assign({'Content-Type': 'application/json'}, auth),
  body: JSON.stringify({secret, code: userInput})
});
const {valid} = await check.json();

Python

import requests

r = requests.post("https://passwordgenerator.now/api/2fa/verify",
                  headers={"Authorization": f"Bearer {PGN_API_KEY}"},
                  json={"secret": secret, "code": code})
if r.json()["valid"]:
    login(user)

PHP

$ch = curl_init('https://passwordgenerator.now/api/2fa/verify');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['secret' => $secret, 'code' => $code]));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json',
    'Authorization: Bearer ' . $pgnApiKey]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$valid = json_decode(curl_exec($ch))->valid;

The Attribution Requirement

This API is free because attribution keeps it visible. In exchange for unlimited free calls, your site publishes one link back to this page. We verify it automatically.

  1. Add the link anywhere public on your site - Footer, docs page, security page or your 2FA settings screen.
  2. Register the page in your account under "2FA API key" and click Verify.
  3. Keep it live. We re-check daily. The first time a verified link disappears you get a 7-day grace window and an explanation, never a silent shutdown - Redesigns and migrations happen. After that first forgiveness, a link that disappears again pauses the key immediately, and putting the link back up re-activates it at the next daily check (or instantly if you click Verify).

Copy-paste snippet:

<a href="https://passwordgenerator.now/2fa-api">
  Two-factor authentication powered by PasswordGenerator.now
</a>
New keys get 14 days before verification is enforced, so you can build and test first. During the grace window every response includes a notice field counting down. After that, unverified keys return 402 attribution_required until the link is verified.

On link attributes: a normal followed link is what we ask for and what we check. If your policy or Google's link guidelines lead you to prefer rel="sponsored" or rel="nofollow", that still passes verification - We record which you used and never reject a qualified link. Attribution is the requirement; PageRank is not.

Embeddable 2FA Widget

Drop-in iframe

A self-contained TOTP code generator your users can use on your own pages - Great for docs, admin panels and demos:

<iframe
  src="https://passwordgenerator.now/embed/2fa"
  width="320" height="380"
  style="border:1px solid #e2e8f0;border-radius:10px;"
  title="2FA code generator"></iframe>

Pass ?secret=BASE32… to preload a secret. If you use the widget or API, please link back to passwordgenerator.now/2fa-api so others can find it.

Live preview

Fair Use & Notes

  • Stateless & private: secrets are never stored or logged; every request is computed in memory.
  • Free account required: generate a key in the account panel - It keeps the service free by making abuse revocable.
  • Fair use: keep it under ~60 requests/minute per key. Heavier? Talk to us.
  • Production advice: verify on your backend, store secrets encrypted, and offer backup codes.
  • Attribution: a link back to this page from your docs is appreciated and keeps the service free.
  • Just need codes for yourself? Use the 2FA code generator.

FAQ

Is the 2FA API really free?
Yes - Free forever, no card, no usage tier. It needs a free account so each key can be attributed and abusive keys revoked without punishing everyone else. We ask for fair use (about 60 requests/minute) and a link back to this page from your docs or app.
Why do I need an account for a free API?
Accountability. An anonymous endpoint gets scraped and abused until it has to be rate-limited into uselessness or shut down. A key ties usage to an account, so we can revoke one bad actor instead of throttling everybody. Sign in with Google and generate a key in about fifteen seconds.
What happens if my API key leaks?
Rotate it from the same panel in your account - The old key stops working immediately. Keys only reach the free, stateless TOTP endpoints; they never grant access to your Password Wallet, which is encrypted with a separate key that never leaves your device.
Do you store the TOTP secrets sent to the API?
No. Every endpoint is stateless: secrets are used in memory to compute or verify a code and never written to disk or logs. Still, treat secrets as sensitive - Call verify from your backend, not the browser.
Which authenticator apps are compatible?
Any RFC 6238 TOTP app: Google Authenticator, Microsoft Authenticator, Authy, 1Password, Bitwarden, FreeOTP and more. We use the standard 30-second period, 6 digits and SHA-1.
Can I self-host this instead?
Any TOTP library (pyotp, otplib, speakeasy) implements the same RFC. The API exists so you can prototype in minutes or add 2FA where you cannot install dependencies.