Skip to content
Developers

Authevo documentation

Verify your users on WhatsApp in two API calls, or with any authenticator app via TOTP. Raw REST endpoints for both methods — no SDK required (an official Node.js/TypeScript SDK is also available).

Introduction

Authevo is a WhatsApp OTP + TOTP verification API for Egypt and the wider MENA region. Send a one-time code to a phone number over WhatsApp and verify what your user typed back, or enroll a phone for TOTP two-factor and verify codes from any authenticator app — two independent methods, one account.

Every request is a plain HTTPS call against a single base URL. Responses come back as JSON, wrapped in a predictable envelope, so the same two calls work in any language your backend already speaks.

Base URLhttps://api.authevo.dev

The two-call model

POST /v1/otp/send
Send a one-time code to a phone number.
POST /v1/otp/verify
Check the code the user entered.

Codes are delivered over WhatsApp, with Telegram as a fallback if WhatsApp can't be reached. Link each recipient's Telegram once — a one-tap step, ideally right after they sign up — and every fallback after that is automatic; your integration code never changes.

Quickstart

Integrate the two-call flow in a couple of minutes. WhatsApp sending activates once your Meta Business Verification clears; link Telegram once per recipient (see below) and it covers you in the meantime.

Get an API key

Create an account and copy your secret key from the dashboard. Secret keys are prefixed with sk_ and authenticate every request. Your first 50 verifications are free — after that, a $2 minimum balance is required before you can send.

Get your API key

Send and verify a code

Call the send endpoint with a phone number, then the verify endpoint with the code your user received. Pick your stack:

# 1. Send a one-time code over WhatsApp
curl -X POST https://api.authevo.dev/v1/otp/send \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890" }'

# 2. Verify the code your user entered
curl -X POST https://api.authevo.dev/v1/otp/verify \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890", "code": "123456" }'

Authentication

Authevo uses bearer authentication. Pass your secret key in the Authorization header on every request.

Authorization: Bearer sk_

There are no other auth schemes — no OAuth, no sessions, no logins. A valid secret key is all a request needs.

Keep your secret key on the server

Secret keys grant full access to send and verify on your account. Never ship one in client-side or mobile app code, and never commit it to version control. Make Authevo calls from your backend, and rotate a key immediately if it leaks.

API reference

Two endpoints for the core flow — send and verify — plus one optional endpoint to pre-link Telegram. All POST, all JSON, all authenticated.

Browse the full API reference — every endpoint →

Send OTP

POST/v1/otp/send

Generates a one-time code and delivers it to the phone number over WhatsApp. The code expires after the number of seconds returned in expires_in.

ParameterTypeRequiredDescription
phonestringRequiredRecipient phone number in E.164 format, including the country code.
Request
cURL
curl -X POST https://api.authevo.dev/v1/otp/send \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890" }'
Response
200 OK
{
  "data": {
    "message_id": "msg_9k2m4n8x",
    "status": "sent",
    "expires_in": 300
  }
}

A successful call returns the message identifier and a sent status.

Verify OTP

POST/v1/otp/verify

Checks the code your user entered against the one that was sent to their phone. Returns whether the code is valid.

ParameterTypeRequiredDescription
phonestringRequiredThe same phone number the code was sent to, in E.164 format.
codestringRequiredThe 6-digit code the user received over WhatsApp.
Request
cURL
curl -X POST https://api.authevo.dev/v1/otp/verify \
  -H "Authorization: Bearer sk_…" \
  -d '{ "phone": "+201234567890", "code": "123456" }'
Response
200 OK
{ "data": { "verified": true } }

When the code matches and is still valid, verified is true. Otherwise the request fails with an error envelope.

Two-Factor (TOTP)

A second, independent verification method — any authenticator app (Google Authenticator, Authy, 1Password), no message ever sent, just $0.002 per verification. Enroll once, then verify a rotating 6-digit code forever after.

In sandbox mode, enroll returns a fixed, public demo secret — add it to any authenticator app to get a genuinely valid, rotating test code. Unlike OTP's sandbox, TOTP test codes are NOT always 123456 — they rotate every 30 seconds like the real thing.

Enroll

POST/v1/totp/enroll

Issues a shared secret for a phone number and returns a ready-to-display QR code alongside the raw otpauth:// URL and secret — show the QR to your user, or let them type the secret in manually.

ParameterTypeRequiredDescription
phonestringRequiredThe phone number to enroll, in E.164 format.
replacebooleanOptionalPass true to replace an existing confirmed enrollment (e.g. the user lost their device). A confirmed enrollment already in place returns a 409 rather than silently overwriting it.
Request
cURL
curl -X POST https://api.authevo.dev/v1/totp/enroll \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890" }'
Response
200 OK
{
  "data": {
    "secret": "JBSWY3DPEHPK3PXP",
    "otpauth_url": "otpauth://totp/Authevo:+201234567890?secret=JBSWY3DPEHPK3PXP&issuer=Authevo&algorithm=SHA1&digits=6&period=30",
    "qr_code": "data:image/png;base64,iVBORw0KGgo...",
    "already_enrolled": false
  }
}

qr_code is a ready-to-use PNG data URI — set it directly as an image source, no QR library needed on your end. already_enrolled is true only when a previous confirmed secret existed for this phone.

Verify

POST/v1/totp/verify

Checks a 6-digit code from the user's authenticator app against their enrolled secret.

ParameterTypeRequiredDescription
phonestringRequiredThe enrolled phone number, in E.164 format.
codestringRequiredThe 6-digit code currently shown in the user's authenticator app.
Request
cURL
curl -X POST https://api.authevo.dev/v1/totp/verify \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890", "code": "123456" }'
Response
200 OK
{
  "data": {
    "verified": true,
    "first_confirm": true
  }
}

first_confirm is true only on the exact call that confirms a brand-new enrollment — a good moment to show a one-time "you're all set" message.

Disable

POST/v1/totp/disable

Turns off TOTP for a phone number. Safe to call more than once — disabling an already-disabled (or never-enrolled) phone still returns disabled: true.

ParameterTypeRequiredDescription
phonestringRequiredThe phone number to disable, in E.164 format.
Request
cURL
curl -X POST https://api.authevo.dev/v1/totp/disable \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{ "phone": "+201234567890" }'
Response
200 OK
{
  "data": {
    "disabled": true
  }
}

Re-enrolling the same phone afterward does not require replace: true — a disabled enrollment is treated as a fresh start.

Errors

Authevo uses standard HTTP status codes. Successful responses are wrapped in a data object; failures return an error object with a machine-readable code and a human-readable message.

400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "body/phone must match pattern \"^\\+[1-9]\\d{6,14}$\""
  }
}
StatusCodeMeaning
400VALIDATION_ERRORThe request body was malformed, missing a required field, or the phone number isn't a valid E.164 number.
401INVALID_API_KEYThe Authorization header is missing or the secret key is invalid.
402INSUFFICIENT_CREDITSYour account balance is below the amount required to send — add prepaid credit to continue (a $2 minimum balance applies).
429RATE_LIMIT_EXCEEDEDToo many requests. Slow down and retry after a short delay.
503TELEGRAM_UNAVAILABLETelegram fallback isn't available right now.
Always branch on the HTTP status and the error.code, not the message — messages may change.

Rate limits

Requests are rate limited per account. When you exceed the limit, the API responds with 429 RATE_LIMIT_EXCEEDED — back off and retry after a short delay.

Safety Floor

Beyond simple rate limits, the Safety Floor watches for abuse patterns and runaway spend, throttling suspicious traffic before it costs you. It works automatically — there is nothing to configure.