REST API v1

DogeSMS Developer API

Automate OTP number allocation, SMS retrieval, and order management via the REST API at api.dogesms.com. Authenticate with an API Key. POST /v1/orders accepts an X-Idempotency-Key header to prevent duplicate charges on retries.

Quickstart workflow

A typical integration goes from credentials to SMS delivery in four steps.

1

Create an API Key

Generate an API Key in the dashboard under Settings → API Keys. Copy the key immediately — it is shown only once.

Use one key per environment (development, staging, production) so key rotation and audit logs stay clean.

2

Check your balance

Call GET /v1/balance before ordering to confirm the account has sufficient funds.

Balance is returned in cents (integer). Divide by 100 to display USD. Top up via the dashboard if balance is low.

3

Create an order

POST /v1/orders with service_code and country_code. Include an X-Idempotency-Key UUID to prevent duplicate orders on retries.

Store the returned order id immediately. Webhook event correlation and cancellation both depend on it.

4

Receive number & SMS

Register and verify a webhook to receive order.number_allocated (phone_number ready) and order.completed (sms_code ready) in real time. Order status queries are disabled by default; do not build a polling integration.

Treat expired, cancelled, and failed as terminal states. Cancel with POST /v1/orders/{id}/cancel if the SMS does not arrive within the expected window.

Authentication

Pass your API Key in the Authorization header: Authorization: Bearer sk_live_…

Keys start with sk_live_ — never share or commit them to source control.

Rotate keys any time from the dashboard; old keys are invalidated immediately.

Rate Limiting & Idempotency

Include X-Idempotency-Key: <uuid> on POST /v1/orders (CreateOrder) to make retries safe. The cancel endpoint does not use this header.

A key is permanently bound to the original creation attempt — reusing it after the order ends silently returns the original response, not a new order. Always generate a fresh UUID for each new order.

On HTTP 429, back off exponentially before retrying.

Integration model

Treat the API as an order workflow rather than a single request-response call.

Safe writes with Idempotency-Key

Generate a fresh UUID for each POST /v1/orders call and store it with the order. Retrying the same key returns the original result without charging again.

Track the order lifecycle

Orders move through pending → active (phone_number ready) → completed (sms_code ready), or reach expired / cancelled / failed. Subscribe to webhook events to track the lifecycle.

Handle transient failures

HTTP 429 and 422 SERVICE_NOT_AVAILABLE (no inventory) are expected operational conditions. Back off and retry rather than surfacing raw error codes to end users.

Webhooks (recommended)

Receive order events via HTTP POST the moment they happen — no polling required. Register one endpoint and we push the full lifecycle (number allocation, SMS delivery, and terminal failure/expiry) to you in real time.

Register your endpoint

Configure your webhook URL in the dashboard under Settings → Webhooks (your API Key and webhook endpoint share the same account). The signing secret is shown once at creation — store it safely.

Events

order.number_allocatedorder.number_allocated — fires when the number is allocated (status becomes active). The payload includes phone_number so you can enter it on the target platform. sms_code is not available yet.

order.completedorder.completed — fires when the SMS arrives (status becomes completed). The payload includes sms_code and sms_content.

order.failedorder.failed — fires when the order fails (no number available or allocation error). The payload includes a sanitized error_code; no charge is retained.

order.expiredorder.expired — fires when the number was allocated but no SMS arrived within the window (status becomes expired). The charge is automatically refunded.

Example payloads

POST <your webhook url>
X-Webhook-Signature: sha256=<hex>
Content-Type: application/json

{
  "event_type": "order.number_allocated",
  "order_id": "01960a9b-…",
  "service_code": "whatsapp",
  "country_code": "US",
  "phone_number": "+12015550123",
  "status": "active",
  "allocated_at": "2024-11-01T09:00:05Z"
}
{
  "event_type": "order.completed",
  "order_id": "01960a9b-…",
  "service_code": "whatsapp",
  "country_code": "US",
  "phone_number": "+12015550123",
  "sms_code": "123456",
  "sms_content": "Your code is 123456",
  "completed_at": "2024-11-01T09:01:30Z"
}
{
  "event_type": "order.failed",
  "order_id": "01960a9b-…",
  "service_code": "whatsapp",
  "country_code": "US",
  "status": "failed",
  "error_code": "NO_NUMBERS_AVAILABLE",
  "failed_at": "2024-11-01T09:00:30Z"
}

Verify the signature

Every request carries an X-Webhook-Signature: sha256=<hex> header. Compute HMAC-SHA256 over the raw request body with your secret and compare in constant time before trusting the payload.

import crypto from 'node:crypto'

function verify(rawBody, header, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(rawBody)              // raw bytes, not parsed JSON
    .digest('hex')
  const sig = Buffer.from(header || '', 'utf8')
  const exp = Buffer.from(expected, 'utf8')
  // length check first — timingSafeEqual throws on unequal lengths
  return sig.length === exp.length &&
    crypto.timingSafeEqual(sig, exp)
}

Delivery & retries

Respond with 2xx quickly (within 10s). Failed deliveries are retried up to 5 times with backoff (30s → 5m → 30m → 2h). Delivery is best-effort.

Delivery monitoring

Use the dashboard delivery history to monitor failed events. Order status queries are disabled by default; contact support if you require a dedicated reconciliation workflow.

API Endpoints

Base URL: https://api.dogesms.com — all paths below are relative to this base.

MethodPathDescriptionCommon Responses
GET/v1/balanceGet account balance200 Returns { data: { balance_cents: number, currency: string }, request_id: string }. / 401 API Key missing, invalid, or revoked.
POST/v1/ordersCreate an order201 Order created. Receive number, SMS, and terminal-state updates through webhook events. / 400 Missing or invalid parameters (service_code or country_code absent, bad Idempotency-Key format, etc.). / 412 Actual price exceeds the spend cap (max_price_cents). Error code: PRICE_CHANGED. / 422 Insufficient balance (INSUFFICIENT_BALANCE), wallet not initialized (WALLET_NOT_INITIALIZED), or no numbers available for this service/country combination (SERVICE_NOT_AVAILABLE).
POST/v1/orders/{id}/cancelCancel an order200 Cancellation accepted. If the order is already in a terminal state (completed, expired, failed, or cancelled) and its state can be read back, the current order object is returned idempotently with no side effects. / 404 Order not found or does not belong to this account. / 409 Either the order is already terminal (ORDER_ALREADY_TERMINAL — use the delivered terminal webhook event, or contact support), or cancellation is temporarily unavailable (CANCEL_DENIED_RETRY_LATER — the SMS may still arrive; the order stays active, retry in a few minutes or wait for automatic expiry refund). / 422 Cancellation not allowed within 2 minutes of order creation (cooldown). Error code: CANCEL_TOO_EARLY.
GET/v1/catalog/servicesList available services200 Success. Returns an array of service objects, each with code and name. / 401 Authentication failed.
GET/v1/catalog/countriesList available countries200 Success. Returns an array of country objects with code, name, phone_prefix, and service_count. / 401 Authentication failed.
GET/v1/catalog/pricesList prices for a country200 Success. Returns an array with service_code, service_name, price_cents, and available_count. / 400 Missing country_code parameter. / 401 Authentication failed. / 404 Country not found or no price data available.
GET/v1/balance

Get account balance

Returns the current balance in cents. Check this before placing orders to avoid INSUFFICIENT_BALANCE (422) errors.

Parameters

No request parameters required for this endpoint.

Response codes

200

Returns { data: { balance_cents: number, currency: string }, request_id: string }.

401

API Key missing, invalid, or revoked.

POST/v1/orders

Create an order

Creates an order for the requested service and country. Number and SMS readiness are delivered through order.number_allocated and order.completed webhook events. Include X-Idempotency-Key to prevent duplicate charges on retries.

Parameters

service_codestringRequired

Service to activate, e.g. whatsapp or telegram.

country_codestringRequired

Two-letter country code for number allocation, e.g. US or GB.

tierstringOptional

Price tier: standard (default) or premium.

max_price_centsintegerOptional

Optional spend cap in cents. If the actual price exceeds this (with 5% tolerance), the order returns 412 PRICE_CHANGED.

Response codes

201

Order created. Receive number, SMS, and terminal-state updates through webhook events.

400

Missing or invalid parameters (service_code or country_code absent, bad Idempotency-Key format, etc.).

412

Actual price exceeds the spend cap (max_price_cents). Error code: PRICE_CHANGED.

422

Insufficient balance (INSUFFICIENT_BALANCE), wallet not initialized (WALLET_NOT_INITIALIZED), or no numbers available for this service/country combination (SERVICE_NOT_AVAILABLE).

POST/v1/orders/{id}/cancel

Cancel an order

Cancels an order that is still in progress — either pending (awaiting number allocation) or active (number assigned, waiting for the SMS). Releases the reserved number and refunds the charge. Completed, failed, or already-cancelled orders cannot be cancelled.

Parameters

idstringRequired

Order UUID to cancel.

Response codes

200

Cancellation accepted. If the order is already in a terminal state (completed, expired, failed, or cancelled) and its state can be read back, the current order object is returned idempotently with no side effects.

404

Order not found or does not belong to this account.

409

Either the order is already terminal (ORDER_ALREADY_TERMINAL — use the delivered terminal webhook event, or contact support), or cancellation is temporarily unavailable (CANCEL_DENIED_RETRY_LATER — the SMS may still arrive; the order stays active, retry in a few minutes or wait for automatic expiry refund).

422

Cancellation not allowed within 2 minutes of order creation (cooldown). Error code: CANCEL_TOO_EARLY.

GET/v1/catalog/services

List available services

Returns all supported services (e.g. WhatsApp, Telegram, Google). Use service codes from this list as service_code when creating orders.

Parameters

No request parameters required for this endpoint.

Response codes

200

Success. Returns an array of service objects, each with code and name.

401

Authentication failed.

GET/v1/catalog/countries

List available countries

Returns all supported countries, sorted by number of available services (most popular first). Use country codes from this list as country_code when creating orders.

Parameters

No request parameters required for this endpoint.

Response codes

200

Success. Returns an array of country objects with code, name, phone_prefix, and service_count.

401

Authentication failed.

GET/v1/catalog/prices

List prices for a country

Returns all available services and their reference prices for the specified country. Prices are in cents (USD) and reflect the displayed price including markup. The server applies authoritative catalog pricing at order time — use max_price_cents on POST /v1/orders if you need a price cap.

Parameters

country_codestringRequired

ISO country code (e.g. US, GB). Case-insensitive.

Response codes

200

Success. Returns an array with service_code, service_name, price_cents, and available_count.

400

Missing country_code parameter.

401

Authentication failed.

404

Country not found or no price data available.

Create Order Example

Request body and response JSON when calling POST /v1/orders.

POST https://api.dogesms.com/v1/orders
Authorization: Bearer sk_live_…
X-Idempotency-Key: 73b7f4a2-1c3e-4d5f-8e9a-0b1c2d3e4f52
Content-Type: application/json

{
  "service_code": "whatsapp",
  "country_code": "US"
}
HTTP 201 Created
X-Request-Id: req_abc123…

{
  "data": {
    "id": "01960a9b-…",
    "order_no": "ORD-20241101-0042",
    "service_code": "whatsapp",
    "country_code": "US",
    "status": "pending",
    "amount_cents": 0,
    "currency": "USD",
    "created_at": "2024-11-01T09:00:00Z"
  },
  "request_id": "req_abc123…"
}
// Receive lifecycle updates through Webhook events:
//   order.number_allocated → phone_number is ready
//   order.completed        → sms_code is ready
//   order.failed / order.expired → terminal error states

Open API includes 50 trial calls. After the trial, an enabled and verified webhook is required. Receive number and SMS state through webhook events.

Supported Services & Countries

Currently 6 services and 9 countries/regions available.

📱 WhatsApp✈️ Telegram🔍 Google🎵 TikTok🛒 Amazon🧧 淘宝

Availability varies in real time. Always check your order response rather than assuming a fixed catalog.

Common error codes

Handle these status codes explicitly in your integration rather than relying on generic error handling.

401

Unauthorized

The API Key is missing, malformed, or revoked.

Verify the Authorization header format (Bearer sk_live_…) and confirm the key is active in the dashboard.

403

Forbidden

The API Key is valid but access is blocked: the trial is exhausted without a verified webhook (WEBHOOK_REQUIRED), or the account status is restricted.

Enable and verify your webhook in the dashboard. Contact support if the account remains restricted.

409

State conflict

The order is already in a terminal state (completed, cancelled, or failed) and cannot be modified.

Use the terminal webhook event and do not blindly retry writes. Contact support if reconciliation is required.

412

Price changed

The actual price for the requested number exceeds the max_price_cents cap you supplied.

Remove max_price_cents to place the order at the current market price, or raise the cap and retry.

422

Unprocessable request

Balance is insufficient (INSUFFICIENT_BALANCE) or no numbers are available for the requested service/country (SERVICE_NOT_AVAILABLE).

For INSUFFICIENT_BALANCE: top up via the dashboard. For SERVICE_NOT_AVAILABLE: retry after a short delay or try a different country.

429

Rate limit exceeded

Too many requests in the current time window.

Back off exponentially, preserve your Idempotency-Key, and retry after the window resets.

Technical Support

Telegram Support

@dogesms_official

Hours: Daily 09:00-21:00 UTC+8 for live follow-up

Email Support

support@dogesms.com

Hours: 24/7 ticket intake with business-hour review

For high-volume or enterprise access, contact the sales team.