Skip to main content
The OneXtel Verify API issues one-time PINs and verifies them. You send a PIN against a template, which decides the PIN’s shape (length, character set, lifetime, attempt allowance) and which channels it can go out on. OneXtel generates the code, dispatches it, and holds only a hash of it — so verification is a comparison you make through the API, never a code you store yourself. A single send can fan out to SMS, WhatsApp, and email in parallel, and the response tells you what each channel did.

Base URL

Authentication

Every request carries an API key as a bearer token. Create one in the OneXtel portal under Developers → API Keys.
string
required
Bearer YOUR_API_KEY

The three calls

1

Send

POST /v1/pins generates a PIN, dispatches it to every requested channel, and returns a pinId plus per-channel dispatch status. Hold on to the pinId — it is what you verify against.
2

Resend (optional)

POST /v1/pins/{pinId}/resend issues a new PIN on the same pinId, optionally on a different channel. Because the original is only stored hashed, there is no earlier code to re-send — every resend regenerates the PIN, its expiry, and its attempt allowance.
3

Verify

POST /v1/pins/{pinId}/verify compares what the user typed against the stored hash in constant time.

Partial dispatch

A send that requests several channels can succeed on some and fail on others. The API treats that as success: So a 201 is not a promise that every channel went out. Read channels[] to see which did:

Idempotency

Sends and resends accept an Idempotency-Key header, which protects against duplicate dispatch when you retry a request whose response you never saw.
  • Replaying the same key with the same body within 24 hours returns the original response verbatim — no second message goes out.
  • The same key with a different body is rejected with idempotency_key_reuse.
  • A concurrent request on a key still in flight is rejected with idempotency_in_progress.
Generate the key per logical send attempt — typically once per user action — not per HTTP retry, or the retries will each look like a new send.

Rate limits

Limits are configured per template, not globally, and each has its own error code: Read the current values off the template — resendCooldown, verifyPinLimit, sendPinPerTemplateLimit, sendPinPerPhoneNumberLimit — via List templates.

What’s in this section