📚 Документация Partner API
Обзор
Partner API позволяет интегрировать сервис аренды SMS-номеров в ваши приложения через модель Prepaid Wallet.
Prepaid Wallet
Оптовое пополнение со скидкой 5-15%
Быстрый старт
Простая интеграция через REST API
Безопасность
HMAC-SHA256 подпись запросов
SMS в реальном времени
Webhooks для мгновенных уведомлений
Константы системы
Типы аренды
- SHORT - Краткосрочная аренда на 1 час
- LONG - Долгосрочная аренда от 1 до 90 дней
Доступные страны
- Spain - Испания Доступно
- Germany - Германия Скоро
- UK - Англия Скоро
⚠️ Важно: Типы аренды и коды стран являются константами. Используйте точные значения в запросах к API.
Аутентификация
Все API запросы должны быть подписаны с использованием HMAC-SHA256.
🌐 API Endpoint: https://telegram.smsbot.shop
Обязательные заголовки
HTTP Headers
X-Api-Key: pk_your_api_key_here
X-Signature: a3b9c1f2e4d6... (HMAC-SHA256 signature)
X-Timestamp: 1704106800000
Content-Type: application/json
Генерация подписи
JavaScript
const crypto = require('crypto');
function generateSignature(secretKey, timestamp, method, url, body) {
// Формируем payload для подписи
const payload = `${timestamp}${method}${url}${JSON.stringify(body || {})}`;
// Создаем HMAC-SHA256 подпись
return crypto
.createHmac('sha256', secretKey)
.update(payload)
.digest('hex');
}
// Пример использования
const timestamp = Date.now().toString();
const signature = generateSignature(
'sk_your_secret_key',
timestamp,
'POST',
'/api/v1/wallet/topup',
{ amount: 100 }
);
console.log('Signature:', signature);
Пример для Postman Pre-request Script
Postman Pre-request
// CryptoJS is already available globally in Postman, no require needed.
function generateSignature(secretKey, timestamp, method, url, body) {
const payload = `${timestamp}${method}${url}${JSON.stringify(body || {})}`;
return CryptoJS.HmacSHA256(payload, secretKey).toString(CryptoJS.enc.Hex);
}
// Data extraction (use pm.request for everything)
const timestamp = Date.now().toString();
const method = pm.request.method;
const fullUrl = pm.request.url.toString(); // e.g., "https://api.example.com/api/v1/endpoint?query=param"
const domain = pm.environment.get("domain"); // Ensure this is "https://telegram.smsbot.shop" (full, including protocol)
const url = fullUrl.replace(domain, "").replace('{{domain}}', ''); // Results in "/api/v1/endpoint?query=param"
let body = {};
if (pm.request.body && pm.request.body.mode === 'raw' && pm.request.body.raw) {
try {
body = JSON.parse(pm.request.body.raw);
} catch (e) {
body = {};
}
} // For non-raw bodies (e.g., form-data), it defaults to {} – adjust if needed for your API.
// Generate signature using env secretKey
const secretKey = pm.environment.get("secretKey");
const signature = generateSignature(secretKey, timestamp, method, url, body);
// Set env vars for headers
pm.environment.set("timestamp", timestamp);
pm.environment.set("signature", signature);
// Optional: Log for debugging (view in Postman Console)
console.log('Payload:', `${timestamp}${method}${url}${JSON.stringify(body || {})}`);
console.log('Signature:', signature);
💡 Настройка Postman: Создайте environment переменные domain и secretKey. Добавьте в Headers: X-Timestamp: {{timestamp}} и X-Signature: {{signature}}
Регистрация
Регистрация партнера
POST
/api/v1/auth/register
JSON Request
{
"name": "Название вашей компании",
"webhookUrl": "https://your-domain.com/webhooks",
"email": "admin@your-company.com",
"phone": "+1234567890"
}
JSON Response
{
"success": true,
"data": {
"partnerId": "partner_xyz123",
"apiKey": "pk_live_a1b2c3d4e5f6",
"secretKey": "sk_live_9z8y7x6w5v4u",
"status": "pending_approval",
"message": "Аккаунт партнера создан. Ожидает одобрения."
}
}
🔐 Важно: Сохраните ваш secretKey в безопасном месте. Его невозможно будет восстановить.
Проверка баланса
GET
/api/v1/wallet/balance
✅ Успешный ответ
JSON Response
{
"success": true,
"data": {
"balance": 1000.50,
"balanceBonus": 50.00,
"currency": "EUR",
"total": 1050.50,
"reserved": 25.00,
"available": 1025.50
}
}
Пополнение кошелька
POST
/api/v1/wallet/topup
Доступные платежные системы
- cryptomus - Криптовалютные платежи
- nowpayments - Криптовалютные платежи
JSON Request
{
"amount": 500,
"provider": "cryptomus"
}
JSON Response
{
"success": true,
"data": {
"invoiceId": "inv_abc123xyz",
"amount": 500,
"finalAmount": 450,
"discount": 50,
"discountPercent": 10,
"paymentUrl": "https://pay.cryptomus.com/invoice/abc123",
"expiresAt": "2024-01-01T12:00:00Z",
"status": "pending"
}
}
История транзакций
GET
/api/v1/wallet/transactions?page=1&limit=50
✅ Успешный ответ
JSON Response
{
"success": true,
"data": [
{
"id": "tx_abc123",
"type": "topup",
"amount": 100.00,
"currency": "EUR",
"balanceBefore": 900.00,
"balanceAfter": 1000.00,
"description": "Пополнение кошелька через Cryptomus",
"metadata": {
"provider": "cryptomus",
"invoiceId": "inv_xyz789"
},
"createdAt": "2024-01-01T10:00:00Z"
},
{
"id": "tx_def456",
"type": "charge",
"amount": -27.00,
"currency": "EUR",
"balanceBefore": 1000.00,
"balanceAfter": 973.00,
"description": "Number rental: +34612345678",
"metadata": {
"number": "+34612345678",
"country": "Spain",
"services": ["Google", "WhatsApp"],
"period": "7",
"rentType": "LONG"
},
"createdAt": "2024-01-01T11:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 150,
"totalPages": 3
}
}
Доступные сервисы
GET
/api/v1/numbers/services?country=Spain&rentType=LONG
Параметры запроса
- country - Код страны (Spain, Germany, UK)
- rentType - Тип аренды (SHORT, LONG)
JSON Response
{
"success": true,
"data": {
"country": "Spain",
"rentType": "LONG",
"services": [
{
"id": "google",
"name": "Google",
"prices": {
"1": 2.50,
"3": 6.00,
"7": 12.00,
"30": 35.00
},
"currency": "€",
"available": true,
"priority": 1
},
{
"id": "whatsapp",
"name": "WhatsApp",
"prices": {
"1": 3.00,
"7": 15.00,
"30": 45.00
},
"currency": "€",
"available": true,
"priority": 2
}
],
"total": 2
}
}
Расчет стоимости аренды
POST
/api/v1/numbers/calculate-price
JSON Request
{
"country": "Spain",
"rentType": "LONG",
"serviceIds": ["google", "whatsapp"]
}
JSON Response
{
"success": true,
"data": {
"country": "Spain",
"rentType": "LONG",
"services": [
{"id": "google", "name": "Google"},
{"id": "whatsapp", "name": "WhatsApp"}
],
"periods": [
{
"period": "1",
"duration": 1,
"durationUnit": "days",
"description": "1 day",
"basePrice": 5.50,
"price": 5.50,
"currency": "€",
"breakdown": [
{"service": "Google", "price": 2.50},
{"service": "WhatsApp", "price": 3.00}
]
},
{
"period": "7",
"duration": 7,
"durationUnit": "days",
"description": "7 days",
"basePrice": 27.00,
"price": 27.00,
"currency": "€",
"breakdown": [
{"service": "Google", "price": 12.00},
{"service": "WhatsApp", "price": 15.00}
]
}
],
"currency": "€"
}
}
Аренда номера
POST
/api/v1/numbers/rent
JSON Request
{
"country": "Spain",
"rentType": "LONG",
"serviceIds": ["google", "whatsapp"],
"period": "7"
}
JSON Response
{
"success": true,
"data": {
"rentId": "num_def456ghi",
"number": "+34612345678",
"country": "Spain",
"services": [
{"id": "google", "name": "Google"},
{"id": "whatsapp", "name": "WhatsApp"}
],
"price": 27.00,
"currency": "€",
"rentType": "LONG",
"period": "7",
"duration": {
"value": 10080,
"unit": "minutes"
},
"startsAt": "2024-01-01T10:00:00Z",
"expiresAt": "2024-01-08T10:00:00Z",
"status": "active"
}
}
Активные номера
GET
/api/v1/numbers/active?page=1&limit=50
✅ Успешный ответ
JSON Response
{
"success": true,
"data": [
{
"rentId": "num_abc123",
"number": "+34612345678",
"country": "Spain",
"services": [
{"id": "google", "name": "Google", "used": false},
{"id": "whatsapp", "name": "WhatsApp", "used": true}
],
"price": 27.00,
"currency": "€",
"rentType": "LONG",
"period": "7",
"status": "active",
"startsAt": "2024-01-01T10:00:00Z",
"expiresAt": "2024-01-08T10:00:00Z",
"rentedAt": "2024-01-01T10:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 10,
"totalPages": 1
}
}
Продление аренды
Расчет стоимости продления
GET
/api/v1/numbers/{rentId}/extend/calculate
✅ Успешный ответ
JSON Response
{
"success": true,
"data": {
"rentId": "num_abc123",
"number": "+34612345678",
"currentExpiry": "2024-01-08T10:00:00Z",
"availablePeriods": [
{
"period": "1",
"duration": 1,
"durationUnit": "days",
"description": "1 day",
"price": 5.50,
"currency": "€"
},
{
"period": "7",
"duration": 7,
"durationUnit": "days",
"description": "7 days",
"price": 27.00,
"currency": "€"
}
],
"currency": "€"
}
}
Продлить аренду
POST
/api/v1/numbers/{rentId}/extend
JSON Request
{
"period": "7"
}
JSON Response
{
"success": true,
"data": {
"rentId": "num_abc123",
"number": "+34612345678",
"newExpiresAt": "2024-01-15T10:00:00Z",
"extensionPrice": 27.00,
"currency": "€",
"period": "7"
}
}
Переаренда номера
Расчет стоимости переаренды
GET
/api/v1/numbers/{rentId}/re-rent/calculate
✅ Успешный ответ
JSON Response
{
"success": true,
"data": {
"rentId": "num_abc123",
"number": "+34612345678",
"status": "inactive",
"lastExpiry": "2024-01-08T10:00:00Z",
"services": [
{"id": "google", "name": "Google"},
{"id": "whatsapp", "name": "WhatsApp"}
],
"availablePeriods": [
{
"period": "1",
"duration": 1,
"durationUnit": "days",
"description": "1 day",
"price": 5.50,
"currency": "€"
},
{
"period": "7",
"duration": 7,
"durationUnit": "days",
"description": "7 days",
"price": 27.00,
"currency": "€"
}
],
"currency": "€"
}
}
Переарендовать номер
POST
/api/v1/numbers/{rentId}/re-rent
JSON Request
{
"period": "7"
}
JSON Response
{
"success": true,
"data": {
"rentId": "num_abc123",
"number": "+34612345678",
"period": "7",
"price": 27.00,
"currency": "€",
"startsAt": "2024-01-10T10:00:00Z",
"expiresAt": "2024-01-17T10:00:00Z",
"status": "active"
}
}
💡 Переаренда: Позволяет переарендовать номера из истории (статус inactive). Полезно для повторного использования номеров.
Отмена аренды
POST
/api/v1/numbers/{rentId}/cancel
✅ Успешный ответ
JSON Response
{
"success": true,
"message": "Rental cancelled and refunded",
"data": {
"rentId": "num_abc123",
"number": "+34612345678",
"status": "INACTIVE",
"refunded": true,
"refundAmount": 27.00,
"currency": "€"
}
}
💰 Возврат средств: Деньги возвращаются автоматически, если на номер не приходили SMS сообщения.
История SMS
GET
/api/v1/numbers/{rentId}/sms?page=1&limit=50
✅ Успешный ответ
JSON Response
{
"success": true,
"data": [
{
"id": "sms_xyz789",
"from": "Google",
"message": "Your verification code is 123456",
"receivedAt": "2024-01-01T12:00:00Z"
},
{
"id": "sms_abc456",
"from": "WhatsApp",
"message": "WhatsApp code: 789012",
"receivedAt": "2024-01-01T11:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 5,
"totalPages": 1
}
}
История транзакций
GET
/api/v1/wallet/transactions?page=1&limit=50
✅ Успешный ответ
JSON Response
{
"success": true,
"data": [
{
"id": "tx_abc123",
"type": "topup",
"amount": 100.00,
"currency": "EUR",
"balanceBefore": 900.00,
"balanceAfter": 1000.00,
"description": "Пополнение кошелька через Cryptomus",
"metadata": {
"provider": "cryptomus",
"invoiceId": "inv_xyz789"
},
"createdAt": "2024-01-01T10:00:00Z"
},
{
"id": "tx_def456",
"type": "charge",
"amount": -27.00,
"currency": "EUR",
"balanceBefore": 1000.00,
"balanceAfter": 973.00,
"description": "Number rental: +34612345678",
"metadata": {
"number": "+34612345678",
"country": "Spain",
"services": ["Google", "WhatsApp"],
"period": "7",
"rentType": "LONG"
},
"createdAt": "2024-01-01T11:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 50,
"total": 150,
"totalPages": 3
}
}
Webhooks
Мы отправляем уведомления в реальном времени на ваш webhook URL при важных событиях.
События Webhook
- sms.received - Получено новое SMS
- number.expired - Истек срок аренды номера
- balance.low - Баланс ниже порогового значения
- payment.completed - Платеж за пополнение завершен
- payment.failed - Платеж за пополнение не удался
Формат Webhook
JSON Webhook Payload
{
"event": "sms.received",
"data": {
"numberId": "num_def456ghi",
"number": "+34612345678",
"from": "Google",
"message": "Your verification code is: 123456",
"receivedAt": "2024-01-01T10:00:00Z"
},
"webhookId": "wh_789xyz",
"timestamp": "1704106800000",
"signature": "a1b2c3d4e5f6..."
}
Проверка подписи Webhook
Node.js / Express
const crypto = require('crypto');
const express = require('express');
const app = express();
// Middleware для парсинга JSON
app.use(express.json());
function verifyWebhookSignature(secretKey, signature, body) {
// Создаем строку из тела запроса
const payload = JSON.stringify(body);
// Генерируем ожидаемую подпись
const expectedSignature = crypto
.createHmac('sha256', secretKey)
.update(payload)
.digest('hex');
// Сравниваем подписи (защита от timing attacks)
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Endpoint для приема webhook
app.post('/webhooks', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const timestamp = req.headers['x-webhook-timestamp'];
// Проверяем подпись
if (!verifyWebhookSignature(process.env.SECRET_KEY, signature, req.body)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Проверяем timestamp (защита от replay attacks)
const currentTime = Date.now();
const webhookTime = parseInt(timestamp);
const timeDiff = Math.abs(currentTime - webhookTime);
if (timeDiff > 300000) { // 5 минут
return res.status(401).json({ error: 'Request too old' });
}
// Обрабатываем различные события
switch (req.body.event) {
case 'sms.received':
console.log('SMS received:', req.body.data);
// Ваша логика обработки SMS
break;
case 'number.expired':
console.log('Number expired:', req.body.data);
// Логика для истекших номеров
break;
case 'balance.low':
console.log('Low balance alert:', req.body.data);
// Уведомление о низком балансе
break;
default:
console.log('Unknown event:', req.body.event);
}
// Отправляем подтверждение
res.status(200).json({ received: true });
});
// Запуск сервера
app.listen(3000, () => {
console.log('Webhook server running on port 3000');
});
Лимиты запросов
- По умолчанию: 100 запросов за 15 минут с одного IP
- Авторизованные: 1000 запросов за 15 минут на партнера
- Повтор webhook: Максимум 3 попытки с экспоненциальной задержкой
Коды ошибок
Код | Описание | Решение |
---|---|---|
400 | Bad Request - Некорректные параметры | Проверьте формат и обязательные поля запроса |
401 | Unauthorized - Неверный API ключ или подпись | Проверьте API ключ и правильность генерации подписи |
403 | Forbidden - Аккаунт заблокирован | Свяжитесь с поддержкой для разблокировки |
404 | Not Found - Ресурс не найден | Проверьте правильность endpoint и ID ресурса |
429 | Too Many Requests - Превышен лимит | Подождите перед следующим запросом |
500 | Internal Server Error | Попробуйте позже или обратитесь в поддержку |
Формат ответа с ошибкой
JSON Error Response
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Недостаточно средств на балансе",
"details": {
"required": 50.00,
"available": 25.50
}
},
"requestId": "req_abc123xyz"
}
Финансовая модель
💼 Модель Prepaid Wallet
- Создается корпоративный кошелек в системе
- Пополнение оптом со скидкой (5-15%)
- Платежное решение на вашей стороне
- Устанавливаете любые цены для клиентов
- Автоматическое списание по базовым ценам
- Минимальное пополнение: 100€ (для тестов пополнение через Cryptomus от 5€)
Пример расчета
Параметр | Значение |
---|---|
Пополнение | 1000€ |
Скидка | 10% |
Получаете на баланс | 1111€ кредитов |
Ваша выгода | 111€ |
Пример интеграции с полным циклом
JavaScript - Full Example
// Полный пример интеграции Partner API
const crypto = require('crypto');
const axios = require('axios');
class PartnerAPIClient {
constructor(apiKey, secretKey) {
this.apiKey = apiKey;
this.secretKey = secretKey;
this.baseURL = 'https://telegram.smsbot.shop/api/v1';
}
// Генерация подписи для запроса
generateSignature(method, path, body = null) {
const timestamp = Date.now().toString();
const payload = `${timestamp}${method}${path}${JSON.stringify(body || {})}`;
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(payload)
.digest('hex');
return { signature, timestamp };
}
// Выполнение API запроса
async request(method, path, data = null) {
const { signature, timestamp } = this.generateSignature(method, path, data);
try {
const response = await axios({
method,
url: `${this.baseURL}${path}`,
headers: {
'X-Api-Key': this.apiKey,
'X-Signature': signature,
'X-Timestamp': timestamp,
'Content-Type': 'application/json'
},
data
});
return response.data;
} catch (error) {
if (error.response) {
throw new Error(`API Error: ${error.response.data.error}`);
}
throw error;
}
}
// Проверка баланса
async getBalance() {
return this.request('GET', '/wallet/balance');
}
// Пополнение кошелька
async topupWallet(amount, provider = 'cryptomus') {
return this.request('POST', '/wallet/topup', { amount, provider });
}
// Аренда номера
async rentNumber(params) {
return this.request('POST', '/numbers/rent', params);
}
// Получение активных номеров
async getActiveNumbers() {
return this.request('GET', '/numbers/active');
}
// Получение истории SMS
async getSMSHistory(numberId) {
return this.request('GET', `/numbers/${numberId}/sms`);
}
}
// Использование клиента
async function main() {
const client = new PartnerAPIClient(
'pk_live_your_api_key',
'sk_live_your_secret_key'
);
try {
// 1. Проверяем баланс
const balance = await client.getBalance();
console.log('Current balance:', balance.data.total);
// 2. Если баланс низкий, пополняем
if (balance.data.total < 100) {
const topup = await client.topupWallet(500);
console.log('Payment URL:', topup.data.paymentUrl);
}
// 3. Арендуем номер
const rental = await client.rentNumber({
country: 'Spain',
services: ['google', 'whatsapp'],
type: 'LONG',
duration: 24
});
console.log('Rented number:', rental.data.number);
console.log('Expires at:', rental.data.expiresAt);
// 4. Проверяем SMS (polling)
const checkSMS = async () => {
const sms = await client.getSMSHistory(rental.data.numberId);
if (sms.data.messages.length > 0) {
console.log('New SMS:', sms.data.messages);
return true;
}
return false;
};
// Polling каждые 5 секунд
const interval = setInterval(async () => {
const hasNewSMS = await checkSMS();
if (hasNewSMS) {
clearInterval(interval);
}
}, 5000);
} catch (error) {
console.error('Error:', error.message);
}
}
// Запуск
main();