Request Password Reset
Sends a password reset link to the user's email address. Use this when users forget their password.
Endpointβ
POST /api/v1/auth/password-reset
Authenticationβ
No authentication required (public endpoint).
Requestβ
Content-Typeβ
application/json
Request Bodyβ
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address to send reset link to |
Example Requestβ
{
"email": "john@example.com"
}
Responseβ
Success Response (200 OK)β
{
"message": "If the email exists, a password reset link has been sent",
"success": true
}
Security Note
The endpoint always returns success, even if the email doesn't exist. This prevents attackers from discovering which emails are registered.
Examplesβ
curl -X POST https://api.callcov.com/api/v1/auth/password-reset \-H "Content-Type: application/json" \-d '{ "email": "john@example.com"}'Password Reset Flowβ
- User requests reset β This endpoint
- Backend sends email β Email with reset link and token
- User clicks link β Redirected to frontend with token
- User enters new password β Frontend calls /auth/password-reset/confirm
- Password updated β User can log in with new password
Email Contentβ
Users receive an email containing:
- Password reset link with token
- Link expires in 15 minutes
- Token is single-use
Example email:
Subject: Reset your CallCov password
Click the link below to reset your password:
https://app.callcov.com/reset-password-confirmation?token=abc123...
This link expires in 15 minutes.
If you didn't request this, you can safely ignore this email.
Frontend Integrationβ
Typical "Forgot Password" form:
async function handleForgotPassword(email) {
try {
const response = await fetch('https://api.callcov.com/api/v1/auth/password-reset', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
});
if (response.ok) {
// Show success message
alert('If your email is registered, you will receive a password reset link.');
}
} catch (error) {
console.error('Error:', error);
alert('Something went wrong. Please try again.');
}
}
Rate Limitingβ
To prevent abuse:
- Maximum 3 requests per email per hour
- Maximum 10 requests per IP per hour
Security Behaviorβ
When this endpoint is called:
- Invalidates all previous reset tokens for this user
- Generates new reset token (expires in 15 minutes)
- Sends reset email
- Always returns success (even if email doesn't exist)
Security Considerationsβ
- Email enumeration protection: Always returns success
- Token invalidation: Previous reset tokens are invalidated
- Time-limited: Tokens expire in 15 minutes
- Single-use: Tokens can only be used once
- Rate limited: Prevents email bombing
Testing in Developmentβ
In development mode, reset emails are sent to MailHog (http://localhost:8025).
Common Issuesβ
Email Not Receivedβ
Possible reasons:
- Email in spam folder
- Incorrect email address
- Email service temporary issue
Solution: Wait a few minutes, check spam, or try resending.
Rate Limit Exceededβ
{
"detail": "Too many password reset requests. Please try again later."
}
Solution: Wait an hour before trying again.
Complete Reset Form Exampleβ
function ForgotPasswordForm() {
const [email, setEmail] = useState('');
const [sent, setSent] = useState(false);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
await fetch('https://api.callcov.com/api/v1/auth/password-reset', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email })
});
setSent(true);
} catch (error) {
alert('Something went wrong. Please try again.');
} finally {
setLoading(false);
}
};
if (sent) {
return (
<div className="success-message">
<h2>Check your email</h2>
<p>
If your email is registered, you will receive a password reset link
shortly.
</p>
<p>
Didn't receive it? Check your spam folder or try again in a few
minutes.
</p>
</div>
);
}
return (
<form onSubmit={handleSubmit}>
<h2>Forgot Password?</h2>
<p>Enter your email and we'll send you a reset link.</p>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="your@email.com"
required
/>
<button type="submit" disabled={loading}>
{loading ? 'Sending...' : 'Send Reset Link'}
</button>
<a href="/login">Back to Login</a>
</form>
);
}
Relatedβ
- Confirm Password Reset - Complete the reset with new password
- Login - Log in after password reset
- Register - Create new account