Entorno y autenticación
GET /api/sandbox y POST /api/sandbox requieren la identidad autenticada de la app. El servidor deriva el dueño de la sesión; el cliente no elige un propietario ni un identificador de usuario. No hay API keys comerciales ni OAuth para integradores. La vinculación de iPhone emite un acceso de dispositivo limitado a la cuenta de pruebas que lo aprueba. Sin identidad, la API responde 401.
La demo pública de este sitio utiliza memoria temporal independiente y no llama a estos endpoints. La app iOS puede vincularse mediante un código temporal aprobado en /app/devices. Después consulta y opera la misma cuenta mediante /api/device/sandbox. Su demo local permanece separada y no se importa al servidor.
Importes y respuesta
Usa centavos enteros positivos, hasta 100,000,000 por operación: 45000 representa MXN 450.00. Un resultado exitoso devuelve { "state": SandboxState }. Los errores devuelven { "error": "mensaje", "code": "ERROR_CODE" }. Las respuestas privadas no se cachean.
Crear un cobro de prueba
Este ejemplo se ejecuta desde la aplicación autenticada, en su mismo origen. Lee primero GET /api/sandbox y envía su accountId en la cabecera X-Plasma-Account; si tu sesión cambia, la operación responde SESSION_CHANGED sin afectar otra cuenta. La documentación es informativa; este botón solo copia texto y no cobra.
const response = await fetch('/api/sandbox', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'charge',
payload: {
amount: 45000,
customer: 'Cliente de prueba',
method: 'card',
description: 'Pedido de prueba'
},
idempotencyKey: 'demo-charge-001',
mode: 'sandbox'
})
});
const result = await response.json();Idempotencia
Cada nueva operación necesita una clave de 8–128 caracteres de [A-Za-z0-9_.:-]. Repetir clave y contenido devuelve el estado persistido con replayed: true, sin repetir el efecto. La misma clave con otro contenido devuelve 409 IDEMPOTENCY_CONFLICT. Un conflicto de concurrencia devuelve 409 CONCURRENT_UPDATE; actualiza el estado y reintenta con la misma clave.
Acciones disponibles
| Acción | Campos del payload |
|---|---|
| charge | amount, customer, method, description |
| chargeCart | items[{productId, quantity}], customer, method |
| refund | transactionId, amount |
| createLink | title, amount |
| toggleLink / payLink | id |
| transfer | amount, recipient, clabe |
| walletTransfer | amount, recipient |
| billPay | amount, service, reference |
| topUp | amount, phone |
| createCustomer | name, email, phone |
| createProduct | name, price, stock, category |
| createSubscription | customer, plan, amount |
| toggleSubscription | id |
| resolveDispute | id |
| submitKyc | legalName, rfc |
| toggleCard | Objeto vacío |
| updateSettings | businessName, email, notifications |
Los métodos de charge son card, spei, qr, link y wallet, todos simulados. chargeCart calcula el importe con el catálogo guardado: no acepta precios o totales del cliente. payLink pertenece al comercio autenticado y no implementa un checkout público.
Límites y errores
Los cuerpos de petición están limitados a 64 KiB y deben usar application/json. Campos desconocidos, credenciales y datos de tarjetas son rechazados. mode solo acepta sandbox; ningún flag habilita dinero real.
Las mutaciones usan almacenamiento atómico, control de versión y registros balanceados. Un incumplimiento del ledger falla con LEDGER_INVARIANT; la capacidad del estado agregado falla con SANDBOX_CAPACITY. Estos controles pertenecen al sandbox y no certifican respaldo externo, carga de producción o resiliencia de una institución financiera.
Próxima integración
API externa versionada, scopes, claves, webhooks durables, SDKs, proveedores y conciliación son trabajo pendiente. Los contratos de acquiring, payouts, issuer, lending e inversión no equivalen a acuerdos comerciales o capacidades activas.