Guía rápida
Tu primer pago de prueba, paso a paso
Realiza un pago de prueba en el entorno Stage después del onboarding y la configuración inicial.
- Stage: sin dinero real
- cURL y Node.js
- Datos de prueba ficticios
Resumen
Tres fases, seis pasos
Todo lo que sigue ocurre en Stage, el sandbox que replica producción. El acceso a producción llega al final, tras las verificaciones del paso 6.
- 01
Configura el acceso
Recibe tus credenciales de Stage, guárdalas en un gestor de secretos y registra las IP de tus servidores.
Pasos 1–2
- 02
Haz tus primeras llamadas
Obtén un token, crea un cobro de prueba y verifica el webhook que lo confirma.
Pasos 3–5
- 03
Sal a producción
Completa la revisión de seguridad y la verificación de tu empresa (KYB) y cambia a credenciales de producción.
Paso 6
Paso 1 de 6
Obtén tus credenciales de Stage
Las credenciales de Stage, un usuario y una contraseña de API para api.stage.localpayment.com, se emiten al iniciar tu alianza con Localpayment. Trátalas como secretos de producción desde el primer día.
- Carga las credenciales desde un gestor de secretos o variables de entorno; nunca las subas al repositorio
- Stage y producción usan credenciales y URL base distintas
- Usa solo datos de prueba ficticios, nunca datos reales de clientes
// Carga las credenciales de Stage desde AWS Secrets Manager al iniciar (AWS SDK v3).
// Sirve cualquier bóveda: lo importante es que los secretos nunca estén en el código.
import { SecretsManagerClient, GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManagerClient({ region: process.env.AWS_REGION });
export async function loadMerchantSecrets() {
const { SecretString } = await client.send(
new GetSecretValueCommand({ SecretId: 'localpayment/stage/api' }),
);
// JSON esperado: { "username": "…", "password": "…", "webhookSecret": "…" }
return JSON.parse(SecretString);
}Paso 2 de 6
Registra las IP de tus servidores
La API solo acepta llamadas desde las direcciones IP que registraste. Agrega las IP de salida de tus servidores en el Business Portal de Stage antes de tu primera solicitud.
- Business Portal → Whitelist your IP
- Las solicitudes desde cualquier otra IP se rechazan
- ¿Serverless o autoescalado? Envía el tráfico saliente por una IP de salida fija (NAT)
- Repite esta configuración en el entorno de producción antes del lanzamiento
- PCI DSS v4.0.1
- SOC 2 Type II
- ISO 27001
- AML/KYC
- TLS 1.2+ · AES-256
Paso 3 de 6
Obtén un token de acceso
Intercambia tu usuario y contraseña de API por un par de JWT. Envía el token de acceso como token Bearer en cada llamada y renuévalo antes de que venza.
- Token de acceso: válido por 5 minutos
- Token de refresco: válido por 24 horas; usa POST /api/token/refresh/
- Guarda los tokens en memoria y nunca los escribas en los registros de la aplicación
# Obtén un token de acceso en Stage (válido por 5 minutos)
curl -X POST https://api.stage.localpayment.com/api/token/ \
-H "Content-Type: application/json" \
-d "{\"username\": \"$LP_API_USER\", \"password\": \"$LP_API_PASSWORD\"}"Paso 4 de 6
Crea un cobro de prueba
Este ejemplo crea un cobro Pix en Brasil. La respuesta devuelve un código QR y un texto Pix Copia e Cola, con estado 100 INPROGRESS hasta que el pagador completa el pago.
- Genera un UUID nuevo como externalId para cada transacción
- Reintentar con el mismo externalId devuelve 409 Conflict en lugar de crear un segundo cobro
- Monto en USD: la respuesta devuelve el monto en BRL que se le cobra al pagador y la cotización aplicada
# Cobro Pix ilustrativo en Stage (Brasil). Valores ficticios;
# consulta docs.localpayment.com para el contrato completo.
curl -X POST https://api.stage.localpayment.com/api/payin/ \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"paymentMethod": { "type": "BankTransfer", "code": "1314", "flow": "DIRECT" },
"externalId": "7c1e2f7a-0000-4000-8000-000000000001",
"country": "BRA",
"currency": "USD",
"amount": 100,
"accountNumber": "<your-account-number>",
"conceptCode": "0003",
"merchant": { "type": "COMPANY", "name": "Nortia Commerce Ltda" },
"payer": {
"type": "INDIVIDUAL",
"name": "Maria",
"lastname": "Silva",
"document": { "type": "CPF", "id": "000.000.000-00" }
}
}'Paso 5 de 6
Procesa el webhook
Cuando el pago se completa, Localpayment envía una notificación firmada a tu endpoint HTTPS. Verifica la firma sobre el cuerpo crudo, responde 200 de inmediato y haz el trabajo de forma asíncrona.
- Registra tu URL en Business Portal → Configurations → Clients → Notifications
- Compara x-Signature con tu propio HMAC-SHA256 usando una comparación de tiempo constante
- Las entregas sin respuesta 200 se reintentan con backoff exponencial
// Receptor Express para webhooks de Localpayment (Node.js 18+).
import crypto from 'node:crypto';
import express from 'express';
import { jobQueue } from './queue.js'; // tu propia cola de trabajos asíncronos
const app = express();
// Carga el secreto del webhook desde tu gestor de secretos al iniciar. Nunca lo escribas en el código.
const WEBHOOK_SECRET = process.env.LP_WEBHOOK_SECRET;
if (!WEBHOOK_SECRET) throw new Error('LP_WEBHOOK_SECRET is not configured');
function hasValidSignature(rawBody, header) {
if (typeof rawBody !== 'string') return false;
// Formato del header: "x-Signature: HMAC-SHA256 <hex>". Quita el prefijo primero.
const received = String(header ?? '').replace(/^HMAC-SHA256\s+/i, '').trim();
if (!/^[0-9a-f]{64}$/i.test(received)) return false;
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(rawBody, 'utf8').digest();
return crypto.timingSafeEqual(Buffer.from(received, 'hex'), expected);
}
// El cuerpo es JSON enviado como Content-Type text/plain: conserva el texto crudo para el HMAC.
app.post('/webhooks/localpayment', express.text({ type: '*/*', limit: '1mb' }), (req, res) => {
if (!hasValidSignature(req.body, req.get('x-signature'))) return res.sendStatus(401);
let event;
try {
event = JSON.parse(req.body);
} catch {
return res.sendStatus(400);
}
res.sendStatus(200); // responde rápido, antes de cualquier trabajo pesado
// Procesa de forma asíncrona. Deduplica por internalId/externalId + estado
// para aplicar una sola vez cada reintento. Nunca registres el payload completo.
jobQueue.enqueue(event);
});Paso 6 de 6
Lista para salir a producción
Las credenciales de producción se emiten solo después de estas verificaciones. Planifícalas desde temprano: ayudan a proteger a cada comercio de la plataforma, incluido el tuyo.
Completa las pruebas en Stage
Cubre los caminos de éxito, rechazo, pendiente y error para cada medio de pago y país que vas a lanzar.
Aprueba la revisión de seguridad
Nuestro equipo revisa y certifica tu integración antes de otorgar el acceso a producción.
Completa la verificación de tu empresa
Cumplimiento verifica tu empresa, sus accionistas y tu caso de uso (KYB) como parte del proceso de incorporación.
Guarda bien las credenciales de producción
Mantenlas en un gestor de secretos, separadas de Stage, y limita el acceso a los servicios que las necesitan.
Registra las IP de producción
Agrega las IP de salida de tus servidores de producción en el Business Portal de producción.
Configura los webhooks de producción
Registra tu endpoint HTTPS de producción y confirma que la verificación de firmas funciona antes de la primera transacción real.
Solución de problemas
Problemas comunes en las primeras llamadas
Recibo 401 Unauthorized. ¿Qué reviso?
Los tokens de acceso vencen a los 5 minutos. Renueva con POST /api/token/refresh/ o pide un token nuevo, y confirma que el encabezado sea Authorization: Bearer seguido del token de acceso.
Mi solicitud se rechaza aunque el token es válido.
Verifica que la IP de salida del servidor que llama esté registrada en el Business Portal de ese entorno. Stage y producción se configuran por separado.
¿Por qué recibí 409 Conflict?
Ese externalId ya se usó. Consulta la transacción existente con GET /api/transactions/{externalId}/status en lugar de crear una nueva.
El cobro sigue en 100 INPROGRESS.
Es lo esperado en medios asíncronos como Pix, transferencias bancarias y cuentas virtuales: el estado cambia cuando el pagador paga y el estado final llega por webhook.
La firma de mi webhook no coincide.
Calcula el HMAC sobre el cuerpo crudo de la solicitud tal como llega, antes de interpretar el JSON, y quita el prefijo "HMAC-SHA256 " del encabezado antes de comparar.
¿Necesitas credenciales de Stage?
Cuéntanos tu caso de uso y tus mercados. Nuestro equipo te acompañará durante la incorporación y emitirá tu acceso a Stage cuando comience la alianza.

Stage: sin dinero real