Skip to main content

Verify Email

Verifies a user's email address using the verification token sent via email, and returns authentication tokens.

Endpoint​

POST /api/v1/auth/verify-email

Authentication​

No authentication required (public endpoint).

Request​

Content-Type​

application/json

Request Body​

FieldTypeRequiredDescription
codestringYesVerification token from email link

Example Request​

{
"code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Response​

Success Response (200 OK)​

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}

Response Fields​

FieldTypeDescription
access_tokenstringJWT access token for API requests (expires in 30 minutes)
refresh_tokenstringJWT refresh token for getting new access tokens (expires in 7 days)
token_typestringAlways "bearer"

Token Expiration​

Token TypeExpirationPurpose
Access Token30 minutesMake API requests
Refresh Token7 daysGet new access tokens

When the access token expires, use the refresh endpoint to get a new one.

Examples​

curl -X POST https://api.callcov.com/api/v1/auth/verify-email \
-H "Content-Type: application/json" \
-d '{
"code": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}'

Frontend Integration​

Typical flow in a web application:

// 1. User clicks verification link: https://app.callcov.com/verify-email?token=abc123...
// 2. Frontend extracts token from URL query parameter
const urlParams = new URLSearchParams(window.location.search);
const verificationToken = urlParams.get('token');

// 3. Call verify-email endpoint
const response = await fetch('https://api.callcov.com/api/v1/auth/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code: verificationToken })
});

if (response.ok) {
const { access_token, refresh_token } = await response.json();

// 4. Store tokens
localStorage.setItem('access_token', access_token);
localStorage.setItem('refresh_token', refresh_token);

// 5. Redirect to dashboard
window.location.href = '/dashboard';
} else {
// Show error message
alert('Verification failed. The link may have expired.');
}

Errors​

400 Bad Request​

Invalid verification token:

{
"detail": "Invalid verification token"
}

Verification token has expired:

{
"detail": "Verification token has expired"
}

404 Not Found​

User not found (token was valid but user was deleted):

{
"detail": "User not found"
}

Token Usage​

After verification, use the access token for authenticated API requests:

# Using the access token
curl https://api.callcov.com/api/v1/users/me \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Security Considerations​

  • Single-use tokens: Each verification token can only be used once
  • Time-limited: Tokens expire in 15 minutes (configurable)
  • Secure storage: Store tokens securely (use httpOnly cookies for web apps)
  • HTTPS only: Always use HTTPS in production

Token Storage Best Practices​

Web Applications​

// βœ… GOOD: Use httpOnly cookies (set by backend)
// Access token in httpOnly cookie (protected from XSS)
// Refresh token in httpOnly cookie (protected from XSS)

// ❌ BAD: localStorage (vulnerable to XSS)
localStorage.setItem('access_token', token);

Mobile Applications​

// βœ… GOOD: Use secure storage
// iOS: Keychain
// Android: Keystore or EncryptedSharedPreferences

Verification Token Lifespan​

EventLifespan
Token created15 minutes
Token usedImmediately invalidated
Token expiredAutomatically invalidated

If the token expires, users can request a new one via resend verification.

Complete Registration Flow​

  1. User submits registration form
  2. Backend creates user (unverified)
  3. Backend sends verification email
  4. User clicks link in email
  5. Frontend extracts token from URL
  6. Frontend calls /auth/verify-email with token
  7. Backend verifies token and marks user as verified
  8. Backend returns access and refresh tokens
  9. Frontend stores tokens and redirects to dashboard