API tokens & magic links

How tokens are minted, rotated, and revoked. How the magic-link sign-in flow keeps your account out of password-leak databases.

API tokens

Every MCP request to your endpoint is authenticated with a Bearer token. Tokens are scoped to a single endpoint — a token for endpoint A cannot be used to query endpoint B.

How they're minted

When you click Create token in the dashboard:

  1. The dashboard generates 32 random bytes from crypto.getRandomValues() and prefixes them with smcp_.
  2. It computes the SHA-256 hash of the raw token.
  3. The hash, plus a label and timestamp, is stored in D1. The raw token is never stored.
  4. The dashboard returns the raw token to the browser exactly once, in the green reveal box. We blur it by default and offer a copy button.

That means we cannot show you the value of an existing token — even an admin with full database access only sees the hash. If you lose a token, rotate it.

Rotating a token

From the endpoint detail page or the global Settings page, click Rotate next to a token. We mint a new token, mark the old hash revoked_at, and send you an email confirming the rotation. The old token returns 401 immediately.

Revoking a token

Same flow without minting a replacement. Click Revoke; the row's revoked_at is set; the next request from that token gets 401. No grace period.

Magic-link sign-in

Passwords leak. Reuse is rampant. Magic links sidestep the entire problem. From /auth/magic-link, enter your email — we send you a one-time URL that signs you in with no password.

How it works under the hood

  1. You submit your email.
  2. The dashboard generates a 32-byte random token, computes its SHA-256 hash, and stores (hash, email, expires_at, used_at = null) in D1. The raw token never hits the database.
  3. Loops sends an email containing https://shipmcp.io/auth/verify/<raw-token>. The link expires in 15 minutes.
  4. You click. The verify route hashes the URL token, looks up the row, checks expires_at and used_at, then atomically UPDATEs used_at = now() and re-reads the row to confirm we won the consume race.
  5. Session created, redirect to /endpoints.

Security properties

  • Single-use: used_at means clicking the link twice fails.
  • Time-limited: 15-minute TTL.
  • Hash-only storage: a D1 leak doesn't grant logins — the attacker would still need the raw token from the email.
  • No account enumeration: the form returns the same "check your email" success state regardless of whether the email is registered.

When to use magic-link vs password

Both flows result in the same session. Pick whichever suits the moment — magic-link is the official "forgot password" recovery path, since we don't issue password resets separately. If you log in often from one machine, a password is probably faster. If you're on a new device or have lost your password, magic-link is the answer.

shield_locked

Why no SMS or TOTP yet? SMS adds SIM-swap risk; TOTP is a project we want to do well rather than rush. For Scale-tier customers who require MFA today, contact us — we can enable an Authenticator app on a per-account basis while we ship the broader rollout.