# WhatsApp OTP API

> aut2fa is an API that sends one-time verification codes (OTP, 2FA) over WhatsApp. Your backend sends a phone number to `POST /v1/send`; aut2fa generates a 6-digit code, delivers it from one of its WhatsApp numbers and reports when it was sent, delivered and read. You pay the WhatsApp price per code only when the code is delivered.

Source: https://aut2fa.com/whatsapp-otp · Updated on 2026-10-11

## Key facts

- **Endpoint:** `POST https://api.aut2fa.com/v1/send` with the header `Authorization: Bearer ak_live_…`.
- **Code:** 6 digits, generated by aut2fa. To use your own, send it in the `code` field.
- **Expiry:** The code expires 10 minutes after the send is created.
- **Verification:** `POST /v1/send/{id}/verify` with the code the user typed. After 5 wrong attempts the send is locked.
- **Delivery status:** `queued`, `sending`, `sent`, `delivered`, `read` or `failed`, each with a timestamp, at `GET /v1/send/{id}/status`.
- **Message language:** English or Brazilian Portuguese, set with `locale`: `en` or `pt-BR`.
- **Price:** The WhatsApp price per code, charged only when the code is delivered. See the pricing page for the current price.
- **Test mode:** Keys that start with `ak_test_` are free, and the code aut2fa generates for a test send is always `000000`.
- **Retries:** Repeat a request with the same `Idempotency-Key` header and you get the original send, not a second code.
- **Abuse limits:** Every account has a ceiling of sends per minute, and each application can add caps per minute and per phone number per hour. A request over a cap gets HTTP 429 with `Retry-After`, before anything is sent.
- **Code storage:** The code is kept encrypted until the message is sent; after that only a hash remains.

## How a WhatsApp code is delivered

1. Your backend calls `POST /v1/send` with the user's phone number in international format, such as `+5531999999999`. aut2fa answers `202` with the send `id`.
2. aut2fa picks one of its WhatsApp numbers and sends the message with the code. If that number fails, it tries another, up to 3 attempts.
3. Every status change is stored with its time. Read it at `GET /v1/send/{id}/status` or on the statement in the dashboard.
4. When the user types the code, your backend calls `POST /v1/send/{id}/verify`. The response says whether the code is `valid` and how many `attempts_left` remain.

## Send and verify with cURL

Two requests: one sends the code, the other checks what the user typed.

```bash
curl https://api.aut2fa.com/v1/send \
  -H "Authorization: Bearer ak_live_…" \
  -H "Content-Type: application/json" \
  -d '{"to": "+5531999999999"}'

# The user typed 482913
curl https://api.aut2fa.com/v1/send/snd_8Kq2wR7tXz/verify \
  -H "Authorization: Bearer ak_live_…" \
  -H "Content-Type: application/json" \
  -d '{"code": "482913"}'
```

## Send response

`POST /v1/send` answers `202 Accepted`. `channel` and `from` stay `null` until aut2fa routes the send.

```json
{
  "id": "snd_8Kq2wR7tXz",
  "status": "queued",
  "verification": "pending",
  "mode": "live",
  "channel": null,
  "from": null,
  "expires_at": "2026-10-11T18:10:00Z",
  "created_at": "2026-10-11T18:00:00Z",
  "sent_at": null,
  "delivered_at": null,
  "read_at": null,
  "verified_at": null,
  "failed_at": null,
  "failure_reason": null
}
```

## What aut2fa doesn't do

- Let you pick the channel or the sending number. aut2fa chooses both, and the send status shows which it used.
- Bill after the fact. The balance is prepaid; there is no subscription or post-paid invoice.
- Charge in other currencies. Balance and prices are in Brazilian reais (BRL).

## WhatsApp OTP questions

### What if the phone number has no WhatsApp?

aut2fa can't deliver the code, so the send ends as `failed` and costs nothing.

### How long is the code valid?

10 minutes from the moment you create the send. After that, `/verify` answers with `verification` set to `expired`.

### What happens after 5 wrong codes?

The send is locked: `verification` becomes `locked` and no further code is accepted. Create a new send to try again.

### Can I send my own code?

Yes. Put it in the `code` field of `POST /v1/send`; otherwise aut2fa generates a 6-digit code.

### Can I test for free?

Yes. Keys that start with `ak_test_` are free and the code aut2fa generates for a test send is always `000000`, so automated tests run the whole flow without touching your balance.

- [Start free](https://app.aut2fa.com/signup)
- [Read the docs](https://doc.aut2fa.com)
- [See pricing](https://aut2fa.com/pricing)
