Authentication
Verify Email
Verify a new account's email address using the UUID token from the verification email link.
POST /api/v1/auth/verify-email — 🌐 Public · Rate limit: 20 req / hour
Verifies the user's email using the UUID token sent during registration. On success the User.emailVerified flag flips to true. Idempotent — re-verifying an already-verified token returns the same success response.
Request
Body — VerifyEmailDto
| Field | Type | Required | Validation | Notes |
|---|---|---|---|---|
token | string (UUID v4) | ✓ | @IsUUID() | Token sent via EmailVerification.token from the registration flow |
Response
200 OK — SuccessOnlyResponseDto
{ "success": true }Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
400 | auth.verify_email.invalid_token | Token not found, expired, or already consumed |
400 | (DTO validation) | Token is not a valid UUID |
429 | (throttle) | Rate limit exceeded (20 req/hour) |
Side effects
- Look up
EmailVerificationbytoken(Prisma). - If valid + unexpired: set
User.emailVerified = true,EmailVerification.usedAt = now()in atomic transaction. - Audit log entry (
auth.verify_email.success).
Code samples
curl -X POST https://api.bio.re/api/v1/auth/verify-email \
-H 'Content-Type: application/json' \
-d '{"token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}'async function verifyEmail(token: string): Promise<void> {
const res = await fetch('https://api.bio.re/api/v1/auth/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token }),
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Verification failed'), {
code: json?.error?.code,
});
}
}import { useMutation } from '@tanstack/react-query';
export function useVerifyEmail() {
return useMutation({
mutationFn: async (token: string) => {
const res = await fetch('/api/v1/auth/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token }),
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Verification failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
},
});
}Try it
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
curl -X POST "https://loading/api/v1/auth/verify-email" \ -H "Content-Type: application/json" \ -d '{ "token": "b5507016-7da2-4777-a161-1e8042a6a377" }'{
"success": true
}{
"success": false,
"error": {
"code": "AUTH_UNAUTHORIZED",
"message": "Invalid credentials",
"i18nKey": "auth.login.invalid_credentials",
"i18nVars": {
"field": "email"
},
"details": [
{
"message": "email must be an email"
}
],
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/auth/auth.controller.ts | 98–106 |
| DTO (request) | apps/api-core/src/modules/auth/dto/index.ts | 92–96 (VerifyEmailDto) |
| Service | apps/api-core/src/modules/auth/auth.service.ts | verifyEmail() |
| Prisma model | packages/prisma/prisma/schema.prisma | EmailVerification, User.emailVerified |