Incluye perfil, productos, validación de cuenta cuando corresponde, creación y consulta de pedidos, además del historial de movimientos.
Descargar colecciónAPI B2B de Only For Gamer
Integrá tu plataforma con nuestro catálogo digital, consultá precios, creá pedidos, controlá tu saldo y recibí actualizaciones automáticas mediante webhooks.
Inicio rápido
Todas las solicitudes utilizan JSON y deben enviarse por HTTPS. Para comenzar, realizá una consulta a tu perfil usando un token API generado desde el Centro de desarrolladores del Portal B2B.
curl --request GET \
--url https://b2b.onlyforgamer.com/api/v1/me \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
Colección oficial de Postman
Descargá la colección completa y el entorno de producción para probar todos los endpoints actuales de la API B2B.
Contiene la URL base y variables de ejemplo. No incluye tokens, secretos ni credenciales reales.
Descargar entornoCómo importarlo
- Descargá e importá los dos archivos en Postman.
- Seleccioná el entorno Only For Gamer - Producción.
-
Pegá tu credencial en la variable
api_token. -
Configurá
skuy los datos indicados porrequired_fields, comoplayer_id,server_idoplayer_ip. -
Dejá
idempotency_keyvacía para que la colección genere una automáticamente. - Ejecutá primero Listar productos. La colección guarda el precio, moneda y disponibilidad de validación del SKU.
-
Si
account_validation_availableestrue, ejecutá Validar cuenta antes de Crear pedido.
POST /orders utiliza el saldo
real del revendedor. Antes de crear otro
pedido, vaciá
idempotency_key para generar
una clave nueva.
order_number. Luego podés
ejecutar directamente
Consultar pedido por número.
Autenticación
La API utiliza un token Bearer. Incluí el
encabezado
Authorization
en todas las solicitudes.
Authorization: Bearer <TU_TOKEN_API>
Accept: application/json
Content-Type: application/json
Accept.
X-Request-ID. Si está
presente, guardalo para facilitar el
diagnóstico.
Permisos del token
Cada token puede limitarse a las funciones necesarias para una integración específica.
| Permiso | Descripción |
|---|---|
profile:read
|
Consultar perfil, moneda, saldo, límite de crédito y fondos disponibles. |
balance:read
|
Consultar saldo y mantener compatibilidad con tokens anteriores para movimientos. |
wallet:read
|
Consultar el historial de movimientos de saldo. |
products:read
|
Consultar catálogo, disponibilidad y precio B2B. |
orders:read
|
Listar y consultar pedidos. |
orders:create
|
Crear pedidos nuevos y reservar saldo. |
Límites de uso
El límite se comparte entre todos los tokens
pertenecientes al mismo revendedor. Al
superarlo, la API responde con
HTTP 429.
Consultar perfil y saldo
Devuelve los datos públicos del revendedor, el saldo contable, el límite de crédito y los fondos totales disponibles.
curl --request GET \
--url https://b2b.onlyforgamer.com/api/v1/me \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
Respuesta exitosa
{
"success": true,
"data": {
"code": "RESELLER-CODE",
"company_name": "Empresa revendedora",
"currency": "USD",
"balance": "105.080000",
"credit_limit": "0.000000",
"available_funds": "105.080000"
}
}
available_funds es la suma
del saldo y el límite de crédito
autorizado.
Consultar productos
Devuelve únicamente los productos que están disponibles y son vendibles para el revendedor, junto con su precio B2B, moneda, campos requeridos y disponibilidad de verificación de cuenta.
| Parámetro | Tipo | Descripción |
|---|---|---|
search |
string | Busca por nombre, SKU, marca o categoría. Máximo 100 caracteres. |
brand |
string | Filtra por marca exacta. |
category |
string | Filtra por categoría exacta. |
region |
string | Filtra por región. |
product_type |
string |
Filtra por tipo de producto,
por ejemplo topup.
|
per_page |
integer | Entre 1 y 50. Valor predeterminado: 20. |
page |
integer | Número de página. Mínimo 1. |
curl --request GET \
--url 'https://b2b.onlyforgamer.com/api/v1/products?region=LATAM&product_type=topup&per_page=20' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
Respuesta
{
"success": true,
"data": [
{
"sku": "PRODUCT-SKU",
"name": "Nombre del producto",
"brand": "Marca",
"category": "Recargas",
"region": "LATAM",
"product_type": "topup",
"face_value": "86.000000",
"face_currency": null,
"required_fields": [
"player_id",
"server_id"
],
"account_validation_available": true,
"available": true,
"price": "1.250000",
"currency": "USD"
}
],
"meta": {
"current_page": 1,
"per_page": 20,
"last_page": 1,
"total": 1
}
}
available: true.
required_fields es la fuente
de verdad para saber qué datos enviar en
target_data. Puede incluir
player_id,
server_id,
player_ip,
email o
phone.
price y la
currency recibidos aquí como
expected_price y
expected_currency.
El servidor vuelve a calcular el precio
inmediatamente antes de reservar saldo.
Validar una cuenta antes de comprar
Ejecutá este endpoint solamente cuando
GET /products devuelva
account_validation_available: true
para el SKU elegido.
account_validation_available
es false, no necesitás llamar
este endpoint y no debés inventar un token.
En ambos casos respetá siempre
required_fields.
Solicitud
curl --request POST --url https://b2b.onlyforgamer.com/api/v1/products/PRODUCT-SKU/validate-account --header 'Accept: application/json' --header 'Content-Type: application/json' --header 'Authorization: Bearer <TU_TOKEN_API>' --data '{
"target_data": {
"player_id": "123456789",
"server_id": "1234",
"player_ip": "203.0.113.10"
}
}'
Enviá únicamente los valores correspondientes
al producto. Por ejemplo, si
required_fields contiene solamente
player_id, no necesitás enviar
servidor ni IP.
Cuenta verificada
{
"success": true,
"data": {
"verified": true,
"message": "Cuenta verificada correctamente.",
"player_name": "Cuenta confirmada",
"account_validation_token": "TOKEN_OPACO",
"expires_in": 600
}
}
account_validation_token
está ligado al revendedor, al token API,
al producto y a los datos validados.
Utilizalo en
POST /orders sin modificar
player_id,
server_id ni
player_ip. Vence en
aproximadamente 10 minutos.
Crear un pedido
Crea un pedido B2B, vuelve a comprobar el precio y disponibilidad actuales y reserva los fondos únicamente cuando todas las validaciones requeridas son correctas.
Idempotency-Key.
| Campo | Tipo | Uso |
|---|---|---|
sku
Obligatorio
|
string |
SKU público obtenido desde
GET /products.
Máximo 100 caracteres.
|
quantity
Opcional
|
integer |
Actualmente solo se admite
el valor 1.
|
external_reference
Opcional
|
string | Identificador del pedido en el sistema del revendedor. Máximo 150 caracteres. |
target_data.player_id
|
string |
Enviá este valor cuando
required_fields
incluya player_id.
|
target_data.server_id
|
string |
Enviá este valor cuando
required_fields
incluya server_id.
|
target_data.email
|
Correo del destinatario cuando el producto lo requiera. | |
target_data.phone
|
string | Número telefónico cuando el producto lo requiera. |
target_data.player_ip
|
IP |
Enviá este valor cuando
required_fields
incluya player_ip.
|
expected_price
|
decimal |
Precio aceptado por tu sistema.
Utilizá el valor
price obtenido en
GET /products.
|
expected_currency
|
string |
Moneda correspondiente al
expected_price.
Enviá ambos campos juntos.
|
account_validation_token
|
string |
Obligatorio únicamente cuando
el producto tiene
account_validation_available:
true. Se obtiene mediante
POST
/products/{sku}/validate-account.
|
curl --request POST \
--url https://b2b.onlyforgamer.com/api/v1/orders \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>' \
--header 'Idempotency-Key: order-20260803-0001' \
--data '{
"sku": "PRODUCT-SKU",
"quantity": 1,
"external_reference": "MI-PEDIDO-0001",
"expected_price": "1.250000",
"expected_currency": "USD",
"account_validation_token": "TOKEN_SI_CORRESPONDE",
"target_data": {
"player_id": "123456789",
"server_id": "1234",
"player_ip": "203.0.113.10"
}
}'
expected_price y
expected_currency con los
valores obtenidos del catálogo. Si el
precio cambió antes de reservar saldo, la
API rechaza la solicitud para evitar cobrar
silenciosamente un importe distinto.
Actualizá el catálogo y decidí nuevamente.
Pedido creado
{
"success": true,
"idempotent": false,
"data": {
"order_number": "B2B-01EXAMPLEORDER",
"external_reference": "MI-PEDIDO-0001",
"status": "pending",
"sku": "PRODUCT-SKU",
"product_name": "Nombre del producto",
"quantity": 1,
"currency": "USD",
"unit_price": "1.250000",
"total": "1.250000",
"created_at": "2026-08-03T06:45:00+00:00"
}
}
Idempotencia
La idempotencia permite repetir una solicitud cuando hubo un timeout o una interrupción de red sin crear dos pedidos.
- Generá una clave única para cada pedido.
- Conservá la misma clave al reintentar exactamente la misma solicitud.
- No reutilices la clave para otro SKU, jugador o servidor.
HTTP 200 con
idempotent: true y
devuelve el pedido existente.
HTTP 409 cuando la misma
clave ya se utilizó para otro pedido.
{
"success": true,
"idempotent": true,
"data": {
"order_number": "B2B-01EXAMPLEORDER",
"status": "pending"
}
}
Listar pedidos
Devuelve los pedidos pertenecientes al revendedor autenticado, ordenados desde el más reciente.
| Parámetro | Descripción |
|---|---|
search |
Busca por número de pedido, referencia externa, SKU o nombre del producto. |
per_page |
Entre 1 y 50. Valor predeterminado: 20. |
curl --request GET \
--url 'https://b2b.onlyforgamer.com/api/v1/orders?search=MI-PEDIDO&per_page=20' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
Consultar un pedido
Devuelve el detalle completo de un pedido,
incluyendo los datos públicos del destinatario
enviados en target_data.
curl --request GET \
--url https://b2b.onlyforgamer.com/api/v1/orders/B2B-01EXAMPLEORDER \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
{
"success": true,
"data": {
"order_number": "B2B-01EXAMPLEORDER",
"external_reference": "MI-PEDIDO-0001",
"status": "processing",
"sku": "PRODUCT-SKU",
"product_name": "Nombre del producto",
"product_type": "topup",
"quantity": 1,
"currency": "USD",
"unit_price": "1.250000",
"total": "1.250000",
"created_at": "2026-08-03T06:45:00+00:00",
"updated_at": "2026-08-03T06:45:03+00:00",
"completed_at": null,
"failed_at": null,
"target_data": {
"player_id": "123456789",
"server_id": "1234",
"player_ip": "203.0.113.10"
}
}
}
Recuperar Gift Cards
Cuando un pedido de tipo
gift_card
está completado y existe una entrega digital
disponible, el endpoint
GET /orders/{orderNumber}
incluye el objeto
delivery.
Ejemplo de respuesta
{
"success": true,
"data": {
"order_number": "B2B-01EXAMPLEORDER",
"status": "completed",
"product_type": "gift_card",
"delivery": {
"status": "delivered",
"card_count": 1,
"delivered_at": "2026-08-28T03:00:00+00:00",
"cards": [
{
"code": "EXAMPLE-CODE-NOT-VALID",
"pin": "0000",
"expires_at": "2027-12-31",
"type": "Gift Card"
}
]
}
}
}
code,
pin,
expires_at y
type cuando esos datos existen.
No se exponen referencias internas
ni payloads operativos.
Las respuestas que contienen una entrega digital
utilizan encabezados de caché restrictivos:
Cache-Control: no-store, private
y
Pragma: no-cache
.
No deben almacenarse en proxies, navegadores ni
cachés intermedias.
Movimientos de saldo
Devuelve el historial financiero del revendedor. Los importes se entregan como strings para conservar la precisión decimal.
| Parámetro | Descripción |
|---|---|
type |
Filtra por tipo de movimiento. |
direction |
Admite debit o
credit.
|
order_number |
Filtra por número exacto de pedido B2B. |
date_from |
Fecha inicial en formato
YYYY-MM-DD.
|
date_to |
Fecha final en formato
YYYY-MM-DD.
|
per_page |
Entre 1 y 100. Valor predeterminado: 25. |
page |
Número de página, mínimo 1. |
curl --request GET \
--url 'https://b2b.onlyforgamer.com/api/v1/wallet-transactions?direction=debit&date_from=2026-08-01&date_to=2026-08-31&per_page=25' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <TU_TOKEN_API>'
{
"success": true,
"data": [
{
"id": 12,
"type": "order_debit",
"direction": "debit",
"currency": "USD",
"amount": "1.250000",
"balance_before": "105.080000",
"balance_after": "103.830000",
"order_number": "B2B-01EXAMPLEORDER",
"reference": "B2B-01EXAMPLEORDER",
"description": "Débito automático por pedido B2B.",
"created_at": "2026-08-03T06:45:00+00:00"
}
],
"meta": {
"current_page": 1,
"per_page": 25,
"last_page": 1,
"total": 1,
"from": 1,
"to": 1
}
}
Tipos de movimiento
order_debit
Débito generado por un pedido.
manual_credit
Crédito agregado manualmente.
refund_credit
Reembolso acreditado al saldo.
manual_adjustment
Ajuste administrativo de saldo.
Estados públicos
Los estados internos son normalizados antes de exponerse a los revendedores.
pending
Pedido creado y fondos reservados.
processing
El pedido está siendo procesado.
completed
Pedido entregado correctamente.
failed
El pedido no pudo completarse.
cancelled
El pedido fue cancelado.
refunded
El importe fue reembolsado.
unknown
Estado no reconocido temporalmente.
GET /orders/{orderNumber}
como respaldo para verificar el estado.
Webhooks
Only For Gamer envía solicitudes
POST
al endpoint HTTPS configurado para el
revendedor cuando cambia el estado público
de un pedido.
Eventos disponibles
order.processing
Pedido en procesamiento.
order.completed
Pedido completado.
order.failed
Pedido fallido.
order.refunded
Pedido reembolsado.
order.cancelled
Pedido cancelado.
integration.test
Evento manual de prueba enviado desde el Centro de desarrolladores.
Payload de un pedido
Los eventos de pedidos contienen solamente
información pública. El webhook nunca incluye
códigos, PIN, target_data
ni payloads operativos.
{
"id": "00000000-0000-4000-8000-000000000000",
"event": "order.completed",
"created_at": "2026-08-28T03:00:00+00:00",
"data": {
"order_number": "B2B-01EXAMPLEORDER",
"external_reference": "MI-PEDIDO-0001",
"status": "completed",
"sku": "PRODUCT-SKU",
"product_name": "Nombre del producto",
"product_type": "gift_card",
"quantity": 1,
"currency": "USD",
"unit_price": "10.000000",
"total": "10.000000",
"delivery_available": true,
"created_at": "2026-08-28T02:59:55+00:00",
"updated_at": "2026-08-28T03:00:00+00:00",
"completed_at": "2026-08-28T03:00:00+00:00",
"failed_at": null
}
}
delivery_available
es true, recuperá la entrega
mediante
GET /api/v1/orders/{order_number}
.
Los códigos y PIN nunca se envían dentro
del webhook.
Encabezados enviados
| Encabezado | Contenido |
|---|---|
X-OFG-Event |
Nombre del evento. |
X-OFG-Delivery |
UUID único de la entrega. |
X-OFG-Timestamp |
Timestamp Unix utilizado para firmar la solicitud. |
X-OFG-Signature |
Firma con formato
sha256=....
|
User-Agent |
OnlyForGamer-Webhook/1.0
|
Validación de la firma
Calculá un HMAC-SHA256 usando el timestamp, un punto y el cuerpo JSON original sin modificar.
HMAC_SHA256(
X-OFG-Timestamp + "." + RAW_JSON_BODY,
WEBHOOK_SECRET
)
<?php
$rawBody = file_get_contents('php://input');
$timestamp =
$_SERVER['HTTP_X_OFG_TIMESTAMP']
?? '';
$receivedSignature =
$_SERVER['HTTP_X_OFG_SIGNATURE']
?? '';
$secret = getenv('OFG_WEBHOOK_SECRET');
$expectedSignature =
'sha256='
. hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
$secret
);
if (
! hash_equals(
$expectedSignature,
$receivedSignature
)
) {
http_response_code(401);
exit('Firma inválida');
}
http_response_code(200);
import crypto from 'node:crypto';
function verifyWebhook({
rawBody,
timestamp,
receivedSignature,
secret,
}) {
const expected =
'sha256=' +
crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(receivedSignature)
);
}
Reintentos
El sistema realiza hasta cinco intentos. Los reintentos automáticos utilizan esperas aproximadas de 1, 5, 15 y 60 minutos.
- Una respuesta HTTP 2xx se considera entregada correctamente.
- HTTP 408, 425, 429 y respuestas 5xx pueden volver a intentarse.
- El endpoint debe responder rápidamente y no depender de redirecciones.
Códigos HTTP
| Código | Significado |
|---|---|
200 |
Consulta correcta o reintento idempotente de un pedido. |
201 |
Pedido creado correctamente. |
401 |
Token ausente o inválido. |
403 |
Permiso insuficiente, cuenta inactiva o API deshabilitada. |
404 |
Pedido no encontrado. |
409 |
Conflicto de idempotencia. |
422 |
Error de validación, saldo insuficiente o producto no disponible. |
429 |
Límite de solicitudes superado. |
500 |
Error interno inesperado. |
Ejemplo de validación
{
"message": "El encabezado Idempotency-Key es obligatorio.",
"errors": {
"idempotency_key": [
"El encabezado Idempotency-Key es obligatorio."
]
}
}
Verificación de cuenta requerida
{
"success": false,
"code": "ACCOUNT_VALIDATION_REQUIRED",
"message": "Primero debés verificar la cuenta del jugador."
}
Ejemplo de límite superado
{
"success": false,
"message": "Se alcanzó temporalmente el límite de consultas de la API.",
"error_code": "API_READ_RATE_LIMIT_EXCEEDED"
}
Buenas prácticas
X-Request-ID.