Introduction
Integrate voucher and top-up products, Redeem Data checks, Telegram Stars, and custom-amount Steam Top-Up into your own system using Epinby.com public JSON API. This page includes live playground blocks so resellers can verify their API key, test requests, inspect raw request bodies, and validate webhook signatures directly from the browser.
https://mail.epinby.com/api/v1
/games, /categories, and /products to build your browsing and purchase flow.
X-Idempotency-Key on every order request. You may also send callback_url plus callback_mode.
legacy sends final updates only. events sends signed status-change webhooks.
Base URL & Versioning
All endpoints below are relative to https://mail.epinby.com/api/v1.
Version v1 is stable. Future breaking versions should use a separate prefix.
Authentication
All /api/v1 endpoints require your personal API key in the request header below:
X-API-KEY: YOUR_API_KEY
Idempotency
For POST /order, X-Idempotency-Key is required. Reusing the same key with the same payload safely returns the existing order; reusing it with a different payload returns 409 IDEMPOTENCY_CONFLICT. The Telegram Stars endpoint follows the same safe-replay principle. Steam Top-Up order creation also requires an idempotency key.
X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Get Account Details
Retrieve reseller profile data, balance, currency, and personal webhook_secret.
curl -s "https://mail.epinby.com/api/v1/getMe" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"user_id": 579365494,
"username": "reseller_pro",
"balance": "1250.5000",
"webhook_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"currency": "USD"
}
}
No request yet.
Response will appear here.
Games
List available games that can be used to group or filter top-up products.
curl -s "https://mail.epinby.com/api/v1/games" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": [
{
"id": 1,
"name": "PUBG Mobile"
},
{
"id": 2,
"name": "Mobile Legends"
}
]
}
No request yet.
Response will appear here.
Categories
List active product categories for a specific game. game_id is required.
| Query | Type | Required | Description |
|---|---|---|---|
game_id |
integer | YES | Active game ID whose categories should be returned. |
curl -s "https://mail.epinby.com/api/v1/categories?game_id=1" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": [
{
"id": 10,
"name": "UC Packages",
"image": "https://example.com/storage/categories/category.jpg",
"per_page_count": 15
}
]
}
No request yet.
Response will appear here.
Products
List active products. Supports filters such as type, game, category, and IDs.
| Query | Type | Required | Description |
|---|---|---|---|
type | string | NO | voucher or topup |
game | string | NO | Search by game name |
category | string | NO | Search by category name |
game_id | integer | NO | Filter by game ID |
category_id | integer | NO | Filter by category ID |
page | integer | NO | Page number |
per_page | integer | NO | Maximum 100 |
curl -s "https://mail.epinby.com/api/v1/products?type=voucher&per_page=10" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": [
{
"id": 55,
"name": "Steam Wallet 10 USD",
"game_id": 0,
"game": "",
"category_id": 3,
"category": "Gift Cards",
"type": "VOUCHER",
"price": "9.9900",
"stock_status": "FINITE",
"stock_count": 120,
"fields": [],
"supports_player_validation": false
}
],
"meta": {
"total": 1,
"per_page": 10,
"current_page": 1,
"last_page": 1
}
}
No request yet.
Response will appear here.
Name Check subscription
One subscription for API, reseller panel and Telegram. Your VIP package and product prices stay the same.
Use your existing X-API-KEY. Lookup endpoints require a separate active monthly subscription purchased from the reseller API page. Expiry does not disable product orders.
| Endpoint | Behavior |
|---|---|
GET /api/v1/name-check/subscription | Returns active status, expiry and usage. Authentication required; subscription not required. |
GET /api/v1/name-check/games | Full checker catalog, independent of products on sale. Each profile includes code, fields and capabilities. |
POST /api/v1/name-check | Checks a player and automatically fetches supported extra details and eligible regional packages. |
Send game_code and user_id as strings. Provide server_id, charname and extra.param_* values exactly as required by the selected catalog profile. Keep leading zeroes. Do not infer a country from a server ID.
curl -s "https://mail.epinby.com/api/v1/name-check" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "X-Idempotency-Key: lookup-20261103-001" \
-H "Content-Type: application/json" \
-d '{"game_code":"mobile-legends-wr","user_id":"123456789","server_id":"1234"}'
Illustrative response; values and quotas depend on the player and purchased package.
{
"success": true,
"data": {
"game_code": "mobile-legends-wr",
"player_name": "Example player",
"region": "FR",
"country_code": "FR",
"region_names": {"en":"France","az":"Fransa","tr":"Fransa","ru":"Франция"},
"country_names": {"en":"France","az":"Fransa","tr":"Fransa","ru":"Франция"},
"facts": {},
"package_checks": [{"key":"double_diamonds","items":[{"title":"50+50","limit_reached":true}]}],
"package_check_status": "checked"
},
"request_id": "lookup-20261103-001",
"replayed": false,
"quota": {"monthly_limit":null,"used":1,"remaining":null,"game":{"key":"mobile-legends","daily_limit":null,"used":1,"remaining":null},"requests_per_minute":null,"concurrency_limit":2,"reset_timezone":"Asia/Baku","expires_at":"2026-12-03T12:00:00+00:00"}
}
Only returned evidence is shown. region_names and country_names contain full localized names. A missing country stays unknown. limit_reached=true means the package limit was reached; false means it was not reached; null means unknown. Missing packages are unknown. Extra facts do not imply bonus eligibility. Package-check failures are reported separately and do not invalidate a verified player name.
X-Idempotency-Key (or request_id) is required: 8–100 letters, digits, dots, underscores, colons or hyphens. Reuse it when retrying the same request; do not reuse it with different inputs. A 202 response means processing: wait for Retry-After and retry with the same ID. Replays do not consume another lookup.
Unlimited subscriptions have no daily, monthly or per-minute request-count cap. The simultaneous-request limit still applies and is shared across API, reseller panel, website and Telegram. The response shows the purchased terms: monthly_limit=null, game.daily_limit=null and requests_per_minute=null mean no corresponding cap; concurrency_limit is the maximum number of in-flight checks. used records successful checks and active reservations. A third simultaneous check with concurrency_limit=2 returns TOO_MANY_IN_FLIGHT (HTTP 429); retry after an active check finishes and respect Retry-After. Name and automatic package checks are one request. Finite allowances, when configured on another plan, share usage across channels and game variants; daily usage resets at midnight in Baku. Failed checks release their reservation.
An active subscription includes checks in the API, reseller panel, website and Telegram under the displayed package terms. Included checks do not charge your wallet. Product purchases do not require this subscription.
| HTTP | Status | Behavior |
|---|---|---|
| 403 | SUBSCRIPTION_REQUIRED | An active Name Check API subscription is required. |
| 422 | INVALID_INPUT | Check the required player fields and allowed values. |
| 422 | GAME_NOT_SUPPORTED | Game profile is not supported. |
| 404 | PLAYER_NOT_FOUND | Player could not be verified. |
| 409 | IDEMPOTENCY_CONFLICT | Request ID already used with different inputs. |
| 202 | REQUEST_IN_PROGRESS | Request is still processing. Retry with the same request ID. |
| 429 | MONTHLY_QUOTA_EXCEEDED | Monthly lookup allowance exhausted. |
| 429 | MLBB_DAILY_QUOTA_EXCEEDED | Daily MLBB allowance exhausted. Resets at midnight Asia/Baku. |
| 429 | GAME_DAILY_QUOTA_EXCEEDED | This game’s daily allowance is exhausted. It resets at midnight in Baku. |
| 429 | RATE_LIMITED | Too many requests. Try again shortly. |
| 429 | TOO_MANY_IN_FLIGHT | Wait for your running requests to finish. |
| 503 | LOOKUP_UNAVAILABLE | Service temporarily unavailable. |
| 504 | LOOKUP_TIMEOUT | Lookup timed out. No allowance was consumed. |
Normal product orders and player name validation do not require a Name Check subscription and do not consume its allowance. POST /order does not require a preliminary /validate-player request. Internal delivery compatibility checks remain active. Region and other account details are only exposed through the API to active Name Check subscribers; use POST /name-check for supported package and bonus details.
Player name validation for active top-up products available to your account is free and does not require a Name Check subscription or idempotency key. Without an active subscription, only the player name, input identifiers and validation status are returned. Region, country, package eligibility and additional account facts require an active Name Check API subscription. These restrictions also apply to order responses, order history and webhooks. Standard API authentication, throttling and category/channel rules apply.
Validate Player
Validate the target player before creating a top-up order. This endpoint is only relevant for products that require player input.
| Field | Type | Required | Description |
|---|---|---|---|
product_id | integer | YES | Active top-up product ID |
player_id | string | YES | Player or user identifier |
server_id | string | NO | Server/zone/region value when needed |
input_2...input_8 | string | NO | Extra mapped input fields for advanced products |
curl -s "https://mail.epinby.com/api/v1/validate-player" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"product_id": 91,
"player_id": "5123456789",
"server_id": "2001"
}'
{
"success": true,
"data": {
"nickname": "PlayerOne",
"player_name": "PlayerOne",
"server_id": "2001",
"nickname_verified": true,
"validation_optional": false
}
}
No request yet.
Response will appear here.
Create Order
Create a voucher or top-up order. For top-up products, validate the player first when required.
X-Idempotency-Key is required and makes retries safe. The initial response records the order as PENDING; fulfillment continues asynchronously.
| Field | Type | Required | Description |
|---|---|---|---|
product_id | integer | YES | Target product ID |
qty | integer | NO | Voucher quantity. Top-up orders must use 1. |
player_id | string | TOPUP | Required for top-up products |
server_id | string | NO | Optional second field for supported games |
input_2...input_8 | string | NO | Additional mapped inputs |
callback_url | string | NO | HTTPS webhook endpoint |
callback_mode | string | NO | legacy (default) or events |
Headers
X-API-KEY: YOUR_API_KEY X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Voucher order example
{
"product_id": 55,
"qty": 2,
"callback_url": "https://yourdomain.com/webhooks/epinbycom",
"callback_mode": "legacy"
}
Top-up order example
{
"product_id": 91,
"qty": 1,
"player_id": "5123456789",
"server_id": "2001",
"callback_url": "https://yourdomain.com/webhooks/epinbycom",
"callback_mode": "events"
}
Response
{
"success": true,
"data": {
"order_id": 8821,
"status": "PENDING",
"player": {
"nickname": "PlayerOne",
"player_name": "PlayerOne",
"region": "TR",
"server_id": "2001",
"nickname_verified": true
}
}
}
callback_mode as legacy for old integrations.
Use events only if your webhook consumer is ready for PENDING,
PROCESSING, COMPLETED, and FAILED status updates.
No request yet.
Response will appear here.
Get Order Status
Fetch a single order by ID.
curl -s "https://mail.epinby.com/api/v1/order/8821" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"order_id": 8821,
"client_order_id": "7b8f0a64-4f7e-4a2f-9a0a-7b1f0a3bfa11",
"player_id": "5123456789",
"server_id": "2001",
"player_name": "PlayerOne",
"region": "TR",
"player": {
"nickname": "PlayerOne",
"player_name": "PlayerOne",
"region": "TR",
"server_id": "2001",
"nickname_verified": true
},
"status": "COMPLETED",
"price": "19.9800",
"created_at": "2026-01-30T13:05:04+00:00"
}
}
No request yet.
Response will appear here.
List Orders
Retrieve your recent order list.
{
"success": true,
"data": [
{
"order_id": 8821,
"client_order_id": "7b8f0a64-4f7e-4a2f-9a0a-7b1f0a3bfa11",
"player_name": "PlayerOne",
"region": "TR",
"player": {
"nickname": "PlayerOne",
"player_name": "PlayerOne",
"region": "TR",
"server_id": "2001",
"nickname_verified": true
},
"status": "COMPLETED",
"price": "19.9800",
"created_at": "2026-01-30T13:05:04+00:00"
}
]
}
No request yet.
Response will appear here.
Redeem Data API
Check redemption metadata for a redeem code through the same paid Redeem Data service used by the customer channels. Every request is billed from the API user's wallet according to the configured result price.
charged_amount and the updated balance.
curl -s "https://mail.epinby.com/api/v1/redeem-data/config" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"enabled": true,
"success_price": 0.05,
"not_found_price": 0.02,
"technical_error_price": 0,
"currency_code": "USD",
"balance": 1250.5
}
}
No request yet.
Response will appear here.
| Field | Type | Required | Description |
|---|---|---|---|
code | string | YES | Redeem code to inspect. Length: 6-160 characters. |
curl -s "https://mail.epinby.com/api/v1/redeem-data/check" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"code":"YOUR-REDEEM-CODE"}'
{
"success": true,
"data": {
"id": 4812,
"status": "found",
"code_masked": "ABCD********WXYZ",
"charged_amount": 0.05,
"balance": 1250.45,
"currency_code": "USD",
"redemption_time": "2026-08-12 18:10:24",
"expiration_time": null,
"amount": 60,
"product_name": "PUBG Mobile 60 UC",
"player_id": "5123456789",
"player_name": "PlayerOne",
"receipt_id": 98765,
"receipt_successful": true
}
}
No request yet.
Response will appear here.
| Query | Type | Required | Description |
|---|---|---|---|
limit | integer | NO | Number of recent checks to return. Range: 1-100. |
curl -s "https://mail.epinby.com/api/v1/redeem-data/history?limit=20" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
No request yet.
Response will appear here.
Telegram Stars API
Send an exact Stars amount to a Telegram username using the same custom-amount pricing rules as the reseller panel. Telegram Premium is intentionally not exposed by these endpoints.
/telegram-stars/config → /telegram-stars/recipient → /telegram-stars/quote → /telegram-stars/order.
Poll /telegram-stars/order/{id} when the returned status is PROCESSING.
curl -s "https://mail.epinby.com/api/v1/telegram-stars/config" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"enabled": true,
"service_online": true,
"custom_amount_enabled": true,
"min_stars": 50,
"max_stars": 10000,
"group_discount_percent": "0.0000",
"balance": "1250.5000",
"currency": "USD",
"pricing_mode": "custom_amount"
}
}
No request yet.
Response will appear here.
| Field | Type | Required | Description |
|---|---|---|---|
telegram_username | string | YES | Telegram username with or without @. |
curl -s "https://mail.epinby.com/api/v1/telegram-stars/recipient" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"telegram_username":"@exampleuser"}'
No request yet.
Response will appear here.
| Field | Type | Required | Description |
|---|---|---|---|
stars_amount | integer | YES | Exact number of Stars. Must be within the min/max returned by config. |
curl -s "https://mail.epinby.com/api/v1/telegram-stars/quote" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"stars_amount":137}'
{
"success": true,
"data": {
"service_type": "stars",
"label": "137 Stars",
"stars_amount": 137,
"discount_percent": "0.0000",
"reseller_price_usd": "2.1235",
"you_pay_text": "$ 2.1235",
"receive_text": "137 Stars"
}
}
No request yet.
Response will appear here.
| Field / Header | Type | Required | Description |
|---|---|---|---|
telegram_username | string | YES | Recipient username. |
stars_amount | integer | YES | Exact Stars amount. |
X-Idempotency-Key | header | RECOMMENDED | Unique value, maximum 128 characters. Same key + same payload safely replays the existing Stars order. |
curl -s "https://mail.epinby.com/api/v1/telegram-stars/order" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "X-Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-H "Content-Type: application/json" \
-d '{"telegram_username":"@exampleuser","stars_amount":137}'
{
"success": true,
"data": {
"order_id": 9912,
"client_order_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"quote": {
"service_type": "stars",
"stars_amount": 137,
"reseller_price_usd": "2.1235",
"receive_text": "137 Stars"
}
}
}
No request yet.
Response will appear here.
curl -s "https://mail.epinby.com/api/v1/telegram-stars/order/9912" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"order_id": 9912,
"client_order_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "COMPLETED",
"telegram_username": "@exampleuser",
"stars_amount": 137,
"price": "2.1235",
"currency": "USD"
}
}
No request yet.
Response will appear here.
Steam Top-Up API
Send a custom amount to a Steam account in USD, RUB, KZT or UAH. Currency-specific limits, current rates and your effective pricing adjustment are returned by the configuration endpoint.
/steam-topup/config → /steam-topup/quote → /steam-topup/check-login → /steam-topup/order.
Poll /steam-topup/order/{id} while the returned status is PENDING or PROCESSING.
Currency rules:
currency is optional and defaults to USD for backward compatibility. USD accepts up to 2 decimal places; RUB, KZT and UAH accept up to 4. price_adjustment_percent is signed: negative means a discount and positive means a markup. The returned price is always charged from your API wallet in USD.
Rounding: for RUB, KZT and UAH the USD nominal is rounded up to the next cent so the top-up is never below the amount you requested. Therefore
will_receive can be slightly higher than amount.
curl -s "https://mail.epinby.com/api/v1/steam-topup/config" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"enabled": true,
"currency": "USD",
"min_amount": "0.15",
"max_amount": "1000.00",
"discount_percent": "1.0000",
"default_currency": "USD",
"wallet_currency": "USD",
"currencies": [
{"code":"USD","enabled":true,"min_amount":"0.15","max_amount":"1000.00","rate":"1.00000000","price_adjustment_percent":"-1.0000","effective_price_adjustment_percent":"-1.0000"},
{"code":"RUB","enabled":true,"min_amount":"12.6500","max_amount":"84311.4800","rate":"84.31147500","price_adjustment_percent":"-1.0000","effective_price_adjustment_percent":"-1.0000"},
{"code":"KZT","enabled":true,"min_amount":"66.4900","max_amount":"443262.2900","rate":"443.26229500","price_adjustment_percent":"-1.0000","effective_price_adjustment_percent":"-1.0000"},
{"code":"UAH","enabled":true,"min_amount":"6.7100","max_amount":"44754.1000","rate":"44.75409800","price_adjustment_percent":"-1.0000","effective_price_adjustment_percent":"-1.0000"}
],
"rates_updated_at": "2026-09-27T21:02:01.403Z"
}
}
No request yet.
Response will appear here.
| Field | Type | Required | Description |
|---|---|---|---|
currency | string | NO | USD, RUB, KZT or UAH. Defaults to USD. |
amount | decimal | YES | Amount in the selected currency. USD: up to 2 decimals. RUB/KZT/UAH: up to 4. Use currency-specific min/max values from config. |
curl -s "https://mail.epinby.com/api/v1/steam-topup/quote" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"currency":"RUB","amount":"1000.0000"}'
{
"success": true,
"data": {
"amount": "1000.0000",
"amount_usd": "11.8700",
"currency": "RUB",
"will_receive": "1000.7772",
"will_receive_usd": "11.8700",
"discount_percent": "1.0000",
"price_adjustment_percent": "-1.0000",
"price": "11.7513",
"price_currency": "USD",
"rate": "84.31147500"
}
}
No request yet.
Response will appear here.
| Field | Type | Required | Description |
|---|---|---|---|
steam_login | string | YES | Steam account login to validate before placing an order. |
curl -s "https://mail.epinby.com/api/v1/steam-topup/check-login" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"steam_login":"examplelogin"}'
{
"success": true,
"data": {
"can_refill": true
}
}
No request yet.
Response will appear here.
| Field / Header | Type | Required | Description |
|---|---|---|---|
steam_login | string | YES | Steam account login. |
currency | string | NO | USD, RUB, KZT or UAH. Defaults to USD. |
amount | decimal | YES | Amount in the selected currency. USD supports up to 2 decimals; RUB/KZT/UAH up to 4. |
X-Idempotency-Key | header | YES | Unique value, maximum 128 characters. Same key + same payload safely returns the existing order. |
callback_url | HTTPS URL | NO | Optional order status webhook URL. |
callback_mode | string | NO | legacy or events. Defaults to legacy. |
curl -s "https://mail.epinby.com/api/v1/steam-topup/order" \
-X POST \
-H "X-API-KEY: YOUR_API_KEY" \
-H "X-Idempotency-Key: steam-20260904-0001" \
-H "Content-Type: application/json" \
-d '{"steam_login":"examplelogin","currency":"RUB","amount":"1000.0000"}'
{
"success": true,
"data": {
"order_id": 10452,
"client_order_id": "steam-20260904-0001",
"status": "PROCESSING",
"steam_login": "examplelogin",
"amount": "1000.0000",
"amount_usd": "11.8700",
"currency": "RUB",
"will_receive": "1000.7772",
"will_receive_usd": "11.8700",
"discount_percent": "1.0000",
"price_adjustment_percent": "-1.0000",
"price": "11.7513",
"price_currency": "USD"
}
}
No request yet.
Response will appear here.
curl -s "https://mail.epinby.com/api/v1/steam-topup/order/10452" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
{
"success": true,
"data": {
"order_id": 10452,
"client_order_id": "steam-20260904-0001",
"status": "COMPLETED",
"steam_login": "examplelogin",
"amount": "1000.0000",
"amount_usd": "11.8700",
"currency": "RUB",
"will_receive": "1000.7772",
"will_receive_usd": "11.8700",
"discount_percent": "1.0000",
"price_adjustment_percent": "-1.0000",
"price": "11.7513",
"price_currency": "USD"
}
}
No request yet.
Response will appear here.
Price Change Webhooks
Receive a webhook notification whenever a product's selling price changes.
old_priceshows the previous selling price for your API account.new_priceshows the new selling price for your API account.- If several product prices change together, they may be included in a single delivery.
Configure price notifications
Use your existing X-API-KEY. The same personal webhook_secret returned by GET /getMe signs these deliveries.
curl -s "https://mail.epinby.com/api/v1/price-webhook" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | YES | Enable or disable sale price notifications. |
url | string | WHEN ENABLED | Public HTTPS endpoint on port 443. |
curl -X PUT "https://mail.epinby.com/api/v1/price-webhook" \
-H "X-API-KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"url": "https://yourdomain.com/webhooks/catalog-prices"
}'
Sends a signed test notification to the configured URL.
curl -X POST "https://mail.epinby.com/api/v1/price-webhook/test" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
Disables price notifications.
curl -X DELETE "https://mail.epinby.com/api/v1/price-webhook" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Accept: application/json"
Price change event
The event name and header value are both products.prices_changed.
{
"event": "products.prices_changed",
"event_id": "8b56f17d-45ba-44d0-b851-98a73017a66f",
"currency": "USD",
"products": [
{
"product_id": 145,
"name": "660 UC",
"old_price": "9.0000",
"new_price": "9.9000",
"change_amount": "0.9000",
"change_percent": "10.0000",
"direction": "increased"
},
{
"product_id": 146,
"name": "720 UC",
"old_price": "12.5000",
"new_price": "12.0000",
"change_amount": "-0.5000",
"change_percent": "-4.0000",
"direction": "decreased"
}
],
"changed_at": "2026-09-03T21:30:00+04:00"
}
| Header | Description |
|---|---|
X-GAMEX-Event | products.prices_changed |
X-GAMEX-Event-Id | Stable UUID for idempotent processing. |
X-GAMEX-Timestamp | Timestamp matching the event body. |
X-GAMEX-Signature | sha256=HMAC_SHA256(raw_body, webhook_secret) |
product_id as the stable mapping key in your catalog. Treat new_price as the latest price for your API account. Periodically reconcile with GET /products as the authoritative catalog source.
Delivery and retries
Any HTTP 2xx response marks the delivery successful. Failed deliveries are retried automatically, up to 12 attempts.
No request yet.
Response will appear here.
Webhooks
If you send a valid callback_url while creating an order, webhook behavior depends on callback_mode.
| Mode | Behavior |
|---|---|
legacy |
Backward-compatible mode. Only one final reseller webhook is sent when the order reaches COMPLETED or CANCELED. |
events |
Status-change mode. Signed webhooks are sent for public lifecycle changes such as PENDING, PROCESSING, COMPLETED, and FAILED. |
- Voucher orders may finalize very quickly.
- Top-up orders may remain in
PROCESSINGbefore completion. - Event mode is best for automation flows that should react before final completion.
- When an order is later completed or canceled from the admin panel, the same saved
callback_urlis used for the final webhook. - Your webhook endpoint should answer with
2xxquickly and tolerate duplicate deliveries.
Signature Verification
Signed webhook requests include an HMAC header generated using your personal webhook_secret
from /getMe.
| Header | Description |
|---|---|
X-GAMEX-Signature | HMAC SHA-256 of the raw request body in format sha256=... |
X-GAMEX-Event-Id | Stable event identifier. Store it and ignore a duplicate delivery with the same value. |
X-GAMEX-Timestamp | ISO-8601 timestamp matching the webhook payload. |
X-GAMEX-Event | Present for event-mode webhooks. Current value: order.status_changed |
Content-Type | application/json |
$secret = 'YOUR_WEBHOOK_SECRET';
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_GAMEX_SIGNATURE'] ?? '';
$computed = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($computed, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
http_response_code(204);
No calculation yet.
Result will appear here.
Payload Examples
Legacy final webhook example
{
"event_id": "47c8c6ba-16a5-4089-9f62-7ae1e51d4c0f",
"order_id": 8821,
"client_order_id": "7b8f0a64-4f7e-4a2f-9a0a-7b1f0a3bfa11",
"status": "COMPLETED",
"product_name": "Steam Wallet 10 USD",
"qty": 2,
"player_id": null,
"player_name": null,
"server_id": null,
"region": null,
"player": [],
"price": "19.9800",
"currency": "USD",
"delivery": ["CODE_1", "CODE_2"],
"timestamp": "2026-01-30T13:05:10+00:00"
}
Events mode webhook example
{
"event": "order.status_changed",
"event_id": "63bca98d-d2de-4a95-a98a-d5be39098f17",
"callback_mode": "events",
"order_id": 8821,
"client_order_id": "7b8f0a64-4f7e-4a2f-9a0a-7b1f0a3bfa11",
"product_id": 91,
"product_name": "PUBG Mobile 60 UC",
"product_type": "TOPUP",
"game_id": 1,
"game_name": "PUBG Mobile",
"player_id": "5123456789",
"player_name": "PlayerOne",
"server_id": "2001",
"region": "TR",
"player": {
"nickname": "PlayerOne",
"player_name": "PlayerOne",
"region": "TR",
"server_id": "2001",
"nickname_verified": true
},
"qty": 1,
"price": "0.8800",
"status": "PROCESSING",
"message": "Order is currently being processed.",
"timestamp": "2026-03-30T02:00:00+00:00"
}
Order Status Lifecycle
| Status | Description | Where used |
|---|---|---|
PENDING |
Order created and waiting for provisioning. | Event mode public webhook |
PROCESSING |
Provisioning started but not finalized yet. | Order responses and event mode webhooks |
COMPLETED |
Order delivered successfully. | All modes |
CANCELED |
Internal final failure state used by legacy/final flows. | Legacy final callbacks and order views |
FAILED |
Public failure name used by event mode webhook payloads. Treat it as a terminal canceled/failed order. | Events mode public webhook |
Error Codes
Use error.code for programmatic handling.
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "player_id is required."
}
}
Changelog
Steam Top-Up Public API endpoints for configuration, quoting, Steam login validation, idempotent order creation, optional order callbacks, and order status checks.
products.prices_changed webhooks with per-API-account old/new prices, isolated delivery retries, live configuration endpoints, and documentation playground controls.
Redeem Data and custom-amount Telegram Stars, including live documentation playgrounds, Stars idempotency, recipient lookup, quote, order status, and Redeem Data history.
events webhooks are now dispatched when orders are completed or canceled after creation, including admin/manual status changes. Legacy webhook payload documentation was aligned with the stable payload shape.
callback_mode documentation, event-style webhook coverage,
signed status-change payload examples, and dynamic project branding from admin settings.
Azərbaycan
Engilsh
Russia
Turkey