Build with Vozira SMS

Long-term and temporary numbers. One Vozira account, one wallet, one API.

https://vozirasms.com/api/v1

Authentication & wallet

Sign in to your ordinary Vozira account → API Access → generate a key and save it securely. Existing active keys work with v1. Send X-Api-Key over HTTPS from your server. Keys must not appear in URLs, public repositories or browser code. Rotating a key revokes the old key. Fund your wallet using Recharge on the website; v1 does not create payment invoices.

Long-term numbers

Read /apps and /limits, then buy with the catalog app_id, cate_id, quantity, expiry and expected_total. Only type=1 is supported for new purchases. Save a unique 16–128 character Idempotency-Key before the first request. Success requires status=completed and request_status=completed; use the returned order_reference and item IDs to read orders and SMS. Amounts are USD with up to four decimals. Catalog stock can change before purchase.

Temporary numbers

Use a regular account key. Search services and countries separately; the initial catalog is a shortlist, not every available selection. Request a quote for the pair, review its exact price and expiry, then buy using its quote_id and a saved Idempotency-Key. The same key with another quote returns IDEMPOTENCY_CONFLICT. Orders include SMS, cancel availability and refund state. The order list is the latest 100 orders; save order IDs for older orders.

Cancellation & refunds

A temporary number is valid for 20 minutes; use the returned expires_at. After two minutes, an order without SMS can request cancellation. A pending cancellation is not a completed refund. After expiry, an order with no SMS received by Vozira refunds the original purchase amount to the site wallet. Received-SMS orders do not qualify for this refund. Check refund.status=refunded and refund.amount; each order is refunded at most once. A failed, reversed purchase may also return refunded. Exceptions marked review_required need review.

Retries, status & limits

On a timeout, 5xx, processing or an uncertain charge, query the original key/order. Never rotate the key to retry the same intended purchase. HTTP 200/202 or ok:true alone is not delivery. A missing result immediately after timeout can race the original request; continue checking and contact support if unresolved. Poll messages at least 5 seconds apart and slow to 10–15 seconds when empty. Respect Retry-After on 429. Global IP and network limits also apply. There are no developer callback webhooks in v1; poll orders for SMS/refunds. There is no public sandbox; successful purchases use real wallet funds.

Validity & renewal

expiry: 0=random, 1=5–30 days, 2=10–30, 3=15–30, 4=30–60, 5=60–80, 6=80+ days (+10%). Category 4 and 5 accept only 0. These are selection ranges; the actual order expiry is authoritative. Use renewal eligibility → quote → confirm for eligible regular-account numbers. Confirm with an empty JSON object and one saved idempotency key. Only state=succeeded is an ordinary completed renewal; quoted awaits confirmation, submitting/needs_review must be queried, success_unpaid states need support and must not be purchased again. failed closes the original operation. price_cents is USD cents and quote_expires_at is Unix milliseconds. Receipt end_time may be Unix seconds/milliseconds or a date-time: no offset means UTC+08:00; never append Z. purchased_at and recorded_at are UTC.

Error handling

Errors contain error.code, a fixed message and error.request_id for support. The error trace ID is different from the persistent purchase request_id. Price errors can include unit_price and total_price. charge_status=unknown means check the original operation, not that no debit occurred. Site/CDN rejections may have another body; inspect HTTP status too.

Compatibility

Existing /api/reseller long-number routes and legacy accounts remain available. Their product metadata is reduced to documented customer fields. v1 is the recommended entry. Temporary numbers, wallet transactions and standard renewal require a regular account. Legacy reseller recharge remains in its existing portal. Catalog IDs are opaque selections: use returned values without inferring their meaning.

Examples (replace all fictional IDs and prices)

export VOZIRA_API_KEY='YOUR_VOZIRA_API_KEY'
curl https://vozirasms.com/api/v1/balance \
  -H "X-Api-Key: $VOZIRA_API_KEY"
curl 'https://vozirasms.com/api/v1/apps?type=1&expiry=0&search=Telegram' \
  -H "X-Api-Key: $VOZIRA_API_KEY"
# Use IDs and price returned by the live catalog; save the key before sending.
curl https://vozirasms.com/api/v1/buy \
  -H "X-Api-Key: $VOZIRA_API_KEY" -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: YOUR_SAVED_UNIQUE_KEY_0001' \
  --data '{"app_id":123,"cate_id":2,"type":1,"quantity":1,"expiry":0,"expected_total":"0.5000"}'
# After timeout: query, do not use a new purchase key.
curl https://vozirasms.com/api/v1/requests/by-key \
  -H "X-Api-Key: $VOZIRA_API_KEY" \
  -H 'Idempotency-Key: YOUR_SAVED_UNIQUE_KEY_0001' 
# Search each selection list, then quote the selected pair.
curl 'https://vozirasms.com/api/v1/one-time/catalog?service=Telegram' -H "X-Api-Key: $VOZIRA_API_KEY"
curl 'https://vozirasms.com/api/v1/one-time/catalog?country=United%20States' -H "X-Api-Key: $VOZIRA_API_KEY"
curl https://vozirasms.com/api/v1/one-time/quote \
  -H "X-Api-Key: $VOZIRA_API_KEY" -H 'Content-Type: application/json' \
  --data '{"service_code":"CATALOG_CODE","country_id":1}'
# Review quote.price and expires_at. Save this different key before sending.
curl https://vozirasms.com/api/v1/one-time/buy \
  -H "X-Api-Key: $VOZIRA_API_KEY" -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: YOUR_SAVED_UNIQUE_KEY_0002' \
  --data '{"quote_id":"QUOTE_UUID_FROM_RESPONSE"}'
curl https://vozirasms.com/api/v1/one-time/requests/by-key \
  -H "X-Api-Key: $VOZIRA_API_KEY" -H 'Idempotency-Key: YOUR_SAVED_UNIQUE_KEY_0002'
curl https://vozirasms.com/api/v1/one-time/orders/OT_REPLACE_WITH_ORDER_ID \
  -H "X-Api-Key: $VOZIRA_API_KEY"

Python example · Node.js example

Endpoint reference

OpenAPI: request and response schemas

GET /balance — Account balance

{
  "parameters": []
}
GET /recharge — Website recharge link

{
  "parameters": []
}
GET /limits — Long-number limits

{
  "parameters": []
}
GET /apps — Long-number catalog

{
  "parameters": [
    {
      "name": "type",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "enum": [
          1
        ],
        "default": 1
      },
      "description": ""
    },
    {
      "name": "expiry",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 0,
        "maximum": 6,
        "default": 0
      },
      "description": ""
    },
    {
      "name": "search",
      "in": "query",
      "required": false,
      "schema": {
        "type": "string",
        "maxLength": 80
      },
      "description": ""
    },
    {
      "name": "cate_id",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "description": ""
    }
  ]
}
POST /buy — Buy long numbers

{
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "app_id": {
              "type": "integer",
              "minimum": 1
            },
            "cate_id": {
              "type": "integer",
              "minimum": 1
            },
            "type": {
              "type": "integer",
              "enum": [
                1
              ],
              "default": 1
            },
            "quantity": {
              "type": "integer",
              "minimum": 1
            },
            "expiry": {
              "type": "integer",
              "minimum": 0,
              "maximum": 6,
              "default": 0
            },
            "expected_total": {
              "type": "string",
              "pattern": "^(0|[1-9]\\d{0,5})(\\.\\d{1,4})?$"
            },
            "prefix": {
              "type": "string"
            }
          },
          "required": [
            "app_id",
            "cate_id",
            "quantity",
            "expected_total"
          ],
          "additionalProperties": false
        }
      }
    }
  }
}
GET /requests/by-key — Recover a long purchase by key

{
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ]
}
GET /requests/{id} — Long purchase status

{
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string"
      }
    }
  ]
}
GET /orders — Long-number orders

{
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 20
      },
      "description": ""
    },
    {
      "name": "before_id",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "description": ""
    }
  ]
}
GET /orders/{reference} — Long-number order

{
  "parameters": [
    {
      "name": "reference",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "pattern": "^VZ-\\d+$"
      }
    }
  ]
}
GET /sms/{item_id} — Read long-number SMS

{
  "parameters": [
    {
      "name": "item_id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "integer",
        "minimum": 1
      }
    }
  ]
}
GET /sms-history — SMS history

{
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 20
      },
      "description": ""
    },
    {
      "name": "before_id",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "description": ""
    },
    {
      "name": "item_id",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "description": ""
    }
  ]
}
GET /transactions — Wallet transactions

Regular accounts only. Includes website and API wallet transactions.

{
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 20
      },
      "description": ""
    },
    {
      "name": "before_id",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1
      },
      "description": ""
    }
  ]
}
GET /renewal/eligibility/{itemId} — Check renewal eligibility

Regular accounts only. Read state and payment_state. Confirm the original operation once, then query it; do not create another quote to retry an uncertain result.

{
  "parameters": [
    {
      "name": "itemId",
      "in": "path",
      "required": true,
      "schema": {
        "type": "integer",
        "minimum": 1
      }
    }
  ]
}
POST /renewal/quote/{itemId} — Quote renewal

Regular accounts only. Read state and payment_state. Confirm the original operation once, then query it; do not create another quote to retry an uncertain result.

{
  "parameters": [
    {
      "name": "itemId",
      "in": "path",
      "required": true,
      "schema": {
        "type": "integer",
        "minimum": 1
      }
    }
  ]
}
POST /renewal/confirm/{id} — Confirm renewal

Regular accounts only. Read state and payment_state. Confirm the original operation once, then query it; do not create another quote to retry an uncertain result.

{
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string"
      }
    },
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {},
          "required": [],
          "additionalProperties": false
        }
      }
    }
  }
}
GET /renewal/by-key — Recover renewal by key

Regular accounts only. Read state and payment_state. Confirm the original operation once, then query it; do not create another quote to retry an uncertain result.

{
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ]
}
GET /renewal/{id} — Renewal status

Regular accounts only. Read state and payment_state. Confirm the original operation once, then query it; do not create another quote to retry an uncertain result.

{
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string"
      }
    }
  ]
}
GET /one-time/catalog — Temporary services and countries

Search services and countries separately. Initial response is a shortlist, not the complete catalog. Selecting a pair does not guarantee inventory; request a quote.

{
  "parameters": [
    {
      "name": "service",
      "in": "query",
      "required": false,
      "schema": {
        "type": "string",
        "maxLength": 80
      },
      "description": ""
    },
    {
      "name": "country",
      "in": "query",
      "required": false,
      "schema": {
        "type": "string",
        "maxLength": 80
      },
      "description": ""
    },
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 200,
        "default": 30
      },
      "description": ""
    }
  ]
}
POST /one-time/quote — Quote a temporary number

{
  "parameters": [],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "service_code": {
              "type": "string"
            },
            "country_id": {
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "service_code",
            "country_id"
          ],
          "additionalProperties": false
        }
      }
    }
  }
}
POST /one-time/buy — Buy a temporary number

{
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "quote_id": {
              "type": "string",
              "format": "uuid"
            }
          },
          "required": [
            "quote_id"
          ],
          "additionalProperties": false
        }
      }
    }
  }
}
GET /one-time/requests/by-key — Recover temporary purchase

{
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 16,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._~:+/=\\-]{16,128}$"
      },
      "description": "Save before sending. Reuse only for the exact original operation; never rotate after an unknown outcome."
    }
  ]
}
GET /one-time/orders — Latest 100 temporary orders

{
  "parameters": []
}
GET /one-time/orders/{id} — Temporary order, SMS and refund

{
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "pattern": "^OT-[A-Z0-9]{16}$"
      }
    }
  ]
}
POST /one-time/orders/{id}/cancel — Cancel a temporary number

{
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "pattern": "^OT-[A-Z0-9]{16}$"
      }
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {},
          "required": [],
          "additionalProperties": false
        }
      }
    }
  }
}