Tài liệu API

v1.0.0

Truy cập lập trình đến số ảo, đơn hàng và số dư tài khoản.

Xác thực

Tất cả yêu cầu API đều yêu cầu Bearer token. Tạo token từ Cài đặt tài khoản trong bảng điều khiển, sau đó đính kèm vào mỗi yêu cầu:

Authorization: Bearer YOUR_API_TOKEN

Yêu cầu không có token hợp lệ sẽ nhận phản hồi 401 UNAUTHORIZED.

URL cơ sở

Tất cả đường dẫn endpoint bên dưới tương đối với:

https://api.smscode.gg/v1

Định dạng phản hồi

Mọi phản hồi trả về JSON với cấu trúc nhất quán. Tất cả phản hồi bao gồm header x-request-id để gỡ lỗi.

Thành công
{
  "success": true,
  "data": { ... }
}
Lỗi
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable message"
  }
}
GET /catalog/countries

Trả về danh sách tất cả quốc gia có sẵn.

Tham số

Không có

Ví dụ yêu cầu

curl -s https://api.smscode.gg/v1/catalog/countries \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/catalog/countries", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/countries",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": [
    {
      "id": 6,
      "code": "ID",
      "name": "Indonesia",
      "dial_code": "+62",
      "emoji": "🇮🇩",
      "active": true
    }
  ]
}
GET /catalog/services

Trả về danh sách dịch vụ (nền tảng) có sẵn. Có thể lọc theo quốc gia.

Tham số truy vấn

TênKiểuBắt buộcMô tả
country_idintegerKhôngLọc dịch vụ có sẵn cho quốc gia này

Ví dụ yêu cầu

curl -s "https://api.smscode.gg/v1/catalog/services?country_id=6" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/catalog/services?country_id=6", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/services",
    params={"country_id": 6},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": [
    {
      "id": 3,
      "code": "wa",
      "name": "WhatsApp",
      "active": true
    }
  ]
}
GET /catalog/products

Trả về danh sách sản phẩm có sẵn (phân trang). Lọc theo quốc gia và/hoặc nền tảng.

Tham số truy vấn

TênKiểuBắt buộcMô tả
country_idintegerKhôngLọc theo ID quốc gia
platform_idintegerKhôngLọc theo ID nền tảng/dịch vụ
sortstringKhôngThứ tự sắp xếp: price_asc (mặc định), price_desc, available_asc, available_desc, name_asc, name_desc
limitintegerKhôngSố kết quả mỗi trang (1-10.000, mặc định 1.000)
pageintegerKhôngSố trang (tối thiểu 1, mặc định 1)

Ví dụ yêu cầu

curl -s "https://api.smscode.gg/v1/catalog/products?country_id=6&platform_id=3&limit=10&page=1" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  country_id: "6", platform_id: "3", limit: "10", page: "1",
});
const res = await fetch(`https://api.smscode.gg/v1/catalog/products?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/products",
    params={"country_id": 6, "platform_id": 3, "limit": 10, "page": 1},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": [
    {
      "id": 142,
      "name": "WhatsApp Indonesia",
      "country_id": 6,
      "platform_id": 3,
      "available": 42,
      "price": 15000,
      "active": true
    }
  ],
  "meta": { "page": 1, "limit": 10, "count": 1 }
}
GET /catalog/exchange-rate

Trả về tỷ giá hối đoái hiện tại cho một cặp tiền tệ. Hữu ích để chuyển đổi giá.

Tham số truy vấn

TênKiểuBắt buộcMô tả
pairstringKhôngCặp tiền tệ (mặc định: USD/IDR)

Ví dụ yêu cầu

curl -s "https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/catalog/exchange-rate?pair=USD/IDR", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/catalog/exchange-rate",
    params={"pair": "USD/IDR"},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "pair": "USD/IDR",
    "base_currency": "USD",
    "quote_currency": "IDR",
    "rate": 16250
  }
}
GET /balance

Trả về số dư tài khoản của người dùng đã xác thực bằng IDR.

Tham số

Không có

Ví dụ yêu cầu

curl -s https://api.smscode.gg/v1/balance \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/balance", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/balance",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "currency": "IDR",
    "balance": 500000
  }
}
GET /orders

Trả về danh sách đơn hàng của người dùng đã xác thực, sắp xếp theo mới nhất. Hỗ trợ lọc theo trạng thái và phân trang qua offset.

Tham số truy vấn

TênKiểuBắt buộcMô tả
limitintegerKhôngSố kết quả tối đa (1-100, mặc định 20)
offsetintegerKhôngSố kết quả bỏ qua (mặc định 0)
statusstringKhôngLọc theo trạng thái: ACTIVE, OTP_RECEIVED, COMPLETED, CANCELED, EXPIRED (không phân biệt hoa thường)

Ví dụ yêu cầu

curl -s "https://api.smscode.gg/v1/orders?limit=5&status=ACTIVE" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const params = new URLSearchParams({
  limit: "5", status: "ACTIVE", offset: "0",
});
const res = await fetch(`https://api.smscode.gg/v1/orders?${params}`, {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/orders",
    params={"limit": 5, "status": "ACTIVE", "offset": 0},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": [
    {
      "id": 1001,
      "status": "ACTIVE",
      "created_at": "2026-02-25T10:00:00Z",
      "product_id": 142,
      "phone_number": "+6281234567890",
      "amount": 15000,
      "otp_code": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:20:00Z",
      "canceled_at": null,
      "failed_reason": null
    }
  ]
}
GET /orders/{id}

Trả về một đơn hàng theo ID. Chỉ trả về đơn hàng của người dùng đã xác thực.

Tham số đường dẫn

TênKiểuBắt buộcMô tả
idintegerMã đơn hàng (tham số đường dẫn)

Ví dụ yêu cầu

curl -s https://api.smscode.gg/v1/orders/1001 \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/orders/1001", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/orders/1001",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "id": 1001,
    "status": "OTP_RECEIVED",
    "created_at": "2026-02-25T10:00:00Z",
    "product_id": 142,
    "phone_number": "+6281234567890",
    "amount": 15000,
    "otp_code": "123456",
    "otp_received_at": "2026-02-25T10:05:00Z",
    "expires_at": "2026-02-25T10:20:00Z",
    "canceled_at": null,
    "failed_reason": null
  }
}
GET /orders/active

Liệt kê tất cả đơn hàng đang hoạt động (ACTIVE + OTP_RECEIVED). Sử dụng để theo dõi cập nhật trạng thái OTP.

Tham số

Không có

Ví dụ yêu cầu

curl -s https://api.smscode.gg/v1/orders/active \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/orders/active", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/orders/active",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": [
    {
      "id": 1001,
      "status": "OTP_RECEIVED",
      "otp_code": "123456",
      "otp_message": "Your verification code is 123456",
      "otp_received_at": "2026-02-25T10:05:00Z",
      "expires_at": "2026-02-25T10:20:00Z",
      "failed_reason": null
    },
    {
      "id": 1002,
      "status": "ACTIVE",
      "otp_code": null,
      "otp_message": null,
      "otp_received_at": null,
      "expires_at": "2026-02-25T10:50:00Z",
      "failed_reason": null
    }
  ]
}
POST /orders/create

Tạo đơn hàng số ảo mới. Tự động trừ số dư. Hỗ trợ header Idempotency-Key tùy chọn để tránh tạo đơn trùng lặp khi thử lại do lỗi mạng.

Nội dung yêu cầu

TênKiểuBắt buộcMô tả
product_idintegerID sản phẩm cần đặt hàng
quantityintegerKhôngSố lượng (1-100, mặc định 1)

Truyền header Idempotency-Key (chuỗi bất kỳ duy nhất) để thử lại yêu cầu an toàn mà không tạo đơn trùng lặp.

Ví dụ yêu cầu

curl -s -X POST https://api.smscode.gg/v1/orders/create \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: unique-request-id-123" \
  -d '{"product_id":142,"quantity":1}'
const res = await fetch("https://api.smscode.gg/v1/orders/create", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
    "Idempotency-Key": "unique-request-id-123",
  },
  body: JSON.stringify({ product_id: 142, quantity: 1 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/create",
    json={"product_id": 142, "quantity": 1},
    headers={
        "Authorization": "Bearer YOUR_API_TOKEN",
        "Idempotency-Key": "unique-request-id-123",
    })
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "orders": [
      {
        "id": 1002,
        "status": "ACTIVE",
        "phone_number": "+6281234567891",
        "otp_code": null,
        "otp_received_at": null,
        "expires_at": "2026-02-25T10:50:00Z",
        "failed_reason": null
      }
    ],
    "failed_count": 0
  }
}
POST /orders/cancel

Hủy đơn hàng đang hoạt động. Phí thuê sẽ được hoàn vào số dư tài khoản.

Nội dung yêu cầu

TênKiểuBắt buộcMô tả
idintegerMã đơn hàng cần hủy

Ví dụ yêu cầu

curl -s -X POST https://api.smscode.gg/v1/orders/cancel \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":1001}'
const res = await fetch("https://api.smscode.gg/v1/orders/cancel", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ id: 1001 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/cancel",
    json={"id": 1001},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "CANCELED",
    "refund_amount": 15000,
    "new_balance": 515000
  }
}
POST /orders/finish

Đánh dấu đơn hàng đã hoàn thành sau khi nhận OTP. Giải phóng số ngay lập tức thay vì đợi hết hạn.

Nội dung yêu cầu

TênKiểuBắt buộcMô tả
idintegerMã đơn hàng cần hoàn thành

Ví dụ yêu cầu

curl -s -X POST https://api.smscode.gg/v1/orders/finish \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":1001}'
const res = await fetch("https://api.smscode.gg/v1/orders/finish", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ id: 1001 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/finish",
    json={"id": 1001},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "COMPLETED"
  }
}
POST /orders/resend

Yêu cầu nền tảng gửi lại SMS đến số đã thuê. Không phải tất cả nền tảng đều hỗ trợ gửi lại — kiểm tra trường resent trong phản hồi.

Nội dung yêu cầu

TênKiểuBắt buộcMô tả
idintegerMã đơn hàng cần gửi lại SMS

Ví dụ yêu cầu

curl -s -X POST https://api.smscode.gg/v1/orders/resend \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":1001}'
const res = await fetch("https://api.smscode.gg/v1/orders/resend", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ id: 1001 }),
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/orders/resend",
    json={"id": 1001},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "order_id": 1001,
    "status": "ACTIVE",
    "resent": true
  }
}
GET /webhook

Trả về cấu hình webhook notification hiện tại của bạn.

Tham số

Không có

Ví dụ yêu cầu

curl -s https://api.smscode.gg/v1/webhook \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/webhook", {
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.get("https://api.smscode.gg/v1/webhook",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}
PATCH /webhook

Cập nhật URL webhook và/hoặc secret. Secret được tự động tạo khi bạn đặt URL lần đầu. Gửi chuỗi rỗng để xóa. URL phải sử dụng HTTPS.

Nội dung yêu cầu

TênKiểuBắt buộcMô tả
webhook_urlstringKhôngURL HTTPS để nhận sự kiện webhook (chuỗi rỗng để xóa)
webhook_secretstringKhôngSecret chia sẻ cho chữ ký HMAC-SHA256 (tự động tạo nếu bỏ qua lần đặt đầu tiên)

Cần ít nhất một trường.

Ví dụ yêu cầu

curl -s -X PATCH https://api.smscode.gg/v1/webhook \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"webhook_url":"https://example.com/webhook"}'
const res = await fetch("https://api.smscode.gg/v1/webhook", {
  method: "PATCH",
  headers: {
    Authorization: "Bearer YOUR_API_TOKEN",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ webhook_url: "https://example.com/webhook" }),
});
const data = await res.json();
import requests

res = requests.patch("https://api.smscode.gg/v1/webhook",
    json={"webhook_url": "https://example.com/webhook"},
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "webhook_url": "https://example.com/webhook",
    "webhook_secret": "a1b2c3d4e5f6..."
  }
}
POST /webhook/test

Gửi sự kiện thử nghiệm đến URL webhook đã cấu hình. Trả về mã trạng thái HTTP từ máy chủ của bạn. Hữu ích để kiểm tra endpoint hoạt động trước khi vận hành chính thức.

Tham số

Không có

Ví dụ yêu cầu

curl -s -X POST https://api.smscode.gg/v1/webhook/test \
  -H "Authorization: Bearer YOUR_API_TOKEN"
const res = await fetch("https://api.smscode.gg/v1/webhook/test", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_TOKEN" },
});
const data = await res.json();
import requests

res = requests.post("https://api.smscode.gg/v1/webhook/test",
    headers={"Authorization": "Bearer YOUR_API_TOKEN"})
data = res.json()

Ví dụ phản hồi

200 OK
{
  "success": true,
  "data": {
    "status_code": 200
  }
}

Webhook Notifications

Cấu hình URL webhook để nhận thông báo đẩy theo thời gian thực cho các sự kiện đơn hàng thay vì polling. Đây là phương pháp được khuyến nghị cho bot script.

Sự kiện

Sự kiệnKích hoạt
order.otp_receivedMã OTP đã được gửi đến số thuê
order.completedĐơn hàng đã hoàn thành (thủ công hoặc khi hết hạn)
order.expiredĐơn hàng hết hạn mà không có OTP (đã hoàn tiền)
order.canceledĐơn hàng bị hủy bởi người dùng (đã hoàn tiền)

Payload

Nội dung POST webhook
{
  "event": "order.otp_received",
  "timestamp": "2026-02-25T12:00:00Z",
  "data": {
    "order_id": 1001,
    "phone_number": "+628123456789",
    "otp_code": "1234",
    "otp_message": "Your verification code is 1234",
    "product_id": 42,
    "country": "Indonesia",
    "platform": "WhatsApp"
  }
}

Xác minh chữ ký

Mỗi yêu cầu webhook bao gồm header X-Webhook-Signature chứa chữ ký HMAC-SHA256 của nội dung yêu cầu, sử dụng webhook_secret làm khóa:

X-Webhook-Signature: sha256={HMAC-SHA256(body, webhook_secret)}

Xác minh chữ ký này trên máy chủ để đảm bảo yêu cầu là xác thực. Gửi theo kiểu fire-and-forget với timeout 3 giây và không thử lại.

Rate Limits

Yêu cầu API được giới hạn tốc độ theo nhóm endpoint. Vượt quá giới hạn trả về 429 Too Many Requests với header Retry-After cho biết số giây cần đợi.

Nhóm endpointGiới hạnCửa sổ
Danh mục (quốc gia, dịch vụ, sản phẩm, tỷ giá)1.200 yêu cầu60 giây
Số dư600 yêu cầu60 giây
Đọc đơn hàng (danh sách, chi tiết, hoạt động)1.200 yêu cầu60 giây
Tạo đơn hàng1.200 yêu cầu60 giây
Hủy đơn hàng600 yêu cầu60 giây
Thao tác đơn hàng (hoàn thành, gửi lại)600 yêu cầu60 giây
Cấu hình webhook (xem, cập nhật, thử)120 yêu cầu60 giây

Mã lỗi

Phản hồi lỗi bao gồm một trong các mã sau trong error.code:

HTTPMô tả
UNAUTHORIZED401Thiếu hoặc API token không hợp lệ
FORBIDDEN403Truy cập bị từ chối
NOT_FOUND404Không tìm thấy tài nguyên (đơn hàng, tỷ giá, v.v.)
CONFLICT409Yêu cầu trùng lặp hoặc xung đột tài nguyên
INSUFFICIENT_BALANCE409Số dư không đủ để tạo đơn hàng
VALIDATION_ERROR422Tham số yêu cầu không hợp lệ
RATE_LIMIT_EXCEEDED429Quá nhiều yêu cầu (kiểm tra header Retry-After)
INTERNAL_ERROR500Lỗi máy chủ nội bộ
PROVIDER_ERROR422Nhà cung cấp SMS thượng nguồn từ chối yêu cầu
CANCEL_TOO_EARLY409Đơn hàng quá mới để hủy — hãy đợi 2 phút
SERVICE_UNAVAILABLE503Dịch vụ tạm thời không khả dụng (bảo trì)