Recover API Key

Start the API key recovery flow. Directs users to sign in to the dashboard via a magic link.

POSThttps://api.boringmarketing.com/auth/recover

Starts the API key recovery flow. This endpoint never returns an API key in the response — by design. The response directs the caller to sign in to the dashboard, where they can view or rotate their key after verifying ownership of the email via a magic link.

This is not an account-existence check. The response shape is identical whether the email matches a registered account or not — there is no exists: true|false field, no 404 branch, and the message / dashboard_url payload never varies. Agents that try to use /auth/recover as a lookup for "does this email have an account?" will be misled by the response body.

Security: why the response is uniform

The handler is timing-padded at the Python level: regardless of whether the email resolves to a user, it executes the same sequence of database lookups (one real, one against a sentinel address) so that branch-count divergence doesn't stack on top of any underlying cache-hit vs cache-miss timing oracle in the user store. This reduces branch asymmetry but does not claim to be fully timing-proof — the underlying cache layer can still differ in how long a hit vs a miss takes, and that is not mitigated at this endpoint.

Combined with the rate limit below, the intent is to make email enumeration impractical, not mathematically impossible.

The endpoint is also rate-limited 3 requests per hour per IP. Additional requests return 429 with a retry-after hint.

Request

emailstringrequired

The email address to recover. Lowercased and stripped server-side.

Response

{
  "message": "Sign in to your dashboard to view or rotate your API key.",
  "dashboard_url": "https://dashboard.boringmarketing.com"
}

The response shape never varies. Even on an unknown email, you get the same message and dashboard_url — the dashboard's sign-in flow is what actually gates access to the key.

Errors

StatusMeaning
422email is missing or not a string.
429Rate limit hit (more than 3 requests per hour from this IP).

Example

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}' \
  https://api.boringmarketing.com/auth/recover

Flow

  1. User (or agent on behalf of a user) calls POST /auth/recover with an email.
  2. Server logs the attempt, runs the timing-padded lookup, and returns the dashboard URL.
  3. User opens dashboard_url, signs in with a magic link sent to their email.
  4. Once signed in, the dashboard calls GET /auth/me/api-key internally to hydrate the session with the user's key.
  5. From the dashboard, the user can either view the key or call POST /auth/rotate-key to invalidate the old one and get a fresh one.