API магазина
Получайте каталог, свои покупки, лицензии, продажи и всё из админ-центра из своего Telegram-бота, сайта или скрипта.
https://amx.run/api/v1/# без ключа - каталог curl https://amx.run/api/v1/products?limit=5 # с ключом - ваши лицензии curl -H "Authorization: Bearer amx_ваш_ключ" https://amx.run/api/v1/me/licenses
Ключи и доступ
Ключ создаётся на сайте: покупатель - в профиле, продавец - в кабинете продавца на вкладке «API», сотрудник - в админ-центре в разделе «API». Ключей может быть несколько, и у каждого свои настройки:
- Права - к каким разделам ключ имеет доступ. Ключ админа никогда не получит больше прав, чем есть у его владельца, и теряет их вместе с владельцем.
- Можно изменять - без этой галочки ключ только читает данные. Безопасный выбор для бота-информатора.
- Разрешённые IP - ключ работает только с этих адресов и подсетей (например, с сервера бота).
- Срок действия и выключатель - ключ можно временно выключить или удалить навсегда.
Ключ передаётся в заголовке. Сам ключ виден только при создании: на сайте хранится его отпечаток, поэтому потерянный ключ нельзя посмотреть - только создать новый.
Authorization: Bearer amx_0123456789abcdef0123456789abcdef01234567
# или
X-Api-Key: amx_0123456789abcdef0123456789abcdef01234567
Не передавайте ключ в адресе (?key=) - такой запрос будет отклонён, чтобы ключ не попал в журналы серверов. Никому не показывайте ключ: с ним действуют от вашего имени.
/keyОтветы и ошибки
Ответ всегда в JSON и UTF-8. Даты - Unix-время в секундах, деньги - числа в валюте магазина (₽).
Изменения - методом POST, поля можно слать формой или JSON-объектом (Content-Type: application/json).
{
"ok": true,
"data": [ … ],
"meta": { "page": 1, "limit": 20,
"total": 57, "pages": 3 }
}
{
"ok": false,
"error": {
"code": "scope_denied",
"message": "У ключа нет доступа «Лицензии»"
}
}
Списки листаются параметрами page (с 1) и limit (1-100).
| HTTP | code | Что значит |
|---|---|---|
| 401 | auth_required invalid_key key_disabled key_expired | Нет ключа, ключ удалён, выключен или истёк |
| 403 | scope_denied read_only wrong_key_kind ip_denied | У ключа нет права, он только для чтения, это метод для другого вида ключа или запрос с неразрешённого IP |
| 404 | not_found | Нет такого метода или записи |
| 405 | method_not_allowed | Изменения - только POST |
| 409 / 422 | разные | Действие сейчас невозможно или поле заполнено неверно - текст в message |
| 429 | rate_limited | Слишком часто - подождите (заголовок Retry-After) |
Лимиты
- Без ключа - до 60 запросов в минуту с одного IP.
- По ключу - до 300 запросов в минуту на ключ.
- После 30 запросов с неверным ключом за 10 минут адрес временно блокируется.
Каждый запрос по ключу записывается в журнал ключа: его видно в настройках ключа на сайте.
Публичные методы
Работают без ключа и с любым ключом.
/ping/stats/categoriesparent_id - id родителя (у основных 0), depth - уровень (0 - основная), products - товаров вместе со всеми подкатегориями./productscategory - slug или id (основная категория - вместе с подкатегориями) · q - поиск · price = free | paid | sale · seller - id продавца · updated_since - Unix-время · sort = new | updated | popular | price_asc | price_desc | name · page, limit/products/{id}sections: install и req - текст, commands (c, d, a), cvars (n, v, d), sounds и sprites (p, d, preview) - списки./products/{id}/reviews/news/news/{id} - новость с текстом./articlescategory - рубрика); /articles/{id} - статья с текстом.Пример товара
{
"id": 2, "name": "Advanced Bans", "url": "https://amx.run/product/2-advanced-bans",
"category": { "id": 1, "slug": "plugins", "name": "Плагины", "parent_id": 0 },
"seller": null, "price": 199, "old_price": 0, "currency": "₽",
"is_free": false, "is_protected": true, "version": "1.2", "author": "amx.run",
"short_desc": "…", "tags": ["бан", "admin"], "image": "https://amx.run/uploads/…",
"rating": { "value": 4.8, "count": 12 }, "sales": 140, "downloads": 310,
"created_at": 1760000000, "updated_at": 1760300000
}Ключ покупателя
Всё - про владельца ключа. Ключ создаётся в профиле.
/meprofile/me/purchasespurchases/me/orderspurchases/me/licenseslicenses/me/licenses/{id} - одна./me/licenses/{id}/unbindlicensesзапись/me/balancebalance/me/notificationsnotificationsunread=1 - только новые · since - новее этого Unix-времени (удобно для опроса раз в минуту)/me/notifications/readnotificationsзаписьids=1,2,3./me/ticketsticketsstatus = open | answered | closed); /me/tickets/{id} - с перепиской./me/ticketsticketsзаписьsubject, text, category, product_id/me/tickets/{id}/replyticketsзаписьtext)./me/tickets/{id}/closeticketsзапись/me/favoritesfavoritesКлюч продавца
Только ваши товары и их покупатели. Ключ создаётся в кабинете продавца на вкладке «API».
/seller/statsseller.sales/seller/productsseller.products/seller/products/{id} - карточка целиком./seller/salesseller.salesfrom, to - Unix-время · product_id · page, limit/seller/licensesseller.licensesproduct_id · status = active | revoked · q - ключ, логин или IP/seller/requestsseller.requestsstatus = pending | approved | rejected | canceled); /seller/requests/{id} - одна./seller/requests/{id}/cancelseller.requestsзапись/seller/reviewsseller.reviewsproduct_id).Добавление товара
Один запрос - и товар готов: поля карточки, описание из .md-файла, разделы страницы, файл товара, обложка и скриншоты.
Ключ админа сохраняет сразу (нужны право ключа products и галочка «Можно изменять»), ключ продавца отправляет товар на проверку модератору (seller.products + «Можно изменять»).
/productsproducts · seller.productsзапись/products/{id}products · seller.productsзаписьПоля
| Поле | Что это |
|---|---|
markdown | Описание товара в .md - текстом или файлом. Разбирается как кнопка «Заполнить из .md»: # Название, первый абзац - краткое описание, таблица «ключ | значение» - версия, цена, требования;
разделы ## Установка, ## Квары, ## Команды, ## Требования, ## Звуки, ## Спрайты, ## Изменения - в свои вкладки, остальные - в описание.
Разделы-заметки («Почему такая цена» …) и строка «Цена» в таблице не публикуются, пока не передан markdown_private=1. Поля ниже важнее разобранных из файла. |
name | Название (для нового - обязательно, если нет markdown) |
category | id, адрес (plugins) или название; если названия повторяются - путь Counter-Strike 1.6 / Плагины. Список - GET /categories |
short_desc | Краткое описание для карточки, до 250 символов |
description, changelog | Описание и общий список изменений - Markdown: заголовки, таблицы, списки, **жирный**, `код` |
price, old_price | Цена (0 - бесплатно) и старая цена для скидки |
version, version_notes | Версия (по умолчанию 1.0) и что нового в ней - для истории версий; notify_buyers=1 - сообщить купившим о новой версии |
requirements, tags | Строкой или списком: ["ReAPI", "AMXX 1.9+"], ["vip", "меню"] |
author | Подпись автора |
active, protected, featured | Показывать на витрине (по умолчанию да), защита лицензией, хит продаж (только админ) |
seller | Только админ: продавец товара - id или логин, 0 - магазин |
sections | Разделы страницы, см. ниже (те же ключи можно передать и на верхнем уровне: cvars, commands …) |
file, image, screenshots[] | Файлы (multipart/form-data): архив товара, обложка, скриншоты (скриншоты - только админ) |
dry_run=1 | Ничего не сохранять - показать, что получится из запроса и .md-файла |
Разделы sections
install и req - текст (Markdown). Таблицы можно передать как удобнее:
"sections": {
"install": "1. Распакуйте архив в cstrike\n2. Допишите wphys в modules.ini",
"commands": ["say /vip - открыть меню", {"command": "amx_givevip", "description": "выдать VIP", "access": "ADMIN_BAN"}],
"cvars": {"vip_hp": "100", "vip_armor": ["50", "броня при спавне"]},
"sounds": ["sound/vip/buy.wav - при покупке"],
"sprites": [{"path": "sprites/vip/crown.spr", "description": "корона над игроком"}]
}
Квары принимаются и текстом .cfg (vip_hp "100" // описание), и строками из исходника: register_cvar, create_cvar, register_clcmd, precache_sound. Раздел заменяется целиком; превью звуков и спрайтов с тем же путём сохраняются.
Примеры
# товар целиком из .md + архив и обложка (ключ админа) curl -H "Authorization: Bearer amx_ключ_админа" \ -F "markdown=@01-wphys-физика-оружия.md" \ -F "category=Counter-Strike 1.6 / Модули" \ -F "file=@wphys.zip" -F "image=@cover.png" \ https://amx.run/api/v1/products # сначала проверить, как разберётся файл curl -H "Authorization: Bearer amx_ключ" -F "markdown=@описание.md" -F "dry_run=1" https://amx.run/api/v1/products # JSON: обновить цену и квары у товара 14 curl -H "Authorization: Bearer amx_ключ" -H "Content-Type: application/json" \ -d '{"price": 349, "old_price": 395, "sections": {"cvars": {"wphys_bounce": "0.4"}}}' \ https://amx.run/api/v1/products/14
Ответ админу: {"ok": true, "data": {карточка товара, "status", "admin_url"}, "meta": {"message", "created", "markdown": {"used": […], "skipped": […]}, "warnings": […]}}.
Продавцу: {"ok": true, "data": {"product_id", "request_id", "status": "pending", …}} - следить за решением можно через GET /seller/requests/{id}.
Ошибка: {"ok": false, "error": {"code": "invalid" | "bad_category" | "no_changes" | "pending" …, "message": "…"}}.
Ключ админа
Ключ админа вызывает те же действия, что кнопки админ-центра, - с теми же проверками и записью в журнал. Действие доступно, если у ключа есть право на раздел, у владельца есть право на действие, а для изменений включена галочка «Можно изменять». Настройки сайта через API недоступны.
/admin/admin/{действие}/admin/orders, /admin/user_get?id=5, /admin/tickets?status=open./admin/{действие}запись/admin/ticket_reply с id и text, /admin/seller_request_decide с id и decision=approve.Ответ - в формате админ-центра: {"ok": true, …} или {"ok": false, "msg": "…"}.
dashboard
statsdash_moreattentionproducts
productsproduct_getproduct_toggleproduct_saveproduct_deleteproduct_bulkproduct_duplicateversion_deleteversion_restoreversion_notepfilespfile_getpfile_previewpfile_savepfile_deletepfile_sortpfile_scanpfile_importcategories
categoriescategory_savecategory_deletecategory_sortcategory_togglereviews
reviewsreview_statusreview_deletereview_bulkreview_replyreview_editorders
ordersorder_refundpromospromo_savepromo_deleteusers
usersusers_summaryuser_getuser_saveuser_avataruser_grantuser_revokeuser_logout_alluser_impersonateuser_impersonate_stoparticles
articlesarticle_statusarticle_pinarticle_deletereports
reportreport_exportbroadcast
broadcastsbroadcast_countbroadcast_sendbroadcast_recallmoderation
seller_requestsseller_request_getseller_request_fileseller_request_decidepages
pagespage_getpage_savepage_togglepage_deletepage_accesspage_access_savesupport
ticketsticket_getticket_replyticket_updateticket_statusticket_deleterepliesreply_savereply_deletenews
newsnews_savenews_deletelog
logactivityactivity_sessionactivity_ipactivity_cleargroups
groupsgroup_getgroup_savegroup_togglegroup_sortgroup_duplicategroup_deletegroup_member_addgroup_member_removepayments
paymentspayment_confirmpayment_cancelpayment_synccardpayscardpay_attachcardpay_ignorerobot_testlicenses
licenseslicense_getlicense_revokelicense_unbindlicense_savelicense_regenlicense_transferlicense_issuelicense_deletelicense_bulklicense_checkslicense_productslicense_sync_productlicense_log_clearlicense_ip_seenlicense_ip_purgelicense_exportmodule_infomodule_uploadmodule_deleteчтение (GET) изменение (POST, нужна запись)
Примеры
<?php
$key = 'amx_ваш_ключ';
$ch = curl_init('https://amx.run/api/v1/me/licenses');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key],
]);
$r = json_decode(curl_exec($ch), true);
if (!$r['ok']) exit($r['error']['message']);
foreach ($r['data'] as $lic) echo $lic['product']['name'], ': ', $lic['key'], PHP_EOL;
import requests
API = "https://amx.run/api/v1"
H = {"Authorization": "Bearer amx_ваш_ключ"}
r = requests.get(f"{API}/seller/stats", headers=H, timeout=10).json()
if r["ok"]:
s = r["data"]
print(f"Сегодня: {s['sales_today']} продаж на {s['revenue_today']} {s['currency']}")
else:
print(r["error"]["message"])
const API = 'https://amx.run/api/v1';
const r = await fetch(`${API}/products?sort=updated&limit=5`).then(x => x.json());
r.data.forEach(p => console.log(p.name, p.version, p.url));
# Бот присылает в Telegram новые заказы и обращения (ключ админа: orders, support - только чтение)
import time, requests
API = "https://amx.run/api/v1"
H = {"Authorization": "Bearer amx_ключ_админа"}
TG = "https://api.telegram.org/bot<ТОКЕН_БОТА>/sendMessage"
CHAT = "<ID_ЧАТА>"
seen = set()
while True:
r = requests.get(f"{API}/admin/tickets", params={"status": "open"}, headers=H, timeout=15).json()
for t in r.get("rows", []):
if t["id"] not in seen:
seen.add(t["id"])
requests.post(TG, data={"chat_id": CHAT, "text": f"🎧 #{t['id']} {t['subject']}"})
time.sleep(30)
Для бота делайте отдельный ключ: только нужные права, без записи и с IP сервера бота. Если ключ утечёт - удалите его, остальные продолжат работать.