POST
/
api
/
v1
/
auth
/
resend-verify-email
Resend verification email
curl --request POST \
  --url https://api.example.com/api/v1/auth/resend-verify-email
import requests

url = "https://api.example.com/api/v1/auth/resend-verify-email"

response = requests.post(url)

print(response.text)
const options = {method: 'POST'};

fetch('https://api.example.com/api/v1/auth/resend-verify-email', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/auth/resend-verify-email",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"net/http"
"io"
)

func main() {

url := "https://api.example.com/api/v1/auth/resend-verify-email"

req, _ := http.NewRequest("POST", url, nil)

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.example.com/api/v1/auth/resend-verify-email")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.example.com/api/v1/auth/resend-verify-email")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body

Overview

Generates a fresh verification OTP and dispatches it via Resend. Used when the original code expired (5-min TTL) or after 5 failed attempts on /verify-email. Anti-spam cooldown. A new code cannot be requested within 60 s of the previous one. Inside that window the call returns 429 RATE_LIMITED with a Retry-After header and a retryAfterSec field in the Problem Details body. Privacy. The endpoint always returns 200 OK when the email is unknown or already verified — the response cannot be used to enumerate accounts or trigger silent emails on guess.

Authentication

None required.

Path parameters

None.

Query parameters

None.

Request body

FieldTypeRequiredAllowed valuesExample
emailstringyesRFC 5322 valid, lowercased server-sidealice@example.com

Example payload

{
  "email": "alice@example.com"
}

Response — 200 OK

FieldTypeNotesExample
okbooleanAlways true. The actual side effect (email sent or not) is intentionally not exposed.true

Example response

{
  "ok": true
}

Error responses

StatusCodeMeaning
400VALIDATION_FAILEDEmail malformed.
429RATE_LIMITEDInside the 60 s cooldown window. Wait retryAfterSec seconds (also in Retry-After header).

Example error — 429

{
  "type": "https://api.swappr.co.uk/errors/rate-limited",
  "title": "Too many requests",
  "status": 429,
  "code": "RATE_LIMITED",
  "detail": "Please wait 47s before requesting another code",
  "instance": "/api/v1/auth/resend-verify-email",
  "requestId": "01HZQ7K3M4N5P6Q7R8S9T0V1W2",
  "retryAfterSec": 47
}
The Retry-After: 47 HTTP header is also set. Clients should prefer the header for parsing; the body field exists for JSON-only consumers.

Side effects

  • Inserts a new otp_codes row (purpose: 'email_verify', 5-min TTL). Any prior outstanding code for this email is invalidated.
  • Sends an email via Resend with the 6-digit code.
  • Both side effects are skipped when the email is unknown or already verified.

See also

curl

curl -X POST https://api.swappr.co.uk/api/v1/auth/resend-verify-email \
  -H "Content-Type: application/json" \
  -d '{ "email": "alice@example.com" }'