Docs Документация
Max Systems Max Systems
API Status: Operational Статус API: Работает

KeyForge Developer API

KeyForge API для разработчиков

Integrate digital key distribution into your platform. Two API versions, one powerful engine.

Интегрируйте дистрибуцию цифровых ключей в свою платформу. Два API — один мощный движок.

v1

Legacy API v1

Query-parameter based API with 6 action handlers. Battle-tested, stable, backward compatible. Ideal for payment terminals and kiosks.

API на query-параметрах с 6 обработчиками действий. Проверенный временем, стабильный. Идеален для платёжных терминалов и киосков.

6 Actions
v2

REST API v2

Full RESTful API with JWT auth, comprehensive CRUD for all entities, pagination, filtering, and export capabilities.

Полноценный RESTful API с JWT авторизацией, CRUD для всех сущностей, пагинацией, фильтрами и экспортом.

40+ Endpoints

Authentication Аутентификация

How to authenticate your requests depending on the API version.

Как аутентифицировать запросы в зависимости от версии API.

Legacy API v1

Authentication uses a settings query parameter containing a JSON object with your partner login and password. Passwords are validated using bcrypt hashing.

Аутентификация через query-параметр settings, содержащий JSON-объект с login и password партнёра. Пароли проверяются через bcrypt-хеширование.

Example Request
GET /public/json/web.service.2024.php
  ?action=1
  &settings={"login":"your_login","password":"your_password","lang":"en"}
FieldTypeDescriptionОписание
login* string Partner login (issued upon registration) Логин партнёра (выдаётся при регистрации)
password* string Partner password (bcrypt-verified) Пароль партнёра (проверяется через bcrypt)
lang string Response language: en, ru, az Язык ответа: en, ru, az
currency string Currency override: AZN, USD, EUR, TRY, RUB Валюта: AZN, USD, EUR, TRY, RUB

REST API v2

Uses JWT Bearer tokens. Obtain a token via the login endpoint, then include it in every request header.

Используются JWT Bearer токены. Получите токен через эндпоинт авторизации, затем передавайте его в заголовке запроса.

Authorization Header
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Base URLs Базовые URL

Legacy API v1
https://admin.pay.net.az/api/v1/partners/service
Alternative path
Альтернативный путь
https://admin.pay.net.az/public/json/web.service.2024.php
REST API v2
https://admin.pay.net.az/api
Both API versions run on the same server. Legacy v1 is maintained for backward compatibility. New integrations should use REST API v2. Обе версии API работают на одном сервере. Legacy v1 поддерживается для обратной совместимости. Новые интеграции рекомендуем делать через REST API v2.

Error Handling Обработка ошибок

Legacy API v1

Returns a JSON object with code and message. Code "0" means success. Any other code indicates an error.

Возвращает JSON с полями code и message. Код "0" — успех. Любой другой код — ошибка.

Error Response Example
{
  "code": "0-3",
  "message": "PARTNER_INACTIVE"
}

Common Error Codes (prefix 0-X)

Общие коды ошибок (префикс 0-X)

CodeMessageDescriptionОписание
0-1INVALID_REQUESTMissing required query parametersОтсутствуют обязательные параметры
0-2LOGIN_MISSINGMissing 'login' in settingsОтсутствует 'login' в settings
0-3PASSWORD_MISSINGMissing 'password' in settingsОтсутствует 'password' в settings
0-10ACCESS_DENIEDInvalid login or passwordНеверный логин или пароль
0-11PARTNER_BLOCKEDPartner account is blockedАккаунт партнёра заблокирован
0-7INVALID_CURRENCYUnsupported currency codeНеподдерживаемый код валюты
0SUCCESSRequest completed successfullyЗапрос выполнен успешно

REST API v2

Uses standard HTTP status codes with a JSON body containing success boolean and error message.

Использует стандартные HTTP коды с JSON-ответом, содержащим success (boolean) и error (сообщение).

v2 Error Response
{
  "success": false,
  "error": "Unauthorized: Invalid or expired token"
}

Legacy API v1 STABLE

Query-parameter based API designed for payment terminals, kiosks, and simple integrations. All requests use GET method with JSON-encoded data parameter.

API на query-параметрах, разработанный для платёжных терминалов, киосков и простых интеграций. Все запросы через GET с JSON-параметром data.

Request Format

Формат запроса

Base URL
GET /public/json/web.service.2024.php
    ?action={1-6}
    &settings={"login":"...","password":"...","lang":"en","currency":"AZN"}
    &data={url_encoded_json}
ParameterTypeDescriptionОписание
action* integer Action number (1-6) Номер действия (1-6)
settings* json string JSON with login, password, lang, currency JSON с login, password, lang, currency
data json string URL-encoded JSON with action-specific parameters URL-кодированный JSON с параметрами действия

GET  Action 1 — Get Products Получить продукты

Returns the catalog of available products accessible to the partner. Products are filtered by partner's access permissions.

Возвращает каталог доступных продуктов для партнёра. Продукты фильтруются по правам доступа партнёра.

GET /public/json/web.service.2024.php?action=1

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=1" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode "lang=en"

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS",
  "data": [
    {
      "productId": "42",
      "productName": "Xbox Game Pass Ultimate 1 Month",
      "imageUrl": "https://admin.pay.net.az/uploads/products/xbox-gp.png",
      "thumbnailUrl": "https://admin.pay.net.az/uploads/products/thumb/xbox-gp.png"
    },
    {
      "productId": "58",
      "productName": "Steam Wallet $50",
      "imageUrl": "https://admin.pay.net.az/uploads/products/steam-50.png",
      "thumbnailUrl": null
    }
  ]
}

Error Codes

Коды ошибок

CodeMessage
1-1Failed to retrieve products

GET  Action 2 — Get Packages Получить пакеты

Returns available packages for a specific product, with prices in the requested currency.

Возвращает доступные пакеты для конкретного продукта с ценами в запрошенной валюте.

GET /public/json/web.service.2024.php?action=2

Data Parameter

FieldTypeDescription
product* string Product ID from Action 1

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=2" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode 'data={"product":"42"}' \
  --data-urlencode "currency=AZN"

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS",
  "data": [
    {
      "packageId": "101",
      "packageName": "Xbox Game Pass Ultimate 1 Month (TR)",
      "packagePrice": "25.50",
      "currency": "AZN"
    }
  ]
}

Error Codes

CodeMessage
2-1Invalid JSON in 'data' parameter
2-2Missing 'product' in data
2-3Invalid Product ID
2-9System error

GET  Action 3 — Reserve Key Зарезервировать ключ

Reserves a digital key from a package. The key is locked for 10 minutes. Must be confirmed (Action 4) or cancelled (Action 5) within this time.

Резервирует цифровой ключ из пакета. Ключ блокируется на 10 минут. Необходимо подтвердить (Action 4) или отменить (Action 5) в течение этого времени.

Important: Reserved keys are automatically released after 10 minutes if not confirmed. Always confirm or cancel reservations promptly. Важно: Зарезервированные ключи автоматически освобождаются через 10 минут. Всегда подтверждайте или отменяйте резервации своевременно.
GET /public/json/web.service.2024.php?action=3

Data Parameter

FieldTypeDescription
package* string Package ID from Action 2

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=3" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode 'data={"package":"101"}' \
  --data-urlencode "currency=AZN"

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS",
  "data": {
    "keyId": "8847",
    "keyText": "XXXX-YYYY-ZZZZ-WWWW",
    "serialNumber": "SN-12345",
    "price": "25.50",
    "currency": "AZN"
  }
}

Error Codes

CodeMessage
3-1Invalid JSON in 'data' parameter
3-2Missing 'package' in data
3-3Package not found or inactive
3-4No available keys in stock
3-5Key reservation failed

GET  Action 4 — Confirm Sale Подтвердить продажу

Confirms the purchase of a previously reserved key. Creates an order record and marks the key as sold. The package auto-deactivates if this was the last key.

Подтверждает покупку зарезервированного ключа. Создаёт запись заказа и помечает ключ как проданный. Пакет автоматически деактивируется если это был последний ключ.

GET /public/json/web.service.2024.php?action=4

Data Parameter

FieldTypeDescription
key*stringKey ID from Action 3
order*stringYour order ID (max 200 chars)
currencystringCurrency code (default: AZN)

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=4" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode 'data={"key":"8847","order":"PAY-2026-001","currency":"AZN"}'

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS"
}

Error Codes

CodeMessage
4-1Invalid JSON in 'data' parameter
4-2Missing 'key' in data
4-3Missing 'order' in data
4-4Order ID exceeds 200 characters
4-5Invalid key ID or key not reserved
4-6Sale confirmation failed

GET  Action 5 — Cancel Reservation Отменить резервацию

Cancels a previously reserved key, returning it to the available pool.

Отменяет резервацию ключа, возвращая его в доступные.

GET /public/json/web.service.2024.php?action=5

Data Parameter

FieldTypeDescription
key*stringKey ID from Action 3

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=5" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode 'data={"key":"8847"}'

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS"
}

Error Codes

CodeMessage
5-1Invalid JSON in 'data' parameter
5-2Missing 'key' in data
5-3Invalid key ID or key not reserved
5-4Cancellation failed

GET  Action 6 — Direct Purchase (One-Step) Прямая покупка (один шаг)

Combines reservation and confirmation in a single call. Optionally sends the key to the customer via email with activation instructions. Auto-deactivates the package when the last key is sold.

Объединяет резервацию и подтверждение в одном вызове. Опционально отправляет ключ клиенту по email с инструкцией активации. Автоматически деактивирует пакет при продаже последнего ключа.

Recommended: Use Action 6 for simple integrations. It handles the entire purchase flow in one request, including optional email delivery to end customers. Рекомендуется: Используйте Action 6 для простых интеграций. Он обрабатывает весь процесс покупки в одном запросе, включая опциональную email-доставку клиенту.
GET /public/json/web.service.2024.php?action=6

Data Parameter

FieldTypeDescription
package*stringPackage ID
order*stringYour order ID (max 200 chars)
emailstringCustomer email — key will be sent with activation instructions
langstringEmail language (en/ru/az)

Request

cURL
curl -G "https://admin.pay.net.az/public/json/web.service.2024.php" \
  --data-urlencode "action=6" \
  --data-urlencode 'settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"en"}' \
  --data-urlencode 'data={"package":"101","order":"PAY-2026-002","email":"customer@example.com","lang":"en"}' \
  --data-urlencode "currency=AZN"

Response

200 OK
{
  "code": "0",
  "message": "SUCCESS",
  "data": {
    "keyId": "8848",
    "keyText": "AAAA-BBBB-CCCC-DDDD",
    "serialNumber": "SN-67890"
  }
}

Error Codes

CodeMessage
6-1Invalid JSON in 'data' parameter
6-2Missing 'package' in data
6-3Missing 'order' in data
6-4Package not found or inactive
6-5No available keys in stock
6-6Email delivery failed (key still sold)

Purchase Flow Поток покупки

Standard Flow (Two-Step)

Стандартный поток (два шага)

For payment terminals that need to show the price before charging the customer.

Для платёжных терминалов, которым нужно показать цену до списания средств.

1
Action 1 → Products
2
Action 2 → Packages
3
Action 3 → Reserve
4
Payment
5
Action 4 → Confirm

Express Flow (One-Step)

Экспресс-поток (один шаг)

For online stores where payment is already completed.

Для интернет-магазинов, где оплата уже произведена.

1
Action 1 → Products
2
Action 2 → Packages
3
Payment
4
Action 6 → Buy + Email
Tip: If a reservation expires (10 min timeout) and the customer has already paid, use Action 6 to complete the purchase immediately instead of starting a new reserve-confirm cycle. Совет: Если резервация истекла (10 мин), а клиент уже оплатил, используйте Action 6 для завершения покупки вместо нового цикла резервации.

REST API v2 LATEST

Full-featured RESTful API with JWT authentication, comprehensive CRUD operations, pagination, filtering, sorting, and CSV export. Manages the entire KeyForge platform.

Полнофункциональный RESTful API с JWT авторизацией, операциями CRUD, пагинацией, фильтрацией, сортировкой и экспортом CSV. Управляет всей платформой KeyForge.

Response Format

Формат ответа

Success Response
{
  "success": true,
  "data": { ... },
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 148,
    "totalPages": 8
  }
}

Authentication Аутентификация

POST /api/auth/login Login & get JWT token
Request Body
{
  "login": "admin",
  "password": "your_password"
}
Response
{
  "success": true,
  "data": {
    "accessToken": "eyJhbGci...",
    "refreshToken": "eyJhbGci...",
    "user": {
      "id": 1,
      "login": "admin",
      "role": "super_admin"
    }
  }
}
POST /api/auth/refresh Refresh access token
Request Body
{ "refreshToken": "eyJhbGci..." }
GET /api/auth/me Get current user info

Returns the authenticated user's profile information. Requires Bearer token.

Products Продукты

GET /api/products List all products

Query Parameters

ParamTypeDescription
pagenumberPage number (default: 1)
limitnumberItems per page (default: 20)
status0 | 1Filter by active (1) / inactive (0)
searchstringSearch by product name
vendor_idnumberFilter by vendor
cURL
curl "https://admin.pay.net.az/api/products?page=1&limit=10&status=1" \
  -H "Authorization: Bearer YOUR_TOKEN"
GET /api/products/:id Get product details

Returns full product details including vendor info and subcategory.

POST /api/products Create product
Request Body
{
  "name_en": "Steam Wallet $20",
  "name_ru": "Steam Кошелёк $20",
  "name_az": "Steam Cüzdan $20",
  "vendor_id": 5,
  "subcategory_id": 12,
  "status": 1,
  "position": 10
}
PUT /api/products/:id Update product

Same body as POST. All fields optional — only provided fields are updated.

DEL /api/products/:id Delete product

Permanently deletes a product. Will fail if product has associated packages with keys.

GET /api/products/stats Product statistics

Returns aggregate statistics: total products, active/inactive counts, by vendor breakdown.

Packages Пакеты

GET /api/packages List packages with filters

Paginated list with status, product_id, search filters. Includes available key count.

GET /api/packages/:id Get package details

Full package details including product info, pricing in all currencies, and key statistics.

GET /api/packages/:id/prices Get prices in all currencies

Returns the package price converted to all supported currencies (AZN, USD, EUR, TRY, RUB).

POST /api/packages Create package
Request Body
{
  "name_en": "Steam $20 Global",
  "product_id": 42,
  "supplier_id": 3,
  "price": 34.00,
  "currency": "AZN",
  "status": 1
}
PUT /api/packages/:id Update package

Update package details. Auto-activates when keys are added to an inactive package.

DEL /api/packages/:id Delete package

Deletes a package and all associated keys.

Keys Ключи

GET /api/keys List keys

Query Parameters

ParamTypeDescription
page, limitnumberPagination
statusnumber1=available, 2=reserved, 3=sold
package_idnumberFilter by package
searchstringSearch key text
GET /api/keys/with-hierarchy Keys with product hierarchy

Returns keys with their full hierarchy: vendor → product → package. Includes serial_number field.

POST /api/keys Create single key
Request Body
{
  "package_id": 101,
  "key_text": "XXXX-YYYY-ZZZZ-WWWW",
  "serial_number": "SN-12345",
  "expires_at": "2027-12-31"
}
Adding a key to an inactive package will automatically activate it.
POST /api/keys/bulk Bulk create keys
Request Body
{
  "package_id": 101,
  "keys": [
    { "key_text": "KEY-001", "serial_number": "SN-001" },
    { "key_text": "KEY-002", "serial_number": "SN-002" },
    { "key_text": "KEY-003" }
  ]
}

Returns count of successfully added keys. Duplicate keys are skipped.

DEL /api/keys/bulk/delete Bulk delete keys
Request Body
{ "ids": [100, 101, 102] }

Orders Заказы

GET /api/orders List orders

Query Parameters

ParamTypeDescription
page, limitnumberPagination
statusstringpending, confirmed, cancelled, refunded
partnerIdnumberFilter by partner
dateFrom, dateTodateDate range filter
searchstringSearch order ID
GET /api/orders/:id Get order details

Full order details including key information, partner, product, and pricing breakdown.

PATCH /api/orders/:id/status Update order status
Request Body
{ "status": "cancelled" }
GET /api/orders/stats/dashboard Dashboard statistics

Summary: total orders, revenue, orders today/this week/this month, status distribution.

GET /api/orders/export/csv Export orders to CSV

Downloads a CSV file with orders filtered by status, partner, and date range.

Partners Партнёры

GET /api/partners List partners

Paginated list of partners with status filter and search.

GET /api/partners/:id Get partner details

Full partner profile including currency settings, commission rates, and access control.

GET /api/partners/:id/statistics Partner statistics

Orders count, revenue, most purchased products, activity timeline.

GET /api/partners/:id/access Get access control

Returns which products/packages this partner can access via the API.

PUT /api/partners/:id/access Update access control
Request Body
{
  "product_ids": [42, 58, 73],
  "all_products": false
}
GET /api/partners/:id/currency-settings Currency settings

Get partner's default currency, allowed currencies, and exchange rate rules.

POST /api/partners Create partner
Request Body
{
  "name": "PayNet Azerbaijan",
  "login": "paynet",
  "password": "secure_password",
  "api_key": "unique-api-key-string",
  "status": 1,
  "default_currency": "AZN"
}

Suppliers (Vendors) Поставщики (Вендоры)

GET /api/suppliers List suppliers

Paginated list of suppliers with product counts and status.

GET /api/suppliers/:id/prices Supplier prices by currency

Returns all package prices from this supplier, broken down by currency with cost/margin data.

POST /api/suppliers/:id/prices/convert Convert prices to currencies

Auto-converts all supplier package prices to other currencies using current exchange rates.

POST /api/suppliers Create supplier
Request Body
{
  "name": "Digital Keys Supplier",
  "country": "Turkey",
  "contact_email": "sales@supplier.com",
  "status": 1
}

Email Integration Email интеграция

How to send digital keys to customers via email using Action 6.

Как отправлять цифровые ключи клиентам по email через Action 6.

When you include the email parameter in Action 6, KeyForge automatically sends a beautifully formatted email to the customer containing:

Когда вы включаете параметр email в Action 6, KeyForge автоматически отправляет красиво оформленное письмо клиенту, содержащее:

  • Product name and image
  • Название и изображение продукта
  • Digital key (PIN code)
  • Цифровой ключ (PIN-код)
  • Serial number (if applicable)
  • Серийный номер (если есть)
  • Product-specific activation instructions
  • Инструкции по активации для конкретного продукта
  • Partner branding (logo, support email)
  • Брендинг партнёра (логотип, email поддержки)
Emails are sent via Resend with delivery tracking. The email language is determined by the lang parameter (en/ru/az). Письма отправляются через Resend с отслеживанием доставки. Язык письма определяется параметром lang (en/ru/az).
Example: Action 6 with Email
// Send key + email to customer in Russian
GET /public/json/web.service.2024.php
  ?action=6
  &settings={"login":"YOUR_LOGIN","password":"YOUR_PASSWORD","lang":"ru"}
  &data={"package":"101","order":"ORD-001","email":"user@mail.com","lang":"ru"}

Webhooks Вебхуки

Receive real-time notifications about email delivery events.

Получайте уведомления о статусе доставки email в реальном времени.

KeyForge processes webhook events from Resend to track email delivery status. Supported events:

KeyForge обрабатывает вебхук-события от Resend для отслеживания статуса доставки. Поддерживаемые события:

EventDescription
email.sentEmail accepted by provider
email.deliveredEmail delivered to inbox
email.openedRecipient opened the email
email.clickedRecipient clicked a link
email.bouncedEmail bounced (invalid address)
email.complainedRecipient marked as spam