Sell our products from your own website
A simple API: a catalog with prices, player ID verification, and orders charged to your balance and delivered automatically.
Create your key
Go to your profile and generate an API key. It is shown only once: store it on your server.
Add balance
Orders are charged to your balance in dollars, at the same price any customer with balance pays. Top up by QR or Binance from the store.
Integrate and sell
List the catalog, verify the player ID and create the order. We deliver it; you check the status and, for gift cards, receive the code.
Authentication
Every request carries the key in the Authorization header. The key is a secret: use it only from your server, never from your customers' browser. If it leaks, revoke it from your profile and create another.
curl https://bitsmarkets.net/api/v1/catalog/?game=free-fire \
-H "Authorization: Bearer bmk_TU_CLAVE"Endpoints
| Method | Path | What it does |
|---|---|---|
| GET | /api/v1/account/ | Your account and your balance in dollars. |
| GET | /api/v1/catalog/ | Active games and products, with the price in dollars you are charged for each one. Accepts ?game=slug for a single game. |
| GET | /api/v1/verify/ | Verifies a player ID before buying: returns the name and region when the game allows it. |
| GET · POST | /api/v1/orders/ | Creates an order charged to your balance (POST) or lists yours (GET, with page, page_size, status and since). |
| GET | /api/v1/orders/{id}/ | One order: its status and, for a delivered gift card, its codes. |
curl "https://bitsmarkets.net/api/v1/verify/?game=mobile-legends&player_id=123456789&zone_id=5021" \
-H "Authorization: Bearer bmk_TU_CLAVE"Create an order
Send the product and the player ID. With reference (your own order number) you can retry safely: the same reference returns the same order and never charges twice.
| Field | Required | Description |
|---|---|---|
| product_id | Yes | The product id, as it comes in the catalog. |
| player_id | Yes | The player ID. Top-ups need it; gift cards do not. |
| zone_id | Depends on the game | The server or zone, when the game asks for it (requires_zone_id in the catalog). |
| reference | Depends on the game | Your reference, up to 40 characters. Recommended: it is what makes retrying safe. |
| contact_email | No | The end buyer's email. If you send it, they receive the order notifications. |
curl -X POST https://bitsmarkets.net/api/v1/orders/ \
-H "Authorization: Bearer bmk_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"product_id": 123,
"player_id": "123456789",
"zone_id": "5021",
"reference": "pedido-1001"
}'The response, with the order already charged and being delivered:
{
"id": 10234,
"reference": "pedido-1001",
"status": "processing",
"product": { "id": 123, "name": "110 Diamantes", "game_slug": "free-fire", "game_name": "Free Fire" },
"player_id": "123456789",
"zone_id": "5021",
"charged_usd": 1.02,
"codes": [],
"origin": "api"
}Poll the order every few seconds until it becomes completed:
curl https://bitsmarkets.net/api/v1/orders/10234/ \
-H "Authorization: Bearer bmk_TU_CLAVE"Order statuses
- processing: charged and being delivered. Usually takes seconds or minutes.
- completed: delivered. For a gift card, codes holds the codes.
- attention: a person delivers it and it may take longer. If it cannot be delivered, it is cancelled and the balance returns.
- cancelled: cancelled and the balance refunded.
Errors
Every error returns a message and a stable codigo so your system can decide what to do.
- 401 clave_invalida: the key does not exist or was revoked.
- 402 saldo_insuficiente: not enough balance. The response includes disponible_usd and necesario_usd.
- 400: a field is missing or malformed (falta_product_id, falta_player_id, referencia_larga).
- 409: the product just sold out, or the reference is already in use.
- 429: too many requests. Wait a moment.
- 503 saldo_sin_tasa: no reliable exchange rate right now. Retry in a few minutes.
Webhooks
Instead of polling, we can notify your server when an order made with your key finishes. You set the URL from your profile, on the key; there you also see the secret to verify the signature and can send a test.
Events
- order.completed: delivered. For a gift card, order.codes holds the codes.
- order.attention: a person delivers it and it may take longer.
- order.cancelled: cancelled and the balance refunded.
- ping: the test you send from your profile. order comes as null.
What you receive
A POST with JSON. order is the same object the order detail returns at that moment. delivery_id identifies the notification: if you receive it twice, ignore the second one.
POST https://tu-tienda.com/bits/webhook
Content-Type: application/json
X-Bits-Event: order.completed
X-Bits-Delivery: 517
X-Bits-Timestamp: 1758012345
X-Bits-Signature: v1=3f1c9a...
{
"event": "order.completed",
"delivery_id": 517,
"sent_at": "2026-09-16T14:05:45+00:00",
"order": { "id": 10234, "reference": "pedido-1001", "status": "completed", "codes": ["ABCD-1234"], ... }
}Verify the signature
Every notification carries the X-Bits-Timestamp and X-Bits-Signature headers. The signature is HMAC-SHA256 with your secret over the text timestamp.body. Recompute it and compare; reject the notification if the timestamp is older than five minutes.
import hmac, hashlib, time
def verificar(cuerpo: bytes, ts: str, firma: str, secreto: str) -> bool:
if abs(time.time() - int(ts)) > 300:
return False
esperada = "v1=" + hmac.new(secreto.encode(), f"{ts}.".encode() + cuerpo, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperada, firma)const crypto = require("crypto");
function verificar(cuerpo, ts, firma, secreto) {
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const esperada = "v1=" + crypto.createHmac("sha256", secreto).update(ts + ".").update(cuerpo).digest("hex");
return esperada.length === firma.length && crypto.timingSafeEqual(Buffer.from(esperada), Buffer.from(firma));
}Retries
Respond 2xx within seven seconds. If your server does not respond or returns another code, we retry at 1, 5, 15, 60, 180, 720 and 1440 minutes and then give up. You can see it in your profile and in the API's deliveries list.
The URL must be https and public. We do not accept internal addresses and we do not follow redirects.
Rules
- You are charged from your balance in dollars, at the same price any customer with balance pays. You set your margin in your store.
- The key lives only on your server. Never in a page, an app or a public repository.
- Limits per key: 60 requests per minute to the catalog and the account, 120 verifications per minute and 120 orders per hour.
- This is version v1. New fields may appear in responses; existing ones do not change meaning.
Ready to integrate?
Create your key from your profile and try the catalog.