Integración Payments
La integración Payments es una API REST agnóstica de proveedor para las operaciones financieras esenciales que todo backoffice necesita:- Emitir Invoice (cobro) —
POST /payments/invoices. Una Invoice aquí es una solicitud de pago — un cobro recolectado vía PIX, boleto, tarjeta, ACH o SEPA según la región. - Cancelar Invoice —
POST /payments/invoices/{id}/cancel(anula cobros no pagados). - Emitir documento fiscal (NFS-e/NF-e/PEPPOL) —
POST /payments/invoices/{id}/tax-documents. Opcional, específico por región (Brasil hoy, Europa después). También puede ser auto-emitido al crear la Invoice. - Pagar a beneficiario (premio o cualquier payout) —
POST /payments/payouts. - Leer un extracto bancario —
GET /payments/balance-transactions.
cost_center (centro de costos) y contractor_reference (referencia del contratante) los envías en el request; our_number (nuestro número) lo genera SalesOS y se devuelve en el response (y en cada movimiento del extracto). Por debajo, SalesOS rutea la solicitud al proveedor correcto — no necesitas elegir el proveedor a menos que quieras.
Cobro ≠ documento fiscal. Una Invoice es la solicitud de pago (boleto, PIX, tarjeta). El documento fiscal (NFS-e en BR, PEPPOL en UE) es un recurso separado y opcional adjunto a la Invoice. Esta separación mantiene la API portable entre BR / US / UE.
La API sigue convenciones de mercado: modelo REST por recurso, montos en unidades menores enteras, timestamps ISO-8601, RFC 9457 Problem Details para errores, header
Idempotency-Key para reintentos seguros, paginación por cursor y webhooks firmados. Si ya integraste con cualquier API moderna de pagos, te sentirás como en casa.Ruteo por Región
SalesOS elige el backend correcto automáticamente a partir decustomer.country y currency. No necesitas escoger.
| País del cliente | Moneda | Estado | Métodos |
|---|---|---|---|
| BR | BRL | activo | pix, boleto, bolepix, card (card-as-PIX) |
| US | USD | próximamente | card, ach_debit, bank_transfer |
| Estados miembros UE | EUR / local | próximamente | card, sepa_debit, bank_transfer |
| Región | Tipo de documento fiscal | Estado |
|---|---|---|
| BR | nfse (servicios) | activo |
| BR | nfe (productos) | próximamente |
| UE | peppol (e-invoice) | próximamente |
| US | n/a | sales tax via metadata de la Invoice; sin documento fiscal |
Cómo Funciona
- Obtienes una API Key en el Dashboard de SalesOS (Admin > Integraciones > API Keys) con los scopes correctos (
payments:write,payments:read). - Emites Invoices (cobros). SalesOS crea la solicitud de pago en la región del cliente (BR activo; US/UE próximamente). Recibes un artefacto pagable: QR-code/copia-pega PIX, código de barras de boleto, URL de checkout de tarjeta.
- (Opcional) Se adjunta un documento fiscal. Cuando
currency = BRLy configurastax_document.auto_issue: true, SalesOS emite una NFS-e automáticamente tras la confirmación del pago. También puedes llamar aPOST /invoices/{id}/tax-documentsdespués para emitir o reintentar. - Pagas a beneficiarios (empleados, partners, ganadores de premios). SalesOS rutea pagos BRL via PIX y otras monedas via transferencia internacional.
- Lees un extracto unificado — toda factura, payout, comisión y fee de documento fiscal en un único libro mayor, filtrable por
cost_center,our_number,contractor_reference, período y proveedor. - Escuchas webhooks para eventos terminales (
invoice.paid,invoice.canceled,tax_document.issued,payout.paid, …) en lugar de hacer polling.
Inicio Rápido
Obtener tu API Key
Ve a Admin > Integraciones > API Keys en el Dashboard de SalesOS. Crea una nueva clave con los scopes
payments:write y payments:read. Copia la clave — solo se mostrará una vez.Tu clave luce así: sk_live_a1b2c3d4e5f6g7h8i9j0...Emite tu primera Invoice (BR — cobro PIX con NFS-e automática)
Crea un cobro PIX para un cliente brasileño. El bloque opcional Respuesta (201 Created):El status pasa por
tax_document indica a SalesOS que emita la NFS-e automáticamente tras el pago.open → paid (en la confirmación PIX, ~segundos) → tax_document.status: issued (emisión de NFS-e, segundos a minutos). Escucha los webhooks invoice.paid y tax_document.issued en vez de hacer polling.(Opcional) Emite una Invoice para cliente US (próximamente)
Para clientes US/UE SalesOS rutea el cobro hacia el backend internacional. Esta ruta queda en cola tras el onboarding de Play2Sell LLC — las llamadas hoy devuelven Sin bloque
501 provider_not_configured.tax_document — US no tiene documento fiscal nacional. Sales tax va en metadata o futuros line_items. El SSN del cliente no se recoge en este endpoint: los cobros B2C/B2B regulares en EE.UU. no lo requieren. El manejo de SSN/EIN para reporting 1099 (cuando pagas a contractors US) es un flujo separado en Payouts, no en Invoices.Pagar a un beneficiario
Paga a un ganador de premio via PIX (BRL — ruteo automático):Respuesta (201 Created):Recibirás un webhook
payout.paid en segundos en sandbox o en menos de un minuto en producción (PIX).Autenticación
Todas las solicitudes requieren una API Key en el headerAuthorization:
| Propiedad | Detalles |
|---|---|
| Header | Authorization: Bearer sk_live_xxx |
| Scopes | payments:write (crear/cancelar), payments:read (listar/consultar) |
| Límite de solicitudes | Configurable por clave (por defecto: 1000 solicitudes/hora) |
| Formato de clave | sk_live_ (producción) o sk_test_ (pruebas) |
Entornos
- Production
- Staging
URL Base:
https://api.play2sell.comDashboard: https://dashboard.play2sell.comReferencia de Endpoints
Path base:/functions/v1/payments. Todos los endpoints aceptan y devuelven JSON.
Invoices (Cobros)
Una Invoice es un cobro — una solicitud de pago que se recolectará de tu cliente vía PIX, boleto, tarjeta u otro método según la región. La Invoice no incluye un documento fiscal por defecto; ver Tax Documents abajo.POST /functions/v1/payments/invoices — crear un cobro
Cliente que será cobrado.
ISO-3166-1 alpha-2 (
BR, US, DE, …). Decide el ruteo de proveedor.CPF (11 dígitos) o CNPJ (14 dígitos) para BR (obligatorio cuando
tax_document está presente). Para cobros US/UE este campo no es obligatorio — déjalo fuera salvo que tu flujo contable lo necesite. SSN/EIN no se recolectan aquí en cobros normales.Razón social o nombre completo (max 255 caracteres).
Email válido — se usa para recibos y (cuando aplique) la entrega del documento fiscal.
Monto total en unidades menores (ej:
12345 = R$ 123,45). Debe ser positivo.Código ISO-4217. Decide el ruteo de proveedor junto con
customer.country.Descripción que aparece en el artefacto de pago y (cuando se emite) en la discriminación del documento fiscal (max 1000 caracteres).
El campo
description se muestra al pagador. En cobros PIX aparece en la app bancaria/billetera del pagador junto al código QR; en boleto se imprime en el comprobante; en NFS-e va en la discriminación del servicio. Elige un valor que tenga sentido en los tres contextos (ej: "Consultoría — Abril/2026", no "INV-2026-000123 fila-billing-interna").Cómo se recolectará el cobro.
Uno de
pix, boleto, bolepix, card (BR); card, ach_debit, bank_transfer (US — próximamente); card, sepa_debit, bank_transfer (UE — próximamente).Para
pix / boleto / bolepix: tiempo de validez del artefacto. Por defecto 3600 (PIX) / 3 días (boleto).Para
card: a dónde redirigir al cliente tras el checkout.Opcional. Cuando está presente, SalesOS emitirá un documento fiscal automáticamente tras el pago. Hoy solo BR.
Cuando
true, el documento fiscal se emite al transitar a paid. Cuando false (u omitido), usa POST /v1/invoices/{id}/tax-documents después."nfse" (servicios BR — activo), "nfe" (productos BR — próximamente), "peppol" (UE — próximamente).Código municipal de servicio, obligatorio cuando
type="nfse" (ej: "01.05" para consultoría en SP).Código de centro de costos interno (max 64 caracteres). Ver Campos de Control Comunes.
Referencia del contratante — referencia externa del cliente/contrato (max 64 caracteres).
Pares clave-valor libres (max 50 claves, valor max 500 caracteres).
our_number (nuestro número) no va en el request — SalesOS lo genera al emitir y lo devuelve en el response (formato: INV-<AAAA>-<secuencia>). Almacénalo para conciliación.GET /functions/v1/payments/invoices/{id} — consultar
payment_method (QR PIX, código de barras de boleto, URL de checkout) y el resumen inline de tax_document cuando existe.
GET /functions/v1/payments/invoices — listar
Filtros: status (open|paid|canceled|failed), payment_method.type, cost_center, our_number, contractor_reference, created[gte], created[lte]. Paginación por cursor mediante limit (≤ 100), starting_after, ending_before.
POST /functions/v1/payments/invoices/{id}/cancel — anular cobro no pagado
tax_document adjunto en estado issued, el cancelamiento se cascada al documento fiscal cuando el municipio aún está dentro de la ventana de cancelación. De lo contrario devuelve cancellation_window_expired.
El reembolso de cobros pagados no está expuesto en la v1. Si necesitas revertir un pago ya liquidado, contacta al soporte — el equipo puede procesarlo manualmente. Una versión futura de la API podría exponer un flujo de reembolso programático conforme los casos de uso maduren.
Tax Documents (Documentos Fiscales)
Un TaxDocument es el artefacto fiscal adjunto a una Invoice — hoy NFS-e (servicios BR). Tiene su propio ciclo de vida y puede emitirse, consultarse o cancelarse independientemente del cobro subyacente. Usa este recurso cuando optaste por no usarauto_issue al crear la Invoice, cuando un intento de auto-emisión falló y quieres reintentar, o cuando necesitas cancelar solo el documento fiscal.
POST /functions/v1/payments/invoices/{id}/tax-documents — emitir/reintentar
"nfse" hoy. Futuro: "nfe", "peppol".Obligatorio cuando
type="nfse".Metadata libre opcional, persistida en el documento.
tax_document.issued (o tax_document.failed). En éxito el documento trae document_number, xml_url, pdf_url e issued_at.
GET /functions/v1/payments/invoices/{id}/tax-documents/{doc_id} — consultar
POST /functions/v1/payments/invoices/{id}/tax-documents/{doc_id}/cancel — cancelar
cancellation_window_expired se devuelve fuera de la ventana.
Payouts (Pagos a Beneficiarios)
POST /functions/v1/payments/payouts — pagar a un beneficiario
Ruteo automático: currency = "BRL" → PIX cashout; otras monedas → transferencia internacional.
Destinatario del payout.
Nombre completo o razón social (max 255 caracteres).
Documento de identificación fiscal del beneficiario. CPF (11 dígitos) o CNPJ (14 dígitos) para BR; pasaporte o ID fiscal local para internacional. Obligatorio.
Teléfono en formato E.164 (ej:
"+5511999000111"). Obligatorio — usado para AML/KYC y notificaciones de estado del payout.Email opcional. Cuando se provee, los recibos del payout se envían a esta dirección.
Cuenta destino. Para PIX usa
type: "pix" con key_type (cpf|cnpj|email|phone|evp) y key. Para internacional usa type: "bank_transfer" con country, iban o account_number + routing_number según los requisitos bancarios del país de destino.Monto en unidades menores. Debe ser positivo.
ISO-4217. Determina el ruteo de proveedor.
Uno de
"prize", "commission", "vendor_payment", "other".Código de centro de costos (max 64 caracteres).
Referencia del contratante — referencia externa (max 64 caracteres).
Pares clave-valor libres (max 50 claves, valor max 500 caracteres).
our_number (nuestro número) no va en el request — SalesOS lo genera al emitir y lo devuelve en el response (formato: PO-<AAAA>-<secuencia>). Almacénalo para conciliación.GET /functions/v1/payments/payouts/{id} — consultar
GET /functions/v1/payments/payouts — listar
Filtros: status, provider, cost_center, our_number, contractor_reference, created[gte], created[lte]. Paginación por cursor.
POST /functions/v1/payments/payouts/{id}/cancel — cancelar
Disponible solo para transferencias internacionales en estado created / incoming_payment_waiting. PIX es síncrono y final — una vez aceptado no se cancela; emite un payout en sentido opuesto como reverso.
Balance Transactions (Extracto Bancario)
Libro mayor unificado entre proveedores. Solo lectura.GET /functions/v1/payments/balance-transactions — listar
Filtros:
| Filtro | Valores |
|---|---|
account | omie, rinne, wise |
type | charge, payout, fee, adjustment |
cost_center | cualquier string |
our_number | cualquier string |
contractor_reference | cualquier string |
currency | código ISO-4217 |
created[gte] / created[lte] | timestamps ISO-8601 |
GET /functions/v1/payments/balance-transactions/{id} — consultar
Cada movimiento expone:
ID estable del movimiento (
btxn_...).charge | payout | fee | adjustment.Monto en unidades menores con signo. Negativo = salida, positivo = entrada.
ISO-4217.
amount - fee para salidas; amount para entradas.Comisión del proveedor en unidades menores, siempre positiva.
Fecha ISO-8601 de liquidación de los fondos.
Timestamp ISO-8601 del movimiento.
{ resource, id } — apunta a la factura/payout origen.Heredado del recurso de origen.
Heredado del recurso de origen.
Heredado del recurso de origen.
Campos de Control Comunes
Toda Invoice, Payout y Balance Transaction lleva los mismos campos de control. Hacen round-trip enGET y son filtrables en LIST.
| Campo | Dirección | Formato | Max | Indexado | Uso |
|---|---|---|---|---|---|
cost_center | input (obligatorio) | string, FK a tu tabla de centros de costo | 64 | sí | Clasifica cada transacción contra una línea de presupuesto. |
contractor_reference | input (opcional) | string | 64 | sí | Referencia del contratante — referencia externa cliente/contrato (PO, ID de contrato, ID de evento). |
metadata | input (opcional) | Record<string, string> | 50 claves, valor 500 caracteres | no | Libre. Usar con moderación; no indexable. |
our_number | solo output | string, formato <PREFIJO>-<AAAA>-<secuencia> | 64 | sí | Nuestro número — generado por SalesOS al emitir y devuelto en el response. Distinto de id (ULID para uso en la API). Estable, secuencial por tipo de recurso por tenant. Úsalo como clave de conciliación del lado bancario. |
Por qué
our_number lo genera el servidor. En el banking brasileño el cedente asigna el “nuestro número” — pero en esta API SalesOS es el gateway de emisión, así que SalesOS asigna el valor y lo devuelve. Si necesitas llevar tu identificador interno, usa contractor_reference (top-level, indexado) o metadata.* (libre).Idempotencia
Todos los endpointsPOST requieren el header Idempotency-Key — una cadena única a tu elección (max 255 caracteres; recomendamos UUIDv4 o una clave determinística derivada de tu dominio).
- La primera llamada con la clave procesa normalmente y la respuesta se almacena por 24 h.
- Reintentos con la misma clave y el mismo body devuelven la misma respuesta, con el header
Idempotent-Replay: true. - Reintentos con la misma clave pero body distinto devuelven
409 idempotency_key_reused.
Montos y Moneda
Los montos son enteros en unidades menores para evitar errores de punto flotante:| Moneda | Unidad menor | 12345 significa |
|---|---|---|
BRL | centavo | R$ 123,45 |
USD | cent | US$ 123.45 |
EUR | cent | €123,45 |
amount con currency. Rechaza en el servidor cualquier payload que mezcle escalas (ej: enviar decimales).
Manejo de Errores
Todos los errores siguen RFC 9457 Problem Details:400 — bad_request
400 — bad_request
JSON malformado o headers obligatorios ausentes. Corrige la solicitud y reenvía.
401 — unauthorized
401 — unauthorized
403 — insufficient_scope
403 — insufficient_scope
Clave válida pero sin el scope requerido (
payments:write o payments:read). Edita la clave en el Dashboard.404 — not_found
404 — not_found
El ID del recurso no existe o pertenece a otro tenant.
409 — idempotency_key_reused
409 — idempotency_key_reused
Misma
Idempotency-Key usada con body distinto. Usa una clave nueva o reenvía el body original.422 — validation_error
422 — validation_error
Validación del body falló. El array
errors[] lista los problemas a nivel de campo.429 — rate_limited
429 — rate_limited
Demasiadas solicitudes. El header
Retry-After indica los segundos a esperar.502 — provider_error
502 — provider_error
El backend downstream devolvió error. El campo
detail contiene un mensaje sanitizado. Reenvía con la misma Idempotency-Key.500 — server_error
500 — server_error
Error interno. Reenvía con backoff exponencial (2s, 4s, 8s). Contacta al soporte si persiste.
Webhooks
Configura un endpoint de webhook por entorno en Admin > Integraciones > Webhooks. SalesOS hará POST con JSON firmado para cada evento terminal:| Evento | Recurso | Disparado cuando |
|---|---|---|
invoice.paid | invoice | Cobro confirmado pagado por el proveedor |
invoice.canceled | invoice | Cobro no pagado anulado |
invoice.failed | invoice | Cobro falló definitivamente (ej: tarjeta rechazada, boleto expirado) |
tax_document.issued | tax_document | Documento fiscal aceptado por el municipio |
tax_document.canceled | tax_document | Cancelamiento del documento fiscal aceptado |
tax_document.failed | tax_document | Emisión falló definitivamente |
payout.paid | payout | Fondos confirmados como entregados |
payout.failed | payout | Proveedor rechazó la transferencia |
payout.canceled | payout | Cancelamiento aceptado (solo transferencias internacionales) |
X-Pay-Event— tipo del evento (ej:payout.paid).X-Pay-Signature—t=<unix>,v1=<hex-hmac-sha256>. Verifica con el secreto configurado en el Dashboard.X-Pay-Delivery— ID único de entrega, útil para deduplicación.
Ejemplos Completos de Código
Mejores Prácticas
Higiene de centros de costos
Elige un conjunto pequeño y estable de códigos (≤ 50). Documéntalos en el wiki de finanzas. Rechaza en el servidor llamadas que referencien códigos desconocidos — fallar ruidosamente es mejor que clasificar mal en silencio.Usa ambas claves juntas para conciliación
our_number(generado por el servidor) es tu clave bancaria — impreso en el boleto / enviado al proveedor, presente en tu archivo de extracto bancario.contractor_reference(lo proporcionas) es tu clave de contrato — el PO, ID de contrato con vendor o ID del evento referente; presente en tu ERP.
Ruteo por región
SalesOS rutea automáticamente porcustomer.country y currency. No necesitas escoger backend; confía en el ruteo.
Confiabilidad de webhooks
Trata los webhooks como fuente de verdad para estados terminales. El polling funciona pero consume rate limit. Verifica siempreX-Pay-Signature y deduplica por X-Pay-Delivery.
Manejo de fallos
- 422: corrige los datos y reenvía con
Idempotency-Keynueva. - 429: espera según
Retry-After. - 502 (provider_error): reenvía con la misma
Idempotency-Key— la solicitud original no hizo commit, así que reintentar es seguro. - 5xx: backoff exponencial (2s, 4s, 8s). Contacta al soporte si persiste.
Límites de Solicitudes
Cada API key tiene un límite configurable (por defecto: 1000 solicitudes por hora). El contador se reinicia cada hora.| Límite | Valor |
|---|---|
| Solicitudes por hora (por defecto) | 1000 |
| Tamaño máximo del payload | 1 MB |
| Tamaño máximo de página en listas | 100 |
| Timeout por solicitud | 60 segundos |
Retry-After (segundos).
Seguridad
- Las API keys se hashean con bcrypt — nunca se almacenan en texto plano.
- Cada clave está limitada a un único tenant — sin acceso entre tenants.
- Se pueden configurar listas de IPs permitidas por clave.
- Todas las solicitudes se registran con fines de auditoría (inmutable, retención de 7 años).
- Las claves pueden revocarse instantáneamente desde el Dashboard.
Próximos Pasos
Autenticación
Aprende a crear y administrar API Keys
Integración Activities
Envía actividades de CRM a SalesOS
Soporte
¿Necesitas ayuda? Contacta a nuestro equipo de soporte

