API Reference
Complete reference for all Novauth verification endpoints. Every channel shares the same authentication model and base URL — only the path and payload differ.
https://api.novauth.com/api/v1/connect-hubAuthentication
Every request must include two headers. You can find your credentials in the Developer → API Keys section of the dashboard. Credentials are cached server-side for 5 minutes, so newly created keys are active within seconds.
x-api-keyYour API key. Treat like a password — never expose in client-side code.x-account-idYour account identifier. Shown on the dashboard beside each API key.x-request-idOptional correlation ID. Pass any UUID; returned in error responses for tracing.Store credentials in environment variables (BETATEL_API_KEY, BETATEL_ACCOUNT_ID). Never hardcode them in source files.
Keys prefixed with sk_test_ are sandbox keys — they never touch real carriers and incur no charges. Use them during development, then swap to your BTEL_ key when you go live. Sandbox Mode →
When creating an API key you can optionally attach one or more IP addresses or CIDR ranges. If an IP whitelist is configured, any request arriving from an IP not in the list is rejected with 401 Unauthorized, even if the API key itself is valid. This lets you lock a key to your server's IP so it cannot be used if leaked.
curl -X POST https://api.novauth.com/api/v1/connect-hub/call/flash \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{"callee": "+14155552671"}'Verify Call
Initiates a short-duration ring-and-hangup call. The caller ID encodes the OTP — your mobile SDK reads the incoming number without the user having to answer.
calleestringrequiredcallerstringmax_ring_timenumberuuidstring (ULID)callerstringcalleestringcurl -X POST https://api.novauth.com/api/v1/connect-hub/call/flash \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"callee": "+14155552671",
"caller": "+38761000001",
"max_ring_time": 5
}'
# Response:
# {
# "uuid": "01KAK9KATW01A437PSXS5EVDCR",
# "caller": "+38761000001",
# "callee": "+14155552671"
# }hangup_causestringdurationnumberbillsecnumberpddnumberdestination_countrystringstart_stampstring (ISO 8601)curl https://api.novauth.com/api/v1/connect-hub/call/flash/01KAK9KATW01A437PSXS5EVDCR/cdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID"
# Response:
# {
# "uuid": "01KAK9KATW01A437PSXS5EVDCR",
# "caller": "+38761000001",
# "callee": "+14155552671",
# "hangup_cause": "NORMAL_CLEARING",
# "duration": 6,
# "billsec": 0,
# "pdd": 2,
# "start_stamp": "2024-06-01T10:30:00.000Z",
# "destination_country": "United States",
# "destination_country_code": "US"
# }Returns a paginated list of all calls for your account. Use filter to narrow results by any CDR field (e.g. callee, hangup_cause).
pagenumberrows_per_pagenumbersort_bystringsort_direction"ASC" | "DESC"filterobjecttotalnumbertotal_pagesnumberhas_next_pagebooleanhas_previous_pagebooleanlistCDR[]curl -X POST https://api.novauth.com/api/v1/connect-hub/call/flash/cdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"rows_per_page": 20,
"sort_by": "start_stamp",
"sort_direction": "DESC"
}'Terminates an active call before it naturally ends. Returns 204 No Content on success.
# Terminate an active call before it naturally ends
curl -X DELETE https://api.novauth.com/api/v1/connect-hub/call/flash/01KAK9KATW01A437PSXS5EVDCR \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID"
# Returns 204 No Content on successSMS
Delivers a text message via SMPP. Typically used to send a numeric OTP code that the user types into your app.
tostringrequiredtextstringrequiredfromstringmessageIdstring (UUID)fromstringtostringcurl -X POST https://api.novauth.com/api/v1/connect-hub/sms \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155552671",
"text": "Your verification code is 482910. Valid for 5 minutes.",
"from": "Novauth"
}'
# Response:
# {
# "messageId": "0a62face-6d15-11f0-962f-d89d6729654c",
# "from": "Novauth",
# "to": "14155552671"
# }Retrieves the delivery status for a sent message. Status is updated asynchronously as carrier delivery reports (DLRs) arrive.
deliveredConfirmed delivery to handset.sentDispatched to carrier; awaiting DLR.failedDelivery failed (invalid number, blocked).undeliveredCarrier accepted but delivery not confirmed.curl https://api.novauth.com/api/v1/connect-hub/sms/0a62face-6d15-11f0-962f-d89d6729654c/sdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID"
# Response:
# {
# "uuid": "...",
# "messageId": "0a62face-6d15-11f0-962f-d89d6729654c",
# "from": "Novauth",
# "to": "+14155552671",
# "status": "delivered",
# "timestamp": "2024-06-01T10:30:00.000Z"
# }Returns a paginated list of all sent messages. Accepts the same pagination body as other list endpoints (page, rows_per_page, sort_by, filter).
curl -X POST https://api.novauth.com/api/v1/connect-hub/sms/sdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"rows_per_page": 20,
"sort_direction": "DESC"
}'Telegram OTP
Sends a numeric OTP via Telegram's official Gateway API. Supports delivery-ability checks, server-side code validation, and revocation with automatic refund.
tostringrequiredcodestringrequiredttlnumbersender_usernamestringcallback_urlstringuuidstring (ULID)request_idstringstatusstringrequest_costnumberremaining_balancenumbercurl -X POST https://api.novauth.com/api/v1/connect-hub/telegram \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155552671",
"code": "482910",
"ttl": 300
}'
# Response:
# {
# "uuid": "01KNV9CWW9ZEYVDFBJ1N7M1DVR",
# "request_id": "tg_req_abc123",
# "to": "14155552671",
# "status": "sent",
# "request_cost": 0.05,
# "remaining_balance": 49.95
# }Probes whether the number has a Telegram account before sending. If is_refunded is true, the user has no Telegram account — the probe cost is refunded and you should fall back to SMS or Verify Call.
curl -X POST https://api.novauth.com/api/v1/connect-hub/telegram/check-send-ability \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{"to": "+14155552671"}'
# Response:
# {
# "request_id": "tg_req_abc123",
# "phone_number": "14155552671",
# "request_cost": 0.01,
# "is_refunded": false,
# "remaining_balance": 49.99,
# "delivery_status": { "status": "sent", "updated_at": 1713350400 }
# }Queries the code-entry outcome for a given request_id. Optionally pass the user-entered code for server-side validation.
code_validUser entered the correct code.code_invalidUser entered a wrong code.code_max_attempts_exceededToo many failed attempts.expiredCode TTL elapsed before entry.curl -X POST https://api.novauth.com/api/v1/connect-hub/telegram/check-verification-status \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"request_id": "tg_req_abc123",
"code": "482910"
}'
# Response:
# {
# "request_id": "tg_req_abc123",
# "verification_status": {
# "status": "code_valid",
# "updated_at": 1713350400
# }
# }Cancels an active OTP request before the user completes it. If the message has not yet been read, is_refunded will be true and the charge is returned to your balance.
curl -X POST https://api.novauth.com/api/v1/connect-hub/telegram/revoke-verification \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{"request_id": "tg_req_abc123"}'
# Response:
# {
# "request_id": "tg_req_abc123",
# "is_refunded": true,
# "remaining_balance": 50.0
# }Fetches the full Telegram Delivery Record for a given uuid (the Novauth correlation ID returned by the send endpoint). Includes delivery status, verification status, cost, and country.
curl https://api.novauth.com/api/v1/connect-hub/telegram/01KNV9CWW9ZEYVDFBJ1N7M1DVR/tdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID"
# Response includes full TDR:
# {
# "uuid": "01KNV9CWW9ZEYVDFBJ1N7M1DVR",
# "to": "+14155552671",
# "status": "DELIVERED",
# "delivery_status": "delivered",
# "verification_status": "code_valid",
# "request_cost": 0.05,
# "country": "United States",
# "created_at": "2024-06-01T10:30:00.000Z"
# }Returns a paginated list of all Telegram delivery records. Filter by <code>verification_status</code>, <code>delivery_status</code>, or any other TDR field.
curl -X POST https://api.novauth.com/api/v1/connect-hub/telegram/tdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"rows_per_page": 20,
"sort_direction": "DESC"
}'Sends an OTP message via WhatsApp Business API. The user reads the code inside the WhatsApp conversation and types it into your app.
tostringrequiredtextstringrequireduuidstring (ULID)tostringcurl -X POST https://api.novauth.com/api/v1/connect-hub/whatsapp/otp \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"to": "+14155552671",
"text": "Your verification code is 482910. Valid for 5 minutes."
}'
# Response:
# {
# "uuid": "01KAK9KATW01A437PSXS5EVDCR",
# "to": "+14155552671"
# }After sending, report the user's verification outcome back via POST /whatsapp/webhook. See the Webhooks reference for details.
Fetches the WhatsApp Delivery Record for a given uuid returned by the send endpoint.
curl https://api.novauth.com/api/v1/connect-hub/whatsapp/01KAK9KATW01A437PSXS5EVDCR/wdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID"
# Response:
# {
# "uuid": "01KAK9KATW01A437PSXS5EVDCR",
# "to": "+14155552671",
# "status": "DELIVERED",
# "created_at": "2024-06-01T10:30:00.000Z"
# }Returns a paginated list of all WhatsApp delivery records. Supports the same <code>page</code>, <code>rows_per_page</code>, <code>filter</code> body as all other list endpoints.
curl -X POST https://api.novauth.com/api/v1/connect-hub/whatsapp/wdr \
-H "x-api-key: YOUR_API_KEY" \
-H "x-account-id: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"page": 1,
"rows_per_page": 20,
"sort_direction": "DESC"
}'Error Codes
All error responses follow the same JSON envelope. The error field contains a machine-readable string; pass your x-request-id to support when reporting issues.
| Status | Code | Description |
|---|---|---|
| 400 | BAD_REQUEST | Invalid request body — missing required field, wrong format, or invalid phone number. |
| 401 | UNAUTHORIZED | Missing or invalid x-api-key / x-account-id headers. |
| 402 | PAYMENT_REQUIRED | Insufficient account balance. Top up your account to continue. |
| 403 | FORBIDDEN | API key exists but lacks permission for this operation. |
| 404 | NOT_FOUND | The requested UUID or resource does not exist. |
| 409 | CONFLICT | Duplicate request or conflicting state (e.g. revoking an already-expired request). |
| 480 | TEMPORARY_UNAVAILABLE | Gateway temporarily unreachable. Retry with exponential back-off. |
| 486 | BUSY_HERE | (Verify Call) Recipient is busy or the call was rejected by the network. |
| 500 | INTERNAL_SERVER_ERROR | Unexpected server error. Contact support with your x-request-id. |
| 503 | SERVICE_UNAVAILABLE | Gateway disconnected or service under maintenance. Check the status page. |
| 603 | DECLINE | (Verify Call) Recipient explicitly declined the call. |
For a full list of error codes including suggested remediation steps, see the Error Handling guide.