Econoverse Public API

Version 1.0 · Base URL: https://econoverse.ring-team.ru/api/v1
1. Обзор 2. Авторизация 3. Сценарий привязки пользователя 4. Endpoints 5. Коды ошибок 6. Пример клиента

1. Обзор

Econoverse Public API — это HTTP REST API, позволяющий сторонним приложениям подключаться к экономике Econoverse (Telegram-бот): получать баланс пользователя, историю транзакций, совершать переводы, взаимодействовать с компаниями.

2. Авторизация

Используется двухуровневая схема:

  1. API key + API secret — выдаются владельцу приложения ботом по команде /newapp. Нужны только для обмена кода привязки на токен.
  2. Access token — выдаётся по коду привязки пользователя. Не истекает, но может быть отозван.

Заголовки всех запросов (кроме oauth/exchange):

X-Api-Key: eco_pk_XXXXXXXXXXXXXXXXXXXX
Authorization: Bearer eco_ut_YYYYYYYYYYYYYYYYYYYY
⚠️ API secret никогда не передаётся клиентскими запросами. Используйте его только на вашем бэкенде при обмене кода на токен.

3. Сценарий привязки пользователя

  1. Разработчик в Telegram пишет боту: /newapp My Cool App → получает api_key и api_secret.
  2. Пользователь в Telegram пишет боту: /mycode → получает 8-символьный код (действует 10 минут).
  3. Пользователь вводит этот код в вашем приложении.
  4. Приложение отправляет код на POST /api/v1/oauth/exchange вместе с api_key и api_secret.
  5. API возвращает access_token — сохраните его для пользователя.
  6. Все дальнейшие запросы от имени пользователя делайте с заголовками X-Api-Key и Authorization: Bearer.

4. Endpoints

POST/api/v1/oauth/exchange

Обменяет код привязки на токен доступа пользователя. Заголовки авторизации не требуются.

Body

ПолеТипОписание
api_keystringПубличный ключ приложения
api_secretstringСекрет приложения
codestring8-символьный код от пользователя

Ответ

{
  "ok": true,
  "access_token": "eco_ut_XXXXXXXXXXXXXX",
  "token_type": "Bearer",
  "app": {"id": 12, "name": "My Cool App"},
  "user": {"id": 3, "telegram_id": 123456, "username": "alice"}
}
GET/api/v1/me

Профиль текущего пользователя, включая баланс и компанию.

{
  "ok": true,
  "user": {
    "id": 3,
    "telegram_id": 123456,
    "username": "alice",
    "balance": 1250.0,
    "is_banned": false,
    "warnings": 0,
    "join_date": "2026-05-10T12:00:00"
  },
  "company": {"id": 4, "name": "RingCorp", "is_owner": true, "balance": 8000.0}
}
GET/api/v1/balance

Текущий баланс пользователя.

{"ok": true, "balance": 1250.0, "currency": "RUB", "username": "alice"}
GET/api/v1/history?limit=30

История транзакций. Параметр limit: 1–500 (по умолчанию 30).

{
  "ok": true,
  "items": [
    {
      "id": 88,
      "direction": "in",
      "peer": "bob",
      "amount": 500,
      "created_at": "2026-08-10T14:22:11",
      "comment": "payment"
    }
  ]
}
POST/api/v1/transfer

Перевод другому пользователю по username.

Body

ПолеТипОписание
to_usernamestringUsername получателя (без @)
amountnumberСумма в ₽ (> 0)
commentstring?Комментарий (до 120 символов)
{
  "ok": true,
  "transaction": {
    "amount": 100,
    "to_username": "bob",
    "comment": "for coffee",
    "new_balance": 1150.0
  }
}
GET/api/v1/company

Компания текущего пользователя и её участники. Если пользователь вне компании, вернётся company: null.

POST/api/v1/company/transfer

Перевод на баланс компании по названию.

Body

ПолеТипОписание
company_namestringТочное название компании
amountnumberСумма (> 0)
commentstring?Комментарий
POST/api/v1/token/revoke

Приложение отзывает свой токен для текущего пользователя. После отзыва потребуется новый код привязки.

5. Коды ошибок

HTTPcodeЗначение
400bad_request, invalid_amount, missing_receiver, missing_code, self_transferПроблема в параметрах
401invalid_api_key, invalid_api_secret, missing_token, invalid_tokenОшибка авторизации
402insufficient_fundsНедостаточно средств
403user_bannedПользователь заблокирован
404code_not_found, receiver_not_found, company_not_found, user_not_foundРесурс не найден
409code_usedКод уже был использован
410code_expiredКод устарел

6. Пример клиента (JavaScript)

const BASE = 'https://econoverse.ring-team.ru/api/v1';

// 1) Обмен кода на токен (только на вашем бэкенде!)
async function link(code) {
  const r = await fetch(BASE + '/oauth/exchange', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({
      api_key: process.env.ECO_API_KEY,
      api_secret: process.env.ECO_API_SECRET,
      code,
    }),
  });
  return r.json();
}

// 2) Запросы от имени пользователя
async function apiCall(path, method='GET', body=null, userToken) {
  return fetch(BASE + path, {
    method,
    headers: {
      'Content-Type': 'application/json',
      'X-Api-Key': process.env.ECO_API_KEY,
      'Authorization': 'Bearer ' + userToken,
    },
    body: body ? JSON.stringify(body) : undefined,
  }).then(r => r.json());
}

const me = await apiCall('/me', 'GET', null, userToken);
const tx = await apiCall('/transfer', 'POST', {to_username: 'bob', amount: 100, comment: 'hi'}, userToken);