Для разработчиков

API документация

Принимайте платежи через счета и выводите средства по API-ключу с HMAC-подписью.

Базовый URLhttps://devonesite.site/api

01 С чего начать

API OneSix позволяет принимать платежи через счета (invoice) и выводить средства (transfer) программно. Запросы авторизуются API-ключом проекта с HMAC-подписью.

Интеграция строится в три шага:

  1. Создайте проект в личном кабинете и подтвердите владение доменом (DNS).
  2. Получите API-ключ проекта: пару id + secret.
  3. Подписывайте запросы ключом (HMAC-SHA256) и вызывайте методы API.
text
Registration → Project (pending) → Domain verification → Moderation → Project (active) → API key → API requests

API-ключ начинает работать только когда и ключ, и проект находятся в статусе active. Пока проект на модерации (pending) или отклонён (rejected), запросы по ключу не проходят.

Форматы идентификаторов

СущностьФормат
id проекта, счёта, API-ключаUUID как есть (aabbccdd-...)
user.id, logo_img_id, id свопа в conversions, id операцииEncoded string (как в остальном кабинете)

02 Подпись запросов (HMAC)

Все запросы к публичному API авторизуются по API-ключу и подписываются алгоритмом HMAC-SHA256. Сессия (cookie / Authorization: Bearer) для API не используется.

Ключи

КлючГде взятьДля чего
id (X-API-Key-ID)Кабинет → проект → API-ключи, поле idИдентификатор ключа в заголовке
key (secret)Там же, поле key (hex, 64 символа)Секрет для вычисления подписи

У проекта один активный ключ (status: active). Ротации ключей пока нет. Секрет key возвращается методом GET /api/projects/{project_id}/api-keys/, храните его в безопасном месте.

Заголовки запроса

ЗаголовокОписание
X-API-Key-IDUUID ключа (поле id, не секрет)
X-TimestampUnix timestamp в секундах. Окно ±15 секунд от серверного времени
X-SignatureHMAC-SHA256 в hex
Content-Typeapplication/json для запросов с телом

Подпись обязательна для всех методов публичного API (GET и POST).

Алгоритм подписи

Шаг 1. Соберите объект данных:

json
{
  "params": "url_encoded_query_string",
  "body": {},
  "path": "/api/invoice/"
}
  • params: query-строка как в URL, без ? (например project_id=...&page=1). Для запроса без query это пустая строка "".
  • body: распарсенный JSON тела запроса. Для GET-запросов без тела это пустой объект {}.
  • path: путь запроса со слешами, включая префикс /api (например /api/invoice/).

Шаг 2. Сериализуйте объект строго с сортировкой ключей:

python
json.dumps(data, separators=(",", ":"), sort_keys=True)

sort_keys=True обязателен. Подписывается объект после JSON-парсинга тела, а не сырая строка.

Шаг 3. Вычислите подпись:

text
payload   = str(timestamp) + json_string
signature = HMAC-SHA256(key=secret, message=payload).hexdigest()

Шаг 4. Передайте X-API-Key-ID, X-Timestamp, X-Signature в заголовках.

Важно

  • X-Timestamp должен быть в пределах ±15 секунд от серверного времени. При расхождении часов синхронизируйтесь через GET /api/-/time/.
  • Подпись одноразовая. Повтор того же X-Signature вернёт 401 Signature already used!. Для каждого запроса нужны новый timestamp и новая подпись.
  • TOTP (2FA) на пути API не требуется.
  • Если у ключа задан список разрешённых IP, запросы принимаются только с них.

Генерация подписи

import hmac, hashlib, json, time

def sign(secret: str, timestamp: int, data: dict) -> str:
    s = json.dumps(data, separators=(",", ":"), sort_keys=True)
    payload = f"{timestamp}{s}"
    return hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()

secret     = "<key>"
api_key_id = "<uuid>"
path       = "/api/invoice/"
params     = ""
body       = {
    "name": "Order 1",
    "target_amount": 100,
    "is_termless": True,
    "is_payer_comission": True,
    "description": "",
    "private_description": "",
}

ts   = int(time.time())
data = {"params": params, "body": body, "path": path}
signature = sign(secret, ts, data)

headers = {
    "X-API-Key-ID": api_key_id,
    "X-Timestamp": str(ts),
    "X-Signature": signature,
    "Content-Type": "application/json",
}
$secret = "<key>";
$path   = "/api/invoice/";
$params = "";
$body   = [
    "name"               => "Order 1",
    "target_amount"      => 100,
    "is_termless"        => true,
    "is_payer_comission" => true,
    "description"        => "",
    "private_description"=> "",
];

$data = ["params" => $params, "body" => $body, "path" => $path];
ksort($data); // params, path, body -> sort_keys=True
$json      = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$timestamp = time();
$signature = hash_hmac("sha256", $timestamp . $json, $secret);
const crypto = require("crypto");

function sign(secret, timestamp, data) {
  // sort top-level keys, compact JSON without spaces
  const ordered = {};
  Object.keys(data).sort().forEach((k) => (ordered[k] = data[k]));
  const s = JSON.stringify(ordered);
  return crypto.createHmac("sha256", secret).update(`${timestamp}${s}`).digest("hex");
}

const secret = "<key>";
const data = {
  params: "",
  body: { name: "Order 1", target_amount: 100, is_termless: true, is_payer_comission: true, description: "", private_description: "" },
  path: "/api/invoice/",
};
const ts = Math.floor(Date.now() / 1000);
const signature = sign(secret, ts, data);

В JS следите, чтобы JSON.stringify давал тот же результат, что и Python json.dumps(..., separators=(",",":"), sort_keys=True): без пробелов и с сортировкой ключей на всех уровнях. Для вложенных объектов в body при необходимости сортируйте ключи рекурсивно.

Примеры запросов

# params = ""  (no query)
# body   = {}  (no body)
# path   = "/api/invoice/my/<invoice_id>/"
# data   = {"body":{},"params":"","path":"/api/invoice/my/<invoice_id>/"}

curl "https://devonesite.site/api/invoice/my/<invoice_id>/" \
  -H "X-API-Key-ID: <UUID>" \
  -H "X-Timestamp: 1718659200" \
  -H "X-Signature: <hex>"
curl "https://devonesite.site/api/invoice/" \
  -X POST \
  -H "Content-Type: application/json" \
  -H "X-API-Key-ID: <UUID>" \
  -H "X-Timestamp: 1718659200" \
  -H "X-Signature: <hex>" \
  -d '{"name":"Order 1","target_amount":100,"is_termless":true,"is_payer_comission":true,"description":"","private_description":""}'

Серверное время

GET/api/-/time/Без авторизацииСерверное время (unix)

Возвращает текущее серверное время (unix, число). Используйте для синхронизации X-Timestamp, если часы клиента могут расходиться более чем на 15 секунд.

Какие методы принимают API-ключ

АвторизацияМетоды
API-ключ (HMAC)POST /api/invoice/ · GET /api/invoice/my/{invoice_id}/ · POST /api/gw/transfer/
Без авторизацииGET /api/invoice/{invoice_id}/ · GET /api/gw/currencies/ · GET /api/gw/currencies/rates/ · GET /api/gw/fees/ · GET /api/gw/fees/calculate/ · GET /api/-/time/
Только сессия (кабинет)Управление проектами, верификация, api-keys, operations, conversions, списки с project_id

Любой метод вне списка «API-ключ (HMAC)» при вызове с ключом вернёт 401 API key not allowed for this endpoint!.

Ошибки подписи и авторизации

Код 401, detailПричина
Invalid API key!Неверный X-API-Key-ID
API key deactivated!Ключ архивирован или проект не active
Invalid signature!Подпись не сошлась (проверьте сериализацию, path, timestamp)
Signature already used!Повтор одноразовой подписи
API key not allowed for this endpoint!Метод не поддерживает авторизацию по ключу
Token not provided!Не передана авторизация

03 Счета (Invoice)

Счёт - это запрос на оплату фиксированной суммы. После создания возвращается адрес для оплаты и платёжная страница. Сумма указывается в фиате (target_amount), оплата поступает в USDT по текущему курсу (rate_pair: USDT_RUB, rate приходит в ответе).

POST/api/invoice/API-ключСоздать счёт
GET/api/invoice/my/{invoice_id}/API-ключСвой счёт (с private_description)
GET/api/invoice/{invoice_id}/Без авторизацииПубличная страница счёта

POST /api/invoice/

Тело запроса (InvoiceCreateDTO)

ПолеТипОбяз.Описание
namestring✔Название. Мин. 3 символа, латиница/кириллица
target_amountnumber✔Сумма к оплате. Минимум 0.1
is_termlessboolБессрочный счёт. По умолчанию false
deadlinedatetime (ISO 8601)Срок счёта. Обязателен при is_termless=false; при is_termless=true должен быть null или не передан
is_payer_comissionboolКомиссию платит плательщик. По умолчанию true
descriptionstringПубличное описание
private_descriptionstringПриватное описание (видно только вам)
imgstring | nullИзображение счёта
project_iduuid | nullНа этом методе не используется. По ключу project_id подставляется из проекта ключа автоматически

По API-ключу 2FA не требуется.

Ответ (MyInvoiceDTO)

ПолеТипОписание
iduuidID счёта
addressstringАдрес для оплаты
namestringНазвание
imgstring | nullИзображение
descriptionstringПубличное описание
private_descriptionstringПриватное описание
statusenumopened / expired / executed / closed
target_amountnumberСумма к оплате
current_amountnumberОплачено на текущий момент
comissionnumberКомиссия
is_termlessboolБессрочный
is_payer_comissionboolКомиссию платит плательщик
deadlinedatetime | nullСрок
rate_pairenumПара курса (USDT_RUB, ALTYN_USDT_RUB)
ratenumberКурс на момент создания
created_atdatetimeДата создания
closed_atdatetime | nullДата закрытия
project_iduuid | nullПроект счёта

GET /api/invoice/my/{invoice_id}/

Возвращает ваш счёт (MyInvoiceDTO, с private_description). По ключу действует дополнительный фильтр: доступны только счета проекта этого ключа.

GET /api/invoice/{invoice_id}/

Публичная страница счёта, без авторизации. Возвращает PublicInvoiceDTO: то же, что MyInvoiceDTO, но без private_description и project_id. Используется для платёжной страницы.

Статусы счёта

statusОписание
openedОткрыт, ожидает оплаты
executedОплачен (сумма набрана)
expiredИстёк срок без полной оплаты
closedЗакрыт

Отслеживание статуса. Исходящих вебхуков о смене статуса в текущей версии API нет. Актуальный статус запрашивайте опросом GET /api/invoice/my/{invoice_id}/ (status, current_amount).

04 Выводы (Transfer)

Создание вывода средств на внешний блокчейн-адрес.

POST/api/gw/transfer/API-ключСоздать вывод

POST /api/gw/transfer/

Тело запроса (WithdrawalCreateDTO)

ПолеТипОбяз.Описание
symbol_idstring✔Идентификатор символа (валюта в сети), например USDTTRC20. Список: GET /api/gw/currencies/
to_addressstring✔Адрес получателя
amountnumber✔Сумма. Больше 0

По API-ключу 2FA не требуется.

Ответ: JSON-объект транзакции вывода (тип, статус, идентификатор операции).

Как и у счетов, вебхуков о завершении вывода нет. Отслеживайте статус опросом операций проекта (GET /api/projects/{project_id}/operations/) или в кабинете.

05 Справочные данные

Публичные методы без авторизации, полезные при интеграции.

GET/api/gw/currencies/Без авторизацииСписок валют и символов
GET/api/gw/currencies/rates/Без авторизацииКурсы валютных пар
GET/api/gw/fees/Без авторизацииКомиссии и лимиты по символам
GET/api/gw/fees/calculate/Без авторизацииРасчёт комиссии по сумме
GET/api/-/time/Без авторизацииСерверное время (unix)

GET /api/gw/currencies/

Список поддерживаемых валют. Используйте поле symbol как значение symbol_id при создании вывода.

Query: search - фильтр. Ответ пагинированный (data[], pages_count, current_page, total).

Каждый элемент (CurrencyDTO):

ПолеОписание
symbolИдентификатор символа для API (symbol_id)
short_nameКраткое название валюты
nameПолное название
blockchainСеть (id, name, ссылки на explorer)
contract_addressАдрес контракта токена, если есть
precisionТочность
is_activeДоступен ли символ
logo_urlЛоготип
min_deposit_confirms / min_withdrawal_confirmsПодтверждений для депозита / вывода

GET /api/gw/fees/

Комиссии и минимальные суммы по символам (GwFeeDTO[]):

ПолеОписание
symbol_idИдентификатор символа
min_deposit_amountМинимальный депозит
min_withdrawal_amountМинимальный вывод
deposit_fee_amount / deposit_fee_percentageКомиссия депозита (фикс / процент)
withdrawal_fee_amount / withdrawal_fee_percentageКомиссия вывода (фикс / процент)
swap_fee_amount / swap_fee_percentageКомиссия конверсии
swap_from_min_amount / swap_to_min_amountМинимумы для конверсии

GET /api/gw/fees/calculate/

Расчёт комиссии для конкретной суммы.

Query (все обязательны): amount, operation_type (deposit / withdrawal / swap), symbol_id.

Ответ (GwServiceFeeCalculationDTO): symbol_id, operation_type, amount, fee_amount, net_amount, gross_amount.

GET /api/gw/currencies/rates/

Курсы валютных пар (CurrencyRateDTO[]):

ПолеОписание
from_symbol_idСимвол/код исходной валюты
to_symbol_nameКод валюты котировки
valueКурс
created_atВремя обновления

06 Управление проектами

Создание и настройка проектов, верификация домена и выпуск ключей выполняются из личного кабинета по сессии (cookie или Authorization: Bearer), без API-ключа. Этот раздел нужен, если вы автоматизируете кабинет; для обычной интеграции достаточно пройти шаги в интерфейсе.

Проекты

GET/api/projects/СессияСписок своих проектов. Без status - все, кроме disabled. Фильтр ?status=pending|active|rejected|disabled
POST/api/projects/СессияСоздать проект (статус pending). Ключ создаётся сразу, но в ответе его нет: берите через api-keys
GET/api/projects/{project_id}/СессияКарточка проекта
PATCH/api/projects/{project_id}/СессияИзменить проект (все поля необязательные). Нельзя править disabled
DELETE/api/projects/{project_id}/СессияМягкое удаление → status: disabled. Ответ {"status": true}

POST /api/projects/ (ProjectCreateDTO)

ПолеТипОбяз.Описание
namestring✔3-128 символов, уникально у пользователя
categoryenum✔goods / services / digital / other
site_urlstring (uri)✔http(s), публичный хост (не localhost и не приватный IP)
contact_telegramstring✔1-64 символа
descriptionstring | nullОписание

PATCH /api/projects/{project_id}/ (ProjectUpdateDTO): category, description, logo_img_id (encoded id вашей картинки), brand_color (# + 6 hex). Логотип должен принадлежать вам.

Карточка проекта (ProjectDTO)

json
{
  "id": "uuid",
  "public_id": "aabbccddeeff",
  "name": "Shop",
  "status": "pending",
  "category": "goods",
  "site_url": "https://shop.example.com",
  "contact_telegram": "@shop",
  "description": null,
  "logo_img_id": null,
  "brand_color": null,
  "is_site_verified": false,
  "verify_method": null,
  "verify_token": null,
  "verified_at": null,
  "rejected_reason": null,
  "created_at": "...",
  "updated_at": "..."
}

status: pending → active (после верификации и одобрения модератором) / rejected / disabled.

Верификация домена (DNS)

POST/api/projects/{project_id}/verification/СессияНачать верификацию. Только при status=pending и is_site_verified=false
POST/api/projects/{project_id}/verification/check/СессияПроверить TXT-запись (без тела)

POST /verification/: тело {"method": "dns"}. Ответ:

json
{
  "method": "dns",
  "verify_token": "<hex>",
  "instruction": "Add a TXT record for shop.example.com with value j1ulwfmkyj0-site-verification=<token>"
}

Покажите пользователю: добавить TXT-запись на хост из site_url со значением j1ulwfmkyj0-site-verification=<verify_token>.

POST /verification/check/: если TXT найден, is_site_verified=true, заполняется verified_at, статус остаётся pending (ждёт модерацию). Если домен уже подтверждён, вернётся 200 без ошибки. Если TXT нет, вернётся 400 Site verification failed.

API-ключи проекта

GET/api/projects/{project_id}/api-keys/СессияКлючи проекта с секретом
json
[
  {
    "id": "key uuid, this is X-API-Key-ID",
    "key": "hex secret, 64 chars",
    "status": "active",
    "created_at": "...",
    "archived_at": null
  }
]

status: active / archived. У проекта один активный ключ. Ротации пока нет.

Операции и конверсии проекта

GET/api/projects/{project_id}/operations/?page=1&per_page=10СессияТранзакции проекта
GET/api/projects/{project_id}/conversions/?page=1&per_page=10СессияСвопы проекта

Пагинация: page с 1, per_page по умолчанию 10. В ответе current_page = page - 1 (с нуля), pages_count, total, data[].

Операция (ProjectAdminTransactionDTO): id, type, subject (usdt/rub), symbol_id, is_incoming, amount, state (created/pending/dirty_lock/executed/cancelled), tx_hash, description, executed_at, created_at, project_id.

Конверсия (SwapOrderResponseDTO): id, from_symbol_id, to_symbol_id, from_amount, to_amount, rate, status (created/processing/executed/cancelled/failed), created_at, project_id, user.

Списки в кабинете с фильтром проекта

http
GET /api/invoice/?project_id=<uuid>
GET /api/transaction/?project_id=<uuid>
GET /api/gw/swap_order/?project_id=<uuid>

07 Коды ошибок

Проекты и верификация (400)

detailПричина
Project with this name already existsИмя проекта занято
site_url must be an http(s) URLНеверный формат URL
site host must be a public addressХост - localhost / приватный IP
brand_color must be a HEX color like #1A2B3CНеверный цвет
Image not foundКартинка логотипа не найдена
Project is disabledПроект отключён, правка запрещена
Project is not pending verificationВерификацию нельзя начать в текущем статусе
Site is already verifiedДомен уже подтверждён
Verification is not startedПроверка до начала верификации
Site verification failedTXT-запись не найдена
Project is not pendingДействие доступно только для pending
Site is not verifiedДомен не подтверждён

Авторизация и подпись (401)

detailПричина
Invalid API key!Неверный X-API-Key-ID
API key deactivated!Ключ архивирован или проект не active
Invalid signature!Подпись не сошлась (проверьте сериализацию, path, timestamp)
Signature already used!Повтор одноразовой подписи
API key not allowed for this endpoint!Метод не поддерживает авторизацию по ключу
Token not provided!Не передана авторизация

Не найдено (404)

detailПричина
Project not foundПроект не найден / недоступен
Invoice not foundСчёт не найден
Готовы начать?
Создайте проект в личном кабинете, получите API-ключ и подключите приём платежей.
Открыть кабинет