Documentación de la API
Con la API REST de LisansX puede importar la lista de productos y el stock a su propio sitio, realizar pedidos y recibir los códigos de entrega al instante. A continuación encontrará la autenticación, los endpoints y ejemplos en PHP, Node.js y Python.
Autenticación
Cada solicitud se firma con tres encabezados. Como la firma abarca conjuntamente la marca de tiempo, el método HTTP, la ruta y el cuerpo sin procesar, la solicitud no puede modificarse en tránsito ni reenviarse.
| Encabezado | Valor |
|---|---|
X-Api-Key | Su clave de API |
X-Timestamp | Segundos Unix: debe estar dentro de ±300 s respecto a la hora del servidor |
X-Signature | Firma hexadecimal generada con la fórmula siguiente |
signingKey = sha256_hex(api_secret) signature = hmac_sha256_hex(signingKey, timestamp + "\n" + METHOD + "\n" + path + "\n" + rawBody)
- path: la ruta y la cadena de consulta, si la hay (
/api/v1/products?limit=50). Los parámetros de consulta también forman parte de la firma: firme exactamente la URL que solicita. - rawBody: el JSON exacto que envía; una cadena vacía en las solicitudes GET.
- No vuelva a serializar el cuerpo después de firmarlo: la más mínima diferencia invalida la firma.
Endpoints
| Método | Ruta | Descripción |
|---|---|---|
| GET | /api/v1/products |
Todos los productos a la venta, con sus precios de distribuidor |
| GET | /api/v1/products/{id} |
Detalles de un producto y estado del stock |
| POST | /api/v1/order |
Crear un pedido: si tiene éxito, devuelve los códigos de entrega |
| GET | /api/v1/order/{order_no} |
Estado del pedido y códigos entregados |
| GET | /api/v1/balance |
Su saldo actual |
El límite de solicitudes por minuto se define para cada cuenta de distribuidor. Si se supera, se devuelve 429 rate_limited. Todas las respuestas de error tienen el formato {"success": false, "error": "...", "message": "..."}.
Ejemplos de integración
Listos para copiar y pegar
<?php
final class LisansXClient
{
public function __construct(
private string $baseUrl,
private string $apiKey,
private string $apiSecret
) { $this->baseUrl = rtrim($baseUrl, '/'); }
public function request(string $method, string $path, ?array $body = null): array
{
$method = strtoupper($method);
$bodyRaw = $body !== null ? json_encode($body, JSON_UNESCAPED_UNICODE) : '';
$ts = (string)time();
// Clave de firma = digest SHA-256 en hexadecimal del secret sin procesar
$signingKey = hash('sha256', $this->apiSecret);
$signature = hash_hmac('sha256', $ts . "\n" . $method . "\n" . $path . "\n" . $bodyRaw, $signingKey);
$ch = curl_init($this->baseUrl . $path);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'X-Api-Key: ' . $this->apiKey,
'X-Timestamp: ' . $ts,
'X-Signature: ' . $signature,
'Content-Type: application/json',
],
]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyRaw);
$raw = curl_exec($ch);
return json_decode((string)$raw, true) ?: ['success' => false, 'error' => 'invalid_response'];
}
}
// --- Uso ---
$api = new LisansXClient('https://lisansx.net', 'SU_CLAVE_API', getenv('LISANSX_SECRET'));
$products = $api->request('GET', '/api/v1/products');
$order = $api->request('POST', '/api/v1/order', ['product_id' => 1, 'qty' => 1]);
if (!empty($order['success'])) {
foreach ($order['data']['codes'] as $code) {
echo "Teslim edilen kod: $code\n";
}
} else {
error_log('LisansX hatasi: ' . ($order['message'] ?? 'bilinmiyor'));
}
Errores frecuentes
401 invalid_signature- Es posible que haya omitido derivar la clave de firma como
sha256(secret). 401 invalid_timestamp- El reloj de su servidor está desincronizado. Sincronícelo con NTP.
403 ip_not_allowed- Hay una restricción de IP configurada y su solicitud procede de una IP que no está en la lista.
409 replayed_request- La misma solicitud POST firmada llegó por segunda vez (protección contra repetición). Firme cada solicitud con una marca de tiempo nueva; si va a realizar dos pedidos del mismo producto en el mismo segundo, añada al cuerpo un campo
"nonce"único (p. ej., su propio número de pedido). 429 rate_limited- Ha superado el límite por minuto; distribuya sus solicitudes en el tiempo.
409 out_of_stock- El producto no tiene stock o no está disponible en la cantidad solicitada (el campo
availableindica la cantidad restante). No se crea el pedido ni se descuenta saldo. Compruebe el stock conGET /api/v1/products/{id}antes de cobrar a su propio cliente; el webhookstock.changedle avisa al instante cuando un producto se agota o vuelve a estar disponible. 409 price_changed- Si envió el campo opcional
"max_unit_price"con el pedido y el precio unitario actual lo supera, no se crea el pedido;unit_priceindica el precio actual. 402 delivery_failed- El pedido se creó, pero el producto no pudo entregarse (p. ej., se agotó en origen en el último momento). El importe se reembolsa automáticamente a su saldo.