Mailbox challenges
Passlock exposes mailbox challenge endpoints for email one-time code flows such as signup verification, passwordless login, and email-change verification.
Create challenge
Section titled “Create challenge”POST https://api.passlock.dev/v2/{tenancyId}/challenges HTTP/1.1Authorization: Bearer {apiKey}Accept: application/jsonContent-Type: application/json
{ "email": "jdoe@example.com", "name": "Jane Doe", "purpose": "signup", "userId": "user_123", "metadata": { "signupId": "signup_123" }, "invalidateOthers": true, "skipRateLimit": false, "sendEmail": true}HTTP/1.1 201 CreatedContent-Type: application/json
{ "_tag": "ChallengeCreated", "challenge": { "challengeId": "abc123def456ghi", "purpose": "signup", "email": "jdoe@example.com", "userId": "user_123", "createdAt": 1710000000000, "expiresAt": 1710000600000, "metadata": { "signupId": "signup_123" }, "secret": "ABC123def-GHI456jkl-MNO789pqr", "code": "123456", "message": { "html": "<html><body><p>Your Passlock code is <strong>123456</strong>.</p></body></html>", "text": "Your Passlock code is 123456." } }}Create success returns the raw code plus a rendered message object with html and text content. Pass sendEmail: true to have Passlock send the email. To send it yourself, omit sendEmail or pass false, then email the rendered content directly or use code to build your own template.
Create requests require email and purpose. They can also include name, userId, metadata, invalidateOthers, skipRateLimit, and sendEmail. The readable challenge returned by create, get, and verify includes userId when one was supplied and always includes metadata, using null when no metadata was supplied.
Errors
Section titled “Errors”429@error/ChallengeRateLimitedwithRetry-AfterandretryAfterSeconds403@error/Forbidden
Get challenge
Section titled “Get challenge”GET https://api.passlock.dev/v2/{tenancyId}/challenges/{challengeId} HTTP/1.1Authorization: Bearer {apiKey}Accept: application/jsonHTTP/1.1 200 OKContent-Type: application/json
{ "_tag": "Challenge", "challengeId": "abc123def456ghi", "purpose": "signup", "email": "jdoe@example.com", "userId": "user_123", "createdAt": 1710000000000, "expiresAt": 1710000600000, "metadata": { "signupId": "signup_123" }}Errors
Section titled “Errors”404@error/NotFound403@error/Forbidden
Verify challenge
Section titled “Verify challenge”POST https://api.passlock.dev/v2/{tenancyId}/challenges/verify HTTP/1.1Authorization: Bearer {apiKey}Accept: application/jsonContent-Type: application/json
{ "challengeId": "abc123def456ghi", "secret": "ABC123def-GHI456jkl-MNO789pqr", "code": "123456"}HTTP/1.1 200 OKContent-Type: application/json
{ "_tag": "ChallengeVerified", "challenge": { "_tag": "Challenge", "challengeId": "abc123def456ghi", "purpose": "signup", "email": "jdoe@example.com", "userId": "user_123", "createdAt": 1710000000000, "expiresAt": 1710000600000, "metadata": { "signupId": "signup_123" } }}Verification success returns a readable nested challenge. The secret and one-time code are not returned.
Errors
Section titled “Errors”400@error/InvalidChallenge400@error/InvalidChallengeCode400@error/ChallengeExpired400@error/ChallengeAttemptsExceeded403@error/Forbidden
Delete challenge
Section titled “Delete challenge”DELETE https://api.passlock.dev/v2/{tenancyId}/challenges/{challengeId} HTTP/1.1Authorization: Bearer {apiKey}Accept: application/jsonHTTP/1.1 202 AcceptedContent-Type: application/json
{ "_tag": "ChallengeDeleted"}Errors
Section titled “Errors”403@error/Forbidden