Authentication¶
Every request to /v1/image needs an API key, sent as a bearer token:
Miss the header (or format it wrong) and you get 401 missing_api_key. Send
a key that doesn't exist or has been revoked and you get 401 invalid_api_key.
Keys are shown once, at creation. Purlo stores only a hash of your key — if you lose it, revoke it and issue a new one; the plaintext can't be recovered.
Getting a key¶
Free tier (no card)¶
The free tier (1,000 images/month) is self-service via an email-verified magic link — no card, about a minute.
- Request a key:
curl -X POST https://api.purlo.dev/v1/signup \
-H "Content-Type: application/json" \
-d '{"email": "you@example.com"}'
Always returns 202 { "message": "Check your email..." } (the response is
the same whether or not you already have an account). This endpoint is
rate-limited per IP — too many attempts return 429 rate_limited.
-
Click the link in the email. It's single-use and expires (30 minutes by default).
-
Get your key. The link opens
GET /v1/signup/verify?token=..., which returns:
The key is issued and returned once. Verify errors: invalid_token,
token_used, token_expired (all 400) — request a fresh link if needed.
If your account already has an active key, apiKey comes back null.
Paid tiers (Starter / Growth / Scale)¶
Paid signup is self-service via Stripe Checkout, no manual billing support needed:
- Start checkout:
curl -X POST https://api.purlo.dev/v1/billing/checkout \
-H "Content-Type: application/json" \
-d '{"tier": "starter", "email": "you@example.com"}'
Returns { "url": "https://checkout.stripe.com/..." }. tier must be one
of the tiers configured as purchasable (starter, growth, scale); an
unrecognised tier returns 400 invalid_tier.
-
Complete checkout at the returned URL (Stripe-hosted).
-
Get your key. On success, Stripe redirects to
GET /v1/billing/session/{id}/key, which returns:
The key is issued and returned once, on your account's first
successful checkout. If your account already has an active key,
apiKey comes back null — manage/rotate keys via the customer portal
instead of re-issuing.
Managing your subscription¶
Once you have a key, self-service upgrade, downgrade, cancel, and card updates all go through the Stripe Customer Portal:
Returns { "url": "https://billing.stripe.com/..." } — a portal session for
your account. No manual billing support required.
Your tier (and therefore quota) updates automatically when your subscription changes; Stripe's webhook is the source of truth, so it applies whether you manage billing through the portal or Checkout.
Issuing keys yourself (self-hosting)¶
If you run Purlo, the npm run keys CLI mints keys directly, no email needed:
npm run keys -- create-account you@example.com free
npm run keys -- issue you@example.com # prints the key once
Using your key¶
Every call to /v1/image needs it: