Skip to content
LogoLogo

Authentication

The Picked API supports four ways to authenticate. They are a session from an email address and a password, an OAuth provider, a magic link, and an API key. This guide covers each one. It also covers how to control a session and how to use multi-factor authentication (MFA).

Use a session

After the caller has a session, it puts the access token in the Authorization header of every request that needs authentication:

Authorization: Bearer <accessToken>

The expiresAt field of the session gives the time at which the access token expires. The caller must refresh the session before that time.

Authenticator assurance levels

The session holds an aal field, and it gives the strength of the authentication:

LevelMeaning
AAL1One factor: an email address and a password, OAuth, or a magic link
AAL2Two factors: the user verified a code from an authenticator app

Picked staff, and every member of an organization that requires MFA, must use AAL2. For these users, an AAL1 session can only do these operations:

  • Read user.
  • Call the MFA mutations.
  • Call passwordUpdate, if the user has no verified authenticator. Therefore, a user can set a password before they add an authenticator.

Every other operation returns the error code MFA_REQUIRED. Read session.user.mfa after sessionCreate to find out whether the user must verify, and see How to set up MFA for the steps.

The API checks the level when it creates a token. An OAuth token for an MCP client or the CLI is created at consent, which needs AAL2 for these users. The token stays valid until it is revoked.

The mutations

MutationWhat it does
sessionStartStarts a sign-in from an email address alone. Returns PASSWORD when the account has a password, and sessionCreate completes the sign-in. Otherwise sends an email with a six-digit code and a sign-in link, and returns EMAIL_CODE, and magicLinkVerify completes the sign-in. An address with no account also gets EMAIL_CODE, but no email. Too many requests from one client return RATE_LIMITED.
sessionCreateAuthenticates an email address and a password. Returns a session at AAL1. session.user.mfa says whether the user must verify.
sessionRefreshExchanges a refresh token for a new session. Needs no Authorization header.
accountCreateCreates an account. metadata takes any JSON.
accountVerifyEmailCompletes email verification with the token from the email.
accountResendVerificationSends the verification email again.
oauthAuthorizeReturns the authorization URL for a provider. Google is supported.
oauthCallbackExchanges an OAuth code for a session.
magicLinkSendSends an email with a six-digit code and a sign-in link to an account. Does not create an account. Returns success: true also for an address with no account, and sends no email to it.
magicLinkVerifyExchanges the six-digit code from the email for a session.
passwordResetSendSends a password reset email.
passwordUpdateSets or changes the password. Needs authentication. Needs AAL2 when the user has a verified authenticator, also when the user does not have to use MFA.
mfaFactorEnrollAdds an authenticator app. A new factor is UNVERIFIED. Returns the QR code and the key one time.
mfaChallengeCreateOpens a challenge against a factor.
mfaChallengeVerifyVerifies the code from the authenticator app. Moves the session to AAL2.
mfaFactorUnenrollRemoves an authenticator. Needs AAL2 for a verified factor.
apiKeyCreateCreates an API key. Only a user with a session can call it.
apiKeyRevokeInvalidates a key immediately.

Credentials

CredentialHeader
Session access tokenAuthorization: Bearer <accessToken>
API keyx-api-key: pk_live_abc123...