Docs / Use cases / Email verification
Use case

Email verification API

Confirm a new user owns their email address with a verification link or code, using one Mailbot API call.

Answer first: to verify an email, POST https://api.mailbot.id/v1/send with your Bearer key and a JSON body whose html/text contains a single-use verification link (or code) that points back to your app. Your backend generates and stores the token with an expiry; Mailbot delivers the message.

Use case

A verification email confirms that the address a user signed up with actually belongs to them. Your backend generates a signed, single-use token, stores it with an expiry, and embeds it in a link like https://yourapp.com/verify?token=.... When the user clicks, your backend marks the account verified. Mailbot handles the send request and returns a message id.

Your backend owns the verification logic: generate the token, store it with an expiry, validate it on click, and invalidate it after use. Mailbot delivers the message containing that link or code.

When to send

  • A new account is created at signup and needs to confirm its email address.
  • A user changes the email address on their account.
  • Periodic re-verification of stale or unconfirmed accounts.
Keep tokens single-use and short-lived. Make verification tokens single-use and short-lived, and treat the link as opaque — don't leak PII in query params. Invalidate the token once the account is verified.

API call

cURL
curl https://api.mailbot.id/v1/send \
  -H "Authorization: Bearer $MAILBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "noreply@yourdomain.com",
    "to": "user@example.com",
    "subject": "Confirm your email address",
    "text": "Confirm your email address: https://yourapp.com/verify?token=eyJhbGciOiJIUzI1NiJ9... This link expires in 24 hours.",
    "idempotency_key": "verify-user-142"
  }'
Python (requests)
import os, requests

token = generate_verification_token()          # your signed, single-use token
store_token(user.id, token, expires_in=86400)  # store with a 24-hour expiry
link = f"https://yourapp.com/verify?token={token}"

res = requests.post(
    "https://api.mailbot.id/v1/send",
    headers={
        "Authorization": f"Bearer {os.environ['MAILBOT_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "from": "noreply@yourdomain.com",
        "to": user.email,
        "subject": "Confirm your email address",
        "text": f"Confirm your email address: {link} This link expires in 24 hours.",
        "idempotency_key": f"verify-user-{user.id}",
    },
)
res.raise_for_status()

Required fields

FieldRequiredNotes
toYesThe user's email address being verified.
subjectYesState the purpose clearly, for example "Confirm your email address".
text or htmlYesThe body must contain the verification link or code.
fromNoVerified sender; defaults to the configured sender if omitted.
idempotency_keyRecommendedTie to the verification request so retries don't double-send.

Example payload

JSON request
{
  "from": "noreply@yourdomain.com",
  "to": "user@example.com",
  "subject": "Confirm your email address",
  "text": "Confirm your email address: https://yourapp.com/verify?token=eyJhbGciOiJIUzI1NiJ9... This link expires in 24 hours. If you didn't create this account, ignore this email.",
  "html": "<p>Confirm your email address by clicking the link below.</p><p><a href=\"https://yourapp.com/verify?token=eyJhbGciOiJIUzI1NiJ9...\">Confirm email address</a></p><p>This link expires in 24 hours.</p>",
  "idempotency_key": "verify-user-142"
}

Example response

202 · queued
{
  "ok": true,
  "id": "msg_3f8c1a...",
  "status": "queued"
}

For delivered messages, the response can include status: "sent" and a delivery_id. See the API reference for every response shape.

Errors

StatusMeaningWhat to do
400Invalid payload (bad to, missing subject/body).Fix the request; read details.
401Bad or missing API key.Check the Bearer header.
429Send limit reached.Back off; surface a "try again later" message to the user.
502 / 503Mailbot is temporarily unable to accept the send.Retry with backoff using the same idempotency_key.

Full error handling guidance is in the integration guide.

Testing

For safe setup, use the standard test endpoint to confirm delivery reaches an address you control:

cURL · test email
curl https://api.mailbot.id/v1/test-email \
  -H "Authorization: Bearer $MAILBOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "safe@yourdomain.com", "label": "Verify test" }'

Production checklist

  • Verification tokens are single-use, expire, and are invalidated after use.
  • No sensitive data embedded in the link beyond an opaque token.
  • Verified sender domain; from set to a verified address.
  • API key kept server-side; never sent to the browser or mobile client.
  • 429/5xx handled with backoff and a clear user message.
  • idempotency_key set so retries don't double-send.