Docs Wholesale & Carriers Gateway Platform API (SMS & Voice)

Gateway Platform API (SMS & Voice)

Send SMS and place calls (incl. flash-call OTP) through your registered Gateway devices via a simple REST API, with optional webhook delivery instead of polling.


Gateway Platform API (SMS & Voice)

Send SMS and place calls (including flash-call OTP verification) programmatically through your own registered SMS/Voice Gateway devices — your phone(s) running the 6X Gateway app do the actual sending, and the API just queues the request. This is separate from the SMPP-bind and Business API systems documented elsewhere: it always requires at least one active gateway device on your account, and it's billed at the same retail rates as sending manually from the Gateway Devices page in your wholesale portal.

Authentication

Every request needs your account's API key, sent as either:

X-API-Key: YOUR_API_KEY

...or as a query parameter:

?api_key=YOUR_API_KEY

Get (or regenerate) your API key from Profile in your wholesale portal. Regenerating immediately invalidates the old key — update your integration before doing so.

Note: this is a different key from the api_key shown on an individual Gateway Device's card — the device key identifies one physical phone; this account-level key identifies you as the caller and is what these endpoints check.

Rate limit

All four endpoints below are limited to 60 requests/minute per IP. Exceeding it returns HTTP 429 — back off and retry after a few seconds.

POST /api/v1/wholesale/sms/send

Queues an SMS on your first active SMS Gateway device.

FieldTypeRequiredDescription
fromstringYesSender ID (subject to your account's sender-ID rules for the destination country)
tostringYesRecipient phone, international format e.g. +447911123456
messagestringYesSMS text

Example request

curl -X POST https://app.6xcom.com/api/v1/wholesale/sms/send \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"from":"6XBiz","to":"+447911123456","message":"Your order has shipped."}'

Response

{
  "success": true,
  "message_id": "abc123",
  "parts": 1,
  "amount": 0.035,
  "balance": 4.965
}

POST /api/v1/voice/call/send

Queues a normal (billed per-minute) call on your first active Voice Gateway device.

FieldTypeRequiredDescription
tostringYesDestination phone, international format
typestringNonormal (default) or flash
webhook_urlstringNoSee Webhook delivery below

Example request

curl -X POST https://app.6xcom.com/api/v1/voice/call/send \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"+447911123456"}'

Response

{
  "success": true,
  "callId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "status": "queued",
  "type": "normal"
}

POST /api/v1/voice/otp/send

Same request/response shape as voice/call/send, but always places a flash call (a ~4-second ring never meant to be answered — the caller ID itself is the OTP) regardless of any type field submitted. Purpose-built for OTP/2FA integrations. Billed a flat per-attempt fee from the superadmin-configured Flash-Verification Rates table (not a per-minute rate) — destinations with no flash rate configured are rejected with a 402.

curl -X POST https://app.6xcom.com/api/v1/voice/otp/send \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"to":"+447911123456","webhook_url":"https://yourapp.example.com/6x-webhook"}'

GET /api/v1/voice/otp/status/{callId}

Polls the current status of a call queued via either voice endpoint above. Use the callId returned at send time.

curl https://app.6xcom.com/api/v1/voice/otp/status/d290f1ee-6c54-4b01-90e6-d701748f0851 \
  -H "X-API-Key: YOUR_API_KEY"
{
  "success": true,
  "callId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
  "type": "flash",
  "status": "ended",
  "durationSeconds": 4,
  "cost": 0.05,
  "error": null
}
statusMeaning
pendingQueued, waiting for your gateway device to pick it up
initiatedDevice has placed the call, not yet finished
endedCall finished normally — terminal, cost is final
failedCall failed (device offline, no signal, etc.) — terminal, nothing charged

Webhook delivery (alternative to polling)

Instead of polling otp/status, pass a webhook_url when sending a call (either voice endpoint). Once the call reaches a terminal state (ended or failed), 6X POSTs the same JSON shape shown above to your URL — a short timeout applies and delivery is retried once on failure, then given up (poll as a fallback if you need a stronger guarantee).

Every webhook request carries two headers so you can verify it actually came from 6X:

HeaderDescription
X-6X-TimestampUnix timestamp the request was sent
X-6X-Signaturesha256=<hex> — HMAC-SHA256 of "{timestamp}.{raw JSON body}", keyed with your account API key

Verifying the signature (PHP)

$timestamp = $_SERVER['HTTP_X_6X_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_6X_SIGNATURE'];
$body      = file_get_contents('php://input');
$expected  = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $yourApiKey);
if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

Error codes (all endpoints)

StatusMeaning
401Missing or invalid API key
402Insufficient wallet balance for this destination, or (OTP) no flash-verification rate configured
404Unknown callId, or it belongs to a different account
422No active gateway device of the right type on your account, or a validation error
429Rate limit exceeded (60 requests/minute)
Was this article helpful?