PayNode · Developers · OpenAPI 3.1
Generada directamente desde la especificación OpenAPI que sirve la API pública v1 — siempre refleja los endpoints reales. Cada operación incluye método, path, permiso requerido y un ejemplo de curl.
Autenticación
Authorization: Bearer pn_xxxoX-API-Key: pn_xxxServidor
https://www.paynode.com.mxErrores
Formato uniforme: { error: { code, message } }. Rate limit: 60 req/min lecturas, 20 req/min escrituras por comercio (headers X-RateLimit-*).
7 endpoints
/api/v1/linksListar links de pagoLista los links de pago del comercio (excluye siempre status=deleted). Si el caller es un vendedor (JWT operator), solo ve los links que le pertenecen.
permiso: links.readmódulo: mod_payment_linksQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.statustypesearch— Busca en name, short_code y merchant_reference.date_from— ISO 8601. Filtra created_at >= date_from.date_to— ISO 8601. Filtra created_at <= date_to.Ejemplo
curl -X GET "https://www.paynode.com.mx/api/v1/links" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/linksCrear link de pagoEl amount se calcula automáticamente de line_items si no se especifica. Soporta display_currency para mostrar precios en otra moneda (USD, EUR, GBP, CAD) — requiere exchange_rate salvo que se pueda auto-calcular. capture_method='manual' (retención de fondos, operativa hotelera) requiere el módulo mod_preauth activo y es incompatible con subscription_id.
permiso: links.createmódulo: mod_payment_linksEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/links" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "string",
"description": "string",
"amount": 10000,
"type": "single",
"max_uses": 10000,
"expires_at": "2026-01-15T10:00:00Z"
}'/api/v1/links/{id}Obtener link de pago{id} acepta UUID o short_code. Incluye bloque `stats` (pagos totales/exitosos/fallidos, revenue). Si el link expiró, se marca expired automáticamente en esta llamada.
permiso: links.readmódulo: mod_payment_linksEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/links/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/links/{id}Actualizar link de pagoSolo se actualizan los campos presentes en el body. metadata se REEMPLAZA completo (no hace merge). status solo acepta 'active'|'paused' aquí (no 'expired'/'deleted').
permiso: links.updatemódulo: mod_payment_linksEjemplo
curl -X PATCH "https://www.paynode.com.mx/api/v1/links/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"amount": 10000,
"status": "active",
"max_uses": 10000,
"expires_at": "2026-01-15T10:00:00Z"
}'/api/v1/links/{id}Actualizar link de pago (alias de PATCH)Alias de PATCH /v1/links/{id}: mismo handler, misma semántica de actualización parcial (PUT aquí NO es full-replace). Ambos verbos existen por compatibilidad con integradores que esperaban PUT.
permiso: links.updatemódulo: mod_payment_linksEjemplo
curl -X PUT "https://www.paynode.com.mx/api/v1/links/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"amount": 10000,
"status": "active",
"max_uses": 10000,
"expires_at": "2026-01-15T10:00:00Z"
}'/api/v1/links/{id}Eliminar link de pagoSoft delete: status pasa a 'deleted'.
permiso: links.deletemódulo: mod_payment_linksEjemplo
curl -X DELETE "https://www.paynode.com.mx/api/v1/links/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/links/{id}/transactionsTransacciones de un linkTransacciones de un link
permiso: transactions.readmódulo: mod_payment_linksQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.statusdate_from— ISO 8601. Filtra created_at >= date_from.date_to— ISO 8601. Filtra created_at <= date_to.Ejemplo
curl -X GET "https://www.paynode.com.mx/api/v1/links/SU_ID/transactions" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"5 endpoints
/api/v1/checkout/sessionsListar checkout sessionsSesiones pending vencidas se marcan expired automáticamente durante esta llamada (dispara webhook checkout.session.expired).
permiso: checkout.sessions.readmódulo: mod_payment_linksQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.statusdate_from— ISO 8601. Filtra created_at >= date_from.date_to— ISO 8601. Filtra created_at <= date_to.client_reference_idEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/checkout/sessions" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/checkout/sessionsCrear checkout sessionRequiere line_items, subscription_id, o monto abierto (min_amount/max_amount) — mutuamente excluyentes. success_url_delay controla la espera (0-30s, default 1.5) antes de redirigir. metadata no puede usar las claves reservadas internas (pos_terminal_qr, pos_transaction_id, pos_intent_id, pos_order_id, pay_at_table).
permiso: checkout.sessions.createmódulo: mod_payment_linksEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/checkout/sessions" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"line_items": [
{
"product_id": "uuid",
"name": "string",
"description": "string",
"quantity": 1,
"unit_amount": 10000,
"image_url": "string"
}
],
"success_url": "string",
"success_url_delay": 1.5,
"cancel_url": "string",
"mode": "embedded",
"allow_msi": true
}'/api/v1/checkout/sessions/{id}Obtener checkout session{id} acepta UUID o session_id (cs_test_*/cs_live_*). Incluye bloque `payment` con la última transacción asociada.
permiso: checkout.sessions.readmódulo: mod_payment_linksEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/checkout/sessions/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/checkout/sessions/{id}Cancelar checkout sessionÚnico uso soportado: {"status":"cancelled"}. Solo funciona si la sesión está en status=pending.
permiso: checkout.sessions.cancelmódulo: mod_payment_linksEjemplo
curl -X PATCH "https://www.paynode.com.mx/api/v1/checkout/sessions/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"status": "cancelled"
}'/api/v1/checkout/sessions/{id}Cancelar checkout session (alias de PATCH)Alias de PATCH /v1/checkout/sessions/{id}: mismo handler y comportamiento. Existe por compatibilidad con integradores que esperaban PUT.
permiso: checkout.sessions.cancelmódulo: mod_payment_linksEjemplo
curl -X PUT "https://www.paynode.com.mx/api/v1/checkout/sessions/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"status": "cancelled"
}'6 endpoints
/api/v1/productsListar productosListar productos
permiso: products.readmódulo: mod_productsQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.search— Busca en name, sku y description.is_activesort_bysort_orderEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/products" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/productsCrear productoCrear producto
permiso: products.createmódulo: mod_productsEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/products" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"unit_amount": 10000,
"currency": "MXN",
"image_url": "string",
"sku": "string"
}'/api/v1/products/{id}Obtener productoObtener producto
permiso: products.readmódulo: mod_productsEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/products/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/products/{id}Actualizar productoTodos los campos opcionales; solo se actualizan los presentes. El mínimo de unit_amount es $1.00 MXN (100 centavos), igual que en la creación.
permiso: products.updatemódulo: mod_productsEjemplo
curl -X PATCH "https://www.paynode.com.mx/api/v1/products/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"unit_amount": 10000,
"currency": "MXN",
"image_url": "string",
"sku": "string"
}'/api/v1/products/{id}Actualizar producto (alias de PATCH)Alias de PATCH /v1/products/{id}: mismo handler, misma semántica de actualización parcial (PUT aquí NO es full-replace). Existe por compatibilidad con integradores que esperaban PUT.
permiso: products.updatemódulo: mod_productsEjemplo
curl -X PUT "https://www.paynode.com.mx/api/v1/products/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"name": "string",
"description": "string",
"unit_amount": 10000,
"currency": "MXN",
"image_url": "string",
"sku": "string"
}'/api/v1/products/{id}Eliminar productoHard delete (a diferencia de links, que hacen soft delete).
permiso: products.deletemódulo: mod_productsEjemplo
curl -X DELETE "https://www.paynode.com.mx/api/v1/products/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"4 endpoints
/api/v1/transactionsListar transaccionesEl environment lo dicta el token, no el toggle del comercio. Si el caller es un vendedor (JWT operator), solo ve transacciones que él distribuyó.
permiso: transactions.readQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.statussource_typepayment_link_idcheckout_session_idcustomer_emailmerchant_referencecard_branddate_from— ISO 8601. Filtra created_at >= date_from.date_to— ISO 8601. Filtra created_at <= date_to.amount_min— Centavos.amount_max— Centavos.Ejemplo
curl -X GET "https://www.paynode.com.mx/api/v1/transactions" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/transactions/{id}Obtener transacciónDevuelve el objeto completo, incluyendo timeline de NetPay, refunds históricos y remaining_refundable.
permiso: transactions.readEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/transactions/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/transactions/{id}Reembolsar o cancelar transacciónMotor único (executeRefundOrVoid) decide automáticamente entre VOID (cancelación, mismo día antes de las 21:00 CDMX, sin costo) y REFUND (reembolso, días anteriores). Si amount se omite, reembolsa el saldo disponible completo.
permiso: transactions.refundEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/transactions/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"amount": 10000,
"reason": "string"
}'/api/v1/balance_transactionsListar ledger de conciliaciónFeed inmutable de movimientos de dinero (charge/fee/refund) derivado de transactions + transaction_refunds, para conciliar contra tu contabilidad. Paginado por CURSOR (no page/offset). El environment lo dicta el token. Si el caller es un vendedor (JWT operator), solo ve movimientos de transacciones que él distribuyó. Reglas: una fila `charge` se emite por cada transacción con status completed/refunded/partially_refunded (el cargo ocurrió aunque luego se reembolsara); NO se emiten filas para retenciones preauth (authorized/partially_captured) ni para referencias OXXO sin pagar. Una fila `fee` solo existe si la transacción ya tiene commission_snapshot con totalFees>0 — si no, la fila charge trae `fee_pending: true` (no se inventa un fee de 0). Una fila `refund` solo se emite por reembolsos con status=succeeded; los pending/pending_verification NO generan fila y se resumen en `meta.reserved_pending_centavos`. Si el comercio tiene configurado (del lado de PayNode, no vía request) ocultar el desglose de comisiones, la respuesta omite todas las filas `fee` y el campo `fee_pending` de las filas `charge` — no asumas que toda `charge` trae su `fee` pareja.
permiso: balance_transactions.readQuery params
cursor— Cursor opaco de `meta.next_cursor` de la respuesta anterior. Omitir para la primera página.limit— Elementos por página. Máximo 100.typecreated_from— ISO 8601. Filtra created_at >= created_from.created_to— ISO 8601. Filtra created_at <= created_to.Ejemplo
curl -X GET "https://www.paynode.com.mx/api/v1/balance_transactions" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"2 endpoints
/api/v1/customersListar clientesUn 'cliente' se deriva agregando transactions/saved_cards/customer_subscriptions — no existe tabla customers formal.
permiso: customers.readQuery params
page— Número de página (1-based).limit— Elementos por página. Máximo 100.searchsortEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/customers" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/customers/{email}Obtener cliente por emailEl email debe ir URL-encoded en la ruta. NUNCA expone vault_token de las tarjetas guardadas, solo metadata segura.
permiso: customers.readEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/customers/SU_EMAIL" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"3 endpoints
/api/v1/merchant/metricsMétricas del comercioSubset curado del dashboard interno. `period` afecta solo revenue/transactions/churn_rate. Los snapshots de suscripciones (active/trialing/past_due) son al momento; mrr es siempre run-rate de los últimos 30 días fijos, independiente de period.
permiso: merchant.metrics.readQuery params
periodEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/merchant/metrics" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/merchant/metrics/seriesSerie temporal de revenueinterval es 'hour' cuando period=today, si no 'day'. Buckets sin ventas se pre-pueblan en 0. Si el caller es un vendedor (JWT operator), filtra a sus transacciones distribuidas.
permiso: merchant.metrics.readQuery params
periodEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/merchant/metrics/series" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/merchant/payment-rulesReglas de pago del comercioMSI, tarjetas permitidas, límites de monto y métodos de pago soportados. Respuesta cacheable (Cache-Control: private, max-age=300).
permiso: merchant.metrics.readEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/merchant/payment-rules" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"11 endpoints
/api/v1/onboarding/applicationsCrear (o recuperar) el expediente de alta del comercioCreate-or-get: un comercio tiene un único expediente a la vez, así que llamar esto de nuevo simplemente devuelve el existente sin duplicarlo ni reiniciar su progreso. `requirements` en la respuesta indica qué falta según el adaptador del adquirente por defecto del despliegue — fijar un adquirente distinto es una decisión operativa del panel interno, no algo que se elija al crear el expediente.
permiso: onboarding.applications.writeEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/onboarding/applications" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"person_type": null
}'/api/v1/onboarding/applications/{id}Obtener el expediente y sus requisitos pendientesObtener el expediente y sus requisitos pendientes
permiso: onboarding.applications.readEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/onboarding/applications/{id}Actualizar secciones del expediente (negocio, banco, PLD)Actualización PARCIAL: solo se tocan las secciones presentes en el body. `bank` se cifra campo a campo antes de persistir. Solo permitido mientras el expediente no esté en un estado final — el servicio responde 409 invalid_state si ya fue enviado y está en revisión/aprobado.
permiso: onboarding.applications.writeEjemplo
curl -X PATCH "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"person_type": null,
"business": {},
"bank": {},
"pld": {}
}'/api/v1/onboarding/applications/{id}Alias de PATCH (actualización parcial, no full-replace)Idéntico a PATCH — se ofrece PUT por consistencia con el resto de la API v1 (links, products), donde tampoco hace reemplazo completo.
permiso: onboarding.applications.writeEjemplo
curl -X PUT "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/onboarding/applications/{id}/personsAgregar una persona al expedienteRepresentante legal, beneficiario controlador, accionista o contacto. `curp`/`rfc` se cifran antes de persistir. La respuesta incluye el expediente completo con `requirements` recalculado.
permiso: onboarding.applications.writeEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/persons" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"role": null,
"first_name": "string",
"last_name": "string",
"birth_date": "1990-05-20",
"birth_country": "MX",
"nationality": "MX"
}'/api/v1/onboarding/applications/{id}/persons/{pid}Editar una persona del expedienteEditar una persona del expediente
permiso: onboarding.applications.writeEjemplo
curl -X PATCH "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/persons/SU_PID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"role": null,
"first_name": "string",
"last_name": "string",
"birth_date": "string",
"birth_country": "string",
"nationality": "string"
}'/api/v1/onboarding/applications/{id}/persons/{pid}Quitar una persona del expedienteQuitar una persona del expediente
permiso: onboarding.applications.writeEjemplo
curl -X DELETE "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/persons/SU_PID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/onboarding/applications/{id}/documentsRegistrar un documento y obtener su URL de subidaDevuelve `upload_url` (firmada, corta vigencia): el cliente sube el archivo con PUT directo a esa URL y luego llama a `POST .../documents/{document_id}/confirm` para marcarlo recibido. El documento NO cuenta como subido hasta esa confirmación.
permiso: onboarding.applications.writeEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/documents" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"kind": null,
"person_id": "uuid",
"filename": "string",
"mime": "application/pdf",
"size": 10000
}'/api/v1/onboarding/applications/{id}/documents/{document_id}Quitar un documento del expedienteSolo permitido mientras el expediente está en borrador o le falta información — un expediente en revisión/aprobado responde 409.
permiso: onboarding.applications.writeEjemplo
curl -X DELETE "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/documents/SU_DOCUMENT_ID" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/onboarding/applications/{id}/documents/{document_id}/confirmConfirmar que el archivo ya se subió a la URL firmadaLlamar después de completar el PUT a `upload_url`. Marca el documento `uploaded` y recalcula `requirements`.
permiso: onboarding.applications.writeEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/documents/SU_DOCUMENT_ID/confirm" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/onboarding/applications/{id}/submitEnviar el expediente a revisiónExige `requirements.currently_due` vacío — si falta algo, responde 400 validation_error (el expediente es válido, solo incompleto). Si el expediente ya no está en draft/needs_info (ya fue enviado o está resuelto), responde 409 invalid_state. Al enviarse: status pasa a `submitted`, `merchants.onboarding_status` a `pending`, y se dispara el webhook `onboarding.application.submitted`.
permiso: onboarding.applications.submitEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/onboarding/applications/SU_ID/submit" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"3 endpoints
/api/v1/mePerfil del usuario autenticado (app móvil)Requiere EXCLUSIVAMENTE JWT Supabase Bearer (no acepta tokens pn_*). Pensado para la app móvil del vendedor. Devuelve las membresías del usuario donde su rol es 'operator' en comercios no suspendidos.
sin token pn_* — JWT SupabaseEjemplo
curl -X GET "https://www.paynode.com.mx/api/v1/me" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx"/api/v1/devices/register-tokenRegistrar push token del dispositivo (app móvil)Requiere JWT Supabase Bearer (no tokens pn_*). Si el token ya pertenece a otro usuario (reasignación de dispositivo), se reasigna al usuario actual.
sin token pn_* — JWT SupabaseEjemplo
curl -X POST "https://www.paynode.com.mx/api/v1/devices/register-token" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"token": "string",
"platform": "android",
"app_version": "string"
}'/api/v1/devices/register-tokenEliminar push token del dispositivo (app móvil)Requiere JWT Supabase Bearer (no tokens pn_*).
sin token pn_* — JWT SupabaseEjemplo
curl -X DELETE "https://www.paynode.com.mx/api/v1/devices/register-token" \
-H "Authorization: Bearer pn_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"token": "string"
}'