La API de InstantPay

Una clave API, una factura, un webhook. Crea una solicitud de pago en EUR o USD, envía al cliente al checkout alojado y recibe un webhook firmado cuando se pague. Esta página se genera a partir del esquema OpenAPI 3 en /openapi.json.

pay.instantnode.eu/v1 Auth por clave API JSON dentro, JSON fuera OpenAPI 3.0.3
20
Endpoints
8
Grupos de recursos
97
Monedas aceptadas
REST / JSON
Sobre HTTPS

Empezar

1

Crea una clave API

En el panel, en API keys. Las claves tienen la forma ik_… y se muestran una sola vez; usa una clave de prueba mientras desarrollas.

2

Envíala en cada petición

Como X-API-Key o Authorization: Bearer. Ambas funcionan igual.

3

Crea una factura y redirige al cliente

La respuesta incluye una checkoutUrl. Cuando el cliente paga, tu webhook recibe invoice.confirmed.

Conviene saber

Los errores son { error, message }. Añade una cabecera Idempotency-Key a POST /invoices para que un reintento nunca cree dos facturas.

bash
$ curl -X POST https://pay.instantnode.eu/v1/invoices \
     -H "X-API-Key: ik_…" -H "Content-Type: application/json" \
     -d '{"amount":"19.99","currency":"EUR","orderId":"order-1042"}'

# 201 Created
{
  "id": "3f9c1b2e-…",
  "status": "created",
  "paid": false,
  "amount": "19.99",
  "currency": "EUR",
  "checkoutUrl": "https://pay.instantnode.eu/pay/57rW…"
}

Guía

Visión general

Con InstantPay tu web acepta pagos en cripto sin que tengas que operar una wallet. Tu cliente paga en SOL, USDC, USDT, ETH, BNB o BTC en una página de checkout alojada por nosotros; tú recibes un webhook firmado y un abono en EUR o USD en tu saldo de InstantPay. Cada pago confirmado cuesta un 1,66 % fijo del importe de la factura. Te pagas a ti mismo a tu propia wallet cuando quieras, en SOL, una stablecoin, ETH, BNB, POL, TRX, BTC o LTC.

Un pago funciona así:

  1. Tu servidor crea una factura con un precio en EUR o USD y recibe una URL de checkout.
  2. El cliente paga en la página de checkout (o en un overlay en tu web): elige una moneda, ve la dirección y el importe exacto, lo envía. El tipo de cambio queda fijado en ese momento.
  3. InstantPay vigila la cadena. En cuanto el pago es definitivo, tu URL de webhook recibe invoice.confirmed.
  4. Tú entregas. El importe de la factura menos la comisión está en tu saldo; solicita un pago en la moneda que elijas cuando quieras.

Lo que necesitas: una cuenta de InstantNode, un servidor que pueda hacer llamadas HTTPS (Node, PHP o cualquier otra cosa) y una URL pública https:// que reciba webhooks. Nunca manejas monedas, direcciones ni tipos de cambio.

Prueba primero el flujo completo: nuestra tienda demo en http://5.230.154.241 es una tienda normal conectada a InstantPay en modo de prueba. Compra algo, paga con el botón «Simulate payment» y mira cómo el pedido pasa a pagado.

Primeros pasos

Seis pasos desde cero hasta una integración en producción. Los pasos 1 a 5 no necesitan aprobación; puedes construir y probar mientras revisamos tu cuenta.

  1. Inicia sesión. Abre pay.instantnode.eu/dashboard e inicia sesión con tu cuenta de InstantNode. Se crea una cuenta de comerciante en estado pending.
  2. Completa tu cuenta. En Account, rellena empresa, web y una breve descripción de lo que vendes, acepta las condiciones y envía. InstantNode lo revisa y te activa, normalmente en un día.
  3. Copia tu clave de prueba. En API keys ya tienes un par de producción y otro de prueba: una clave secreta (sk_test_…, para tu servidor) y una clave pública (pk_test_…, para el navegador). Muestra la clave secreta de prueba y ponla en la configuración de tu servidor, nunca en código del navegador.
  4. Añade un endpoint de webhook. En Webhooks, añade la dirección https:// de tu servidor que debe recibir eventos y pulsa Send test event en la página del endpoint para comprobar que tu verificación de firma funciona.
  5. Haz una compra de prueba. Crea una factura con la clave de prueba (ver abajo), abre la URL de checkout y pulsa Simulate payment. Unos segundos después tu webhook recibe invoice.confirmed con livemode: false.
  6. Pasa a producción. Cuando tu cuenta esté active, cambia el panel al modo producción, muestra la clave secreta de producción (se muestra una vez) y sustituye la de prueba; añade un endpoint de webhook de producción. Las facturas de una clave real se pagan con monedas reales y se abonan en tu saldo.

Formas de integrar

Todas usan la misma API; la única diferencia es dónde paga el cliente. Una regla vale para todas: la factura se crea siempre en tu servidor, nunca en el navegador; de lo contrario tu clave de API queda pública.

Checkout alojado

La forma más sencilla. Tu servidor crea la factura y redirige al cliente a checkoutUrl. Tras el pago, el cliente vuelve a tu redirectUrl. Funciona en cualquier tienda y no necesita JavaScript.

js
// Node (Express) - el SDK es un único archivo: /sdk/node/instapay.mjs
import { InstantPay } from './instapay.mjs';
const pay = new InstantPay({ baseUrl: 'https://pay.instantnode.eu', apiKey: process.env.INSTAPAY_KEY });

app.post('/checkout', async (req, res) => {
  const invoice = await pay.createInvoice({
    amount: '19.99',
    currency: 'EUR',
    orderId: order.id,
    description: 'Camiseta, azul, M',
    redirectUrl: 'https://shop.example/gracias?order=' + order.id,
    cancelUrl: 'https://shop.example/carrito',
  }, order.id);                 // clave de idempotencia: un reintento devuelve la misma factura
  res.redirect(invoice.checkoutUrl);
});
php
// PHP - /sdk/php/InstaPay.php
require 'InstaPay.php';
$pay = new InstantPay('https://pay.instantnode.eu', getenv('INSTAPAY_KEY'));
$invoice = $pay->createInvoice([
  'amount' => '19.99', 'currency' => 'EUR', 'orderId' => (string) $orderId,
  'redirectUrl' => 'https://shop.example/gracias?order=' . $orderId,
], (string) $orderId);
header('Location: ' . $invoice['checkoutUrl']);

Sin nada de código. En Payment links, crea un enlace con importe fijo o importe abierto (lo escribe el cliente, dentro de los límites que fijes), reutilizable o de un solo uso, con caducidad y URL de éxito opcionales. El enlace es una página en https://pay.instantnode.eu/l/<slug> que crea una factura para quien la abre; obtienes la URL, un código QR y un fragmento para incrustar. Cada factura de un enlace lleva paymentLinkId y el id de pedido link:<slug>:<n>, así que el webhook y el abono funcionan exactamente igual. La página del enlace cuenta usos e ingresos y lista sus pagos.

Widget en overlay

El cliente se queda en tu página; el checkout se abre en un overlay. Carga instapay.js y ábrelo con el token, que es la última parte de checkoutUrl y viene de tu servidor. Si prefieres no pasar el token por tu página, el navegador puede obtenerlo con tu clave pública: POST /v1/public/checkout-sessions con { "invoiceId" } responde { token, checkoutUrl } para una factura creada por tu servidor; una clave pública no puede hacer nada más.

html
<script src="https://pay.instantnode.eu/instapay.js"></script>
<script>
  InstantPay.open({
    token: token,                         // último segmento de checkoutUrl
    lang: 'en',                           // o 'de'
    onStatus:  (s) => console.log(s.status),
    onPaid:    (s) => location.href = '/gracias',
    onExpired: (s) => alert('El plazo de pago ha expirado'),
    onClose:   ()  => console.log('cerrado'),
    closeOnPaid: true,
  });
</script>

El widget consulta el estado cada cuatro segundos y llama a onPaid en cuanto el pago se confirma. Aun así, trátalo solo como una cortesía para el cliente: solo el webhook decide si un pedido está pagado.

Tu propia página de pago

Crea la factura, llama a POST /v1/invoices/:id/select con la moneda que eligió el cliente y muestra tú mismo depositAddress y amountExpected. Consulta GET /v1/invoices/:id o espera al webhook.

Crear una factura

POST /v1/invoices con tu clave en la cabecera X-API-Key. Los importes viajan como cadenas; nunca hagas cálculos de dinero con números en coma flotante.

bash
curl -X POST https://pay.instantnode.eu/v1/invoices \
  -H "X-API-Key: sk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001" \
  -d '{
    "amount": "19.99",
    "currency": "EUR",
    "orderId": "ORD-1001",
    "description": "Camiseta, azul, M",
    "redirectUrl": "https://shop.example/gracias?order=1001",
    "cancelUrl": "https://shop.example/carrito",
    "metadata": {"sku": "shirt-blue-m"},
    "ttlSeconds": 1200
  }'
CampoObligatorioSignificado
amountsíPrecio como cadena con como máximo dos decimales, p. ej. "19.99"
currencysíEUR o USD
orderIdnoTu número de pedido. Único por cuenta; el mismo orderId devuelve la misma factura
descriptionnoSe muestra al cliente en el checkout
redirectUrl / cancelUrlnoAdónde va el cliente tras pagar o cancelar
webhookUrlnoSustituye para esta factura la URL de webhook por defecto de tus ajustes
metadatanoCualquier objeto JSON de hasta 4 KB; vuelve en cada webhook
assetnoPreselecciona la moneda (p. ej. USDC_SOL) y omite el selector del checkout
ttlSecondsnoCuánto tiempo se puede pagar la factura: por defecto 1200 (20 minutos), de 60 a 86400
customerEmailnoEl cliente recibe un recibo por correo cuando se confirma el pago; también lo ves en el pago

La respuesta es la factura (201):

json
{
  "id": "f987fead-cbc0-47e1-b9c1-02423c18ec97",
  "orderId": "ORD-1001",
  "status": "created",
  "paid": false,
  "amount": "19.99",
  "currency": "EUR",
  "checkoutUrl": "https://pay.instantnode.eu/pay/Tx7CVPbpJk7IcTkdKMCKCCKt",
  "expiresAt": "2026-09-19T21:20:13.527Z",
  "asset": null, "amountExpected": null, "amountReceived": null, "depositAddress": null
}

Límites: 60 llamadas por minuto y clave (429), como máximo 1000 facturas abiertas a la vez (429 too_many_open_invoices). El mismo Idempotency-Key con un cuerpo distinto responde 409. Los campos que omitas salen de tu configuración de Checkout: tiempo para pagar (ttlSeconds), tolerancia, URL de éxito y de cancelación y las monedas ofrecidas en el checkout.

Webhooks

El webhook es la parte que importa. La redirección tras el pago es solo cosmética: el cliente puede cerrar el navegador y aun así enviar las monedas, así que entrega la mercancía solo cuando haya llegado el evento con paid: true.

En Webhooks añades hasta diez endpoints por modo (las listas de producción y de prueba son independientes). Cada endpoint tiene su propio secreto de firma (whsec_…), una lista de tipos de evento a los que se suscribe (* para todos) y una línea de estado. InstantPay envía un POST con cuerpo JSON a cada endpoint suscrito. La URL debe ser https:// con un nombre de host público; no se siguen redirecciones y tu servidor tiene 10 segundos para responder.

X-InstantPay-Signature: t=1758315600,v1=<hex hmac-sha256>
X-InstantPay-Event: invoice.confirmed
X-InstantPay-Livemode: true
X-InstantPay-Delivery: 42
Idempotency-Key: evt_01K5N3Y7Z2Q8XW6M3R9V4T1B5C

Las mismas cabeceras se envían también con la grafía anterior X-InstaPay-, para que un receptor existente siga funcionando.

Verificar la firma

La firma es un HMAC-SHA256 de "<t>.<cuerpo en bruto>" con el secreto del endpoint (visible en la página del endpoint tras un inicio de sesión reciente). Verifica los bytes en bruto que recibiste, no un objeto reserializado, y rechaza marcas de tiempo de más de cinco minutos.

js
// Node (Express) - verifyWebhook viene del SDK
import { verifyWebhook } from './instapay.mjs';

app.post('/webhooks/instantpay', express.raw({ type: '*/*' }), (req, res) => {
  const raw = req.body.toString('utf8');
  if (!verifyWebhook(process.env.INSTANTPAY_WEBHOOK_SECRET, req.get('x-instantpay-signature'), raw)) {
    return res.status(400).send('bad signature');
  }
  const event = JSON.parse(raw);
  if (event.livemode === false) return res.json({ ok: true });      // un evento de prueba: nunca entregar
  const invoice = event.data.object;
  if (event.type === 'invoice.confirmed' && invoice.paid) markOrderPaid(invoice.orderId);
  res.json({ ok: true });                                            // responde rápido, trabaja después
});
php
// PHP
$raw = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_INSTANTPAY_SIGNATURE'] ?? '';
$event = InstantPay::parseWebhook(getenv('INSTANTPAY_WEBHOOK_SECRET'), $signature, $raw);
if ($event === null) { http_response_code(400); exit('bad signature'); }
if (($event['livemode'] ?? true) === false) { echo 'ok'; exit; }
$invoice = $event['data']['object'];
if ($event['type'] === 'invoice.confirmed' && $invoice['paid']) markOrderPaid($invoice['orderId']);
echo 'ok';

El cuerpo del evento

data.object es el objeto exactamente como lo devuelve GET /v1/invoices/:id (o /v1/payouts/:id), así que un webhook y una lectura nunca se contradicen.

json
{
  "id": "evt_01K5N3Y7Z2Q8XW6M3R9V4T1B5C",
  "object": "event",
  "type": "invoice.confirmed",
  "livemode": true,
  "created": "2026-09-19T21:05:00.000Z",
  "data": {
    "object": {
      "object": "invoice",
      "id": "f987fead-cbc0-47e1-b9c1-02423c18ec97",
      "orderId": "ORD-1001",
      "status": "confirmed",
      "paid": true,
      "livemode": true,
      "amount": "19.99",
      "currency": "EUR",
      "asset": "SOL",
      "amountExpected": "0.206789123",
      "amountReceived": "0.206789123",
      "metadata": {"sku": "shirt-blue-m"},
      "createdAt": "2026-09-19T21:00:13.527Z",
      "expiresAt": "2026-09-19T21:20:13.527Z",
      "confirmedAt": "2026-09-19T21:05:00.000Z"
    }
  }
}
EventoCuándo
invoice.createdLa factura existe
invoice.detectedSe vio una transacción pero aún no es definitiva
invoice.confirmedPagada. paid es true
invoice.overpaidPagada, más de lo necesario; se abona todo lo que llegó. paid es true
invoice.underpaidLlegó demasiado poco; puedes aceptar el pago parcial en el panel
invoice.expiredNo llegó nada antes del plazo
invoice.paid_latePagada después del plazo; ver Comisiones, saldo y pagos
invoice.cancelled / invoice.failedCancelada, o algo salió mal
deposit.confirmedLlegó dinero a la dirección estática de un cliente (función clientes)
payout.paid / payout.failedTerminó un pago a tu wallet; data.object es el pago
refund.paid / refund.failedTerminó un reembolso a un cliente; data.object es el reembolso
account.approved / account.suspendedTu cuenta cambió de estado

Un endpoint también puede configurarse con el cuerpo legacy (event, livemode e invoice / deposit / payout en el nivel superior, priceAmount en lugar de amount), que es lo que reciben las integraciones anteriores a los endpoints; allí invoice.overpaid llega como invoice.confirmed con overpaid: true. Las integraciones nuevas deben usar el formato por defecto.

Reglas para un receptor robusto

  • Responde 2xx en 10 segundos y haz el trabajo real después. Cualquier otra cosa se reintenta con intervalos crecientes (5 s, 20 s, 1 min, 3 min, 10 min, 30 min, 1 h, 2 h, 4 h, 8 h), diez intentos en total, y después la entrega se marca como dead. Un endpoint que falla 20 entregas seguidas durante tres días o más se desactiva y recibes un correo; vuelve a activarlo en su página cuando esté arreglado.
  • Sé idempotente. Hay exactamente un evento por cada cosa que ocurrió, pero una entrega puede repetirse (reintentos, el botón Reenviar). Usa la cabecera Idempotency-Key o event.id para saltarte lo ya procesado.
  • Comprueba livemode. Los eventos de facturas de prueba y del botón Send test event llevan livemode: false. Sirven para probar tu código, nunca para enviar mercancía.
  • En caso de duda, concilia. GET /v1/events lista cada evento de tu cuenta, el más reciente primero, y GET /v1/invoices/:id responde con paid. La pestaña Events del panel muestra la misma lista con cada entrega y un botón Reenviar al endpoint.

Modo de prueba

Una clave de prueba se comporta exactamente como una real, salvo que sus facturas nunca se pagan con monedas. En el checkout, el cliente (es decir, tú) ve un banner «Test mode» con un botón Simulate payment; tu servidor puede hacer lo mismo a través de la API. Las facturas de prueba se abonan en un saldo de prueba separado que solo ves con el interruptor Live/Test del panel en Test; nunca es retirable ni dinero real. Sus webhooks llevan livemode: false.

bash
# pagar una factura de prueba desde tu servidor - "case" puede ser exact, under u over
curl -X POST https://pay.instantnode.eu/v1/invoices/<id>/simulate \
  -H "X-API-Key: sk_test_..." -H "Content-Type: application/json" \
  -d '{"case": "exact"}'

Lista de comprobación antes de pasar a producción:

  • Tu webhook rechaza una firma incorrecta (400) y acepta el evento de prueba del panel.
  • Un pedido solo se marca como pagado tras invoice.confirmed con paid: true y livemode: true.
  • Una entrega repetida no crea un segundo envío.
  • invoice.underpaid e invoice.expired muestran algo razonable al cliente.
  • La clave de prueba se ha sustituido por una clave real en tu configuración y la de prueba está revocada.

Estado de una factura

paid es el campo que hay que mirar: es true para confirmed y overpaid, y false para todo lo demás.

EstadoSignificadopaid
createdCreada, moneda aún no elegidano
awaiting_paymentDirección mostrada, esperando la transferenciano
detectedTransacción vista, aún no definitivano
confirmedPagada y definitivasí
overpaidPagada, más de lo necesariosí
underpaidLlegó demasiado poco; puedes aceptar lo recibido (panel, hasta 7 días tras la caducidad)no
expiredPlazo vencido, no llegó nadano
paid_latePagada después del plazono
cancelled / failedCancelada, o se produjo un errorno

Un cliente que envía un poco menos (hasta un 0,5 %) cuenta igualmente como pagado. Por debajo de eso la factura pasa a underpaid.

Comisiones, saldo y pagos

  • Comisión. Cada pago confirmado se abona en tu saldo en la moneda de la factura menos la comisión de la plataforma, un 1,66 % por defecto. Factura 100.00 € → abono 98.34 €. La comisión se fija al crear la factura, así que un cambio posterior solo afecta a facturas nuevas.
  • Pagada de más. Se te abona todo lo que llegó, al tipo fijado para la factura, menos la comisión. El dinero del cliente es tuyo.
  • Pagada tarde. Hasta 60 minutos después del plazo el pago se abona automáticamente al tipo fijado. Los posteriores te esperan: Aceptar pago tardío en la factura abona lo recibido al tipo actual; la variación del precio desde la factura es tuya.
  • Pagada de menos. No se abona nada por sí solo. Aceptar pago parcial en la factura abona lo recibido al tipo fijado, menos la comisión; posible hasta 7 días después de caducar la factura, después a través del soporte.
  • Saldo. Balance en el panel muestra tres cifras por moneda: disponible (lo que puedes retirar), pendiente (pagos detectados en la cadena pero aún no confirmados) y reservado (retiros y reembolsos abiertos, ya descontados). Debajo, cada apunte: sale, fee, payout, payout_reversal, refund, refund_reversal y adjustment, con saldo acumulado y exportación CSV para tu contabilidad.
  • Reembolsos. Desde una factura pagada, Refund devuelve parte del importe abonado a una dirección que indique el cliente, en la moneda con la que pagó o en tu moneda de retiro. El importe en fiat sale de tu saldo al momento; la comisión de red se descuenta de él y ves las cifras exactas antes de confirmar. Los reembolsos de hasta 200 € de cuentas aprobadas hace 30 días o más salen solos; los mayores los revisa InstantNode. refund.paid / refund.failed llegan como webhooks; GET /v1/refunds los lista. Las facturas de prueba no se pueden reembolsar.
  • Pagos. En Payouts, elige la moneda en la que quieres cobrar (SOL por defecto; también USDC y USDT en Solana, ETH, USDT y USDC en Ethereum, BNB, USDT en BSC, POL, TRX, USDT en TRON, BTC y LTC), guarda tu dirección de wallet para esa moneda y solicita un pago. Tu saldo sigue en EUR/USD; la moneda es solo aquello en lo que se envía el pago. Mínimo 10 € (o $), como máximo 2.000 al día, un pago abierto a la vez. Cada moneda tiene su propia dirección, y una dirección nueva debe tener 24 horas antes de poder recibir un pago. Las solicitudes de hasta 500 € se aprueban automáticamente en un minuto; las mayores las revisa InstantNode. Antes de confirmar, el panel muestra una cotización (tipo, importe en moneda, comisión de red estimada, lo que llega), válida 60 segundos; la comisión de red se descuenta del pago. El importe en cripto se fija de nuevo en la aprobación y se envía a tu wallet. Recibes payout.paid o payout.failed como webhook; el campo payout.asset te dice qué moneda se envió y networkFeeCrypto lo que costó la transferencia.
  • Pagos automáticos. En Payouts fija un umbral, una frecuencia (en cuanto se alcance, como máximo una vez al día, como máximo una vez a la semana) y un importe que se queda en el saldo; la regla solicita pagos por sí sola, marcados como Automático. Desde tu propio sistema, POST /v1/payouts con { "currency": "EUR", "amount": "250.00" } (o "amount": "all") hace exactamente lo que hace el formulario del panel, con las mismas comprobaciones; responde 201 con el objeto de pago, 409 payout_open mientras haya uno abierto y 400 test_mode con una clave de prueba.

Tu cuenta

  • Solicitud. En Cuenta rellenas el perfil de negocio: nombre que ven los clientes, razón social, web, categoría de negocio, país, NIF-IVA (opcional), volumen mensual esperado y qué vendes, y aceptas las condiciones para comerciantes. InstantNode lo revisa, normalmente en un día; recibes un correo en cualquier caso. Las claves de prueba funcionan mientras esperas.
  • Condiciones. Cuando cambian las condiciones recibes un correo y la siguiente visita al panel muestra la nueva versión con una casilla antes de abrir nada más; las claves API y los webhooks siguen funcionando mientras tanto. La versión vigente está siempre en /terms.
  • Notificaciones. En Notificaciones eliges qué correos quieres (pago recibido, pago o reembolso enviado o fallido, endpoint de webhook desactivado, estado de la cuenta, nuevo inicio de sesión desde un dispositivo nuevo), añades hasta 5 destinatarios más y, opcionalmente, un webhook de Discord o Slack que recibe los mismos eventos como mensaje corto.
  • Sesiones. Cuenta lista cada navegador con sesión abierta con dispositivo, IP y última actividad; cierra una o todas las demás. Un inicio de sesión desde un dispositivo que no habíamos visto en tu cuenta se te comunica por correo.
  • Exportación de datos. Crear exportación genera un zip con tu perfil, facturas, libro mayor, pagos, reembolsos, endpoints, eventos y enlaces de pago en JSON. El enlace funciona 60 minutos y se muestra una sola vez; se pide un inicio de sesión reciente.
  • Cerrar la cuenta. Posible cuando el saldo real es cero y no hay ningún pago ni reembolso abierto. Las claves y los endpoints se revocan al momento, todas las sesiones terminan y los registros se conservan durante el periodo de retención.

Referencia de la API

URL base https://pay.instantnode.eu. Toda llamada a /v1 necesita X-API-Key: sk_live_… (o Authorization: Bearer …); una clave anterior a los pares (ik_<id>.<secret>) sigue funcionando. Las claves están en API keys: una clave secreta por modo para tu servidor (acceso completo, se muestra una vez, rotación con 24 h de solapamiento, lista de IP opcional) y una clave pública por modo para el navegador, aceptada solo en GET /v1/public/config, POST /v1/public/checkout-sessions y el estado del checkout. Todo lo demás responde 403 public_key_not_allowed a una clave pública.

ScopePermite
invoices:readLeer facturas, monedas, tu cuenta, saldo, libro mayor y pagos
invoices:writeCrear facturas, preseleccionar una moneda, simular pagos de prueba

Las llamadas de escritura necesitan una cuenta active (403 merchant_not_approved mientras está pendiente, 403 merchant_suspended si está suspendida). Una clave de prueba puede escribir mientras la cuenta aún está pendiente. Leer siempre funciona.

Todos los endpoints con parámetros, cuerpos y respuestas están en la referencia interactiva más abajo. Allí puedes probar peticiones con tu propia clave.

Los errores llegan como JSON con un código error estable:

json
{"error": "invalid_request", "message": "amount: Required", "requestId": "…"}
CódigoHTTPSignificado
unauthorized401Falta la clave o es incorrecta
forbidden403A la clave le falta el scope
public_key_not_allowed403Se usó una clave pública fuera de /v1/public/*
ip_not_allowed403La clave tiene una lista de IP permitidas y esta dirección no está en ella
key_expired401La clave se rotó y su periodo de gracia de 24 h terminó
merchant_not_approved403Cuenta aún no activa; envía la solicitud en el panel
merchant_suspended403Cuenta suspendida; las facturas abiertas se liquidan igualmente
not_found404No existe esa factura para esta clave
invalid_request400Falta un campo o está mal formado
invalid_amount400Importe no positivo o con más de dos decimales
price_currency_not_allowed400Solo EUR y USD
unsafe_webhook_url400No es https, no es un host público o es un destino privado
selection_failed400Moneda no disponible, importe demasiado pequeño o factura vencida
not_test_invoice403Se llamó a simulate sobre una factura real
idempotency_conflict409Mismo Idempotency-Key, cuerpo distinto
too_many_open_invoices429Más de 1000 facturas abiertas
amount_too_large400Por encima del importe máximo por factura fijado para tu cuenta
maintenance503InstantPay está en mantenimiento: las facturas reales nuevas y las solicitudes de retiro se pausan un momento; reintenta pasados los segundos de Retry-After
Too Many Requests429Límite de peticiones; mira la cabecera retry-after
internal_error500Dinos el requestId

SDKs y ejemplos

Todo es un único archivo que copias a tu proyecto; no hay nada que instalar.

  • Node: /sdk/node/instapay.mjs - createInvoice, getInvoice, listInvoices, selectAsset, getMerchant, listLedger, listPayouts, getPayout, createPayout, listRefunds, getRefund, simulatePayment, listEvents, getEvent, verifyWebhook, parseWebhook. El constructor recibe la clave secreta; parseWebhook entiende el cuerpo por defecto y el legacy.
  • PHP: /sdk/php/InstaPay.php - los mismos métodos para PHP 8 (clase InstantPay).
  • Tienda completa: /examples/demo-shop/server.mjs es el código fuente de la tienda demo: productos, checkout alojado, overlay, receptor de webhooks y lista de pedidos en un solo archivo.
  • Overlay en HTML plano: /examples/plain-html.html.
  • WooCommerce: /examples/woocommerce-instapay.php junto con el SDK de PHP en wp-content/plugins/instapay/; introduce URL base, clave y secreto de webhook en WooCommerce → Ajustes → Pagos.

¿Preguntas o una integración atascada? [email protected].

Referencia completa · prueba peticiones en vivo con tu clave