Crear un comercio
POST /api/merchants registra un comercio nuevo. La petición no espera a que el comercio quede escrito: valida el contenido, lo acepta y devuelve un identificador de proceso con el que seguir el resultado.
La petición
Solicitud
curl --request POST \
--url '{URL_BASE}/api/merchants' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {TU_TOKEN}' \
--header 'Idempotency-Key: 8f1c2d3e4a5b6c7d8e9f0a1b' \
--data @merchant.json
Estructura del cuerpo
El cuerpo describe el estado completo del comercio que quieres registrar. Los campos del comercio viajan en la raíz, al lado de las colecciones.
- Name
Campos del comercio- Type
- varios
- is Required
- REQUERIDO
- Description
Identidad, documento, dirección, representante legal, facturación y control comercial. Van directamente en la raíz:
name,brand,document,address… Ver Datos del comercio.
- Name
integrations- Type
- array
- is optional
- Description
Integraciones del comercio con proveedores externos. Ver Integraciones.
- Name
paymentMethods- Type
- array
- is optional
- Description
Medios de pago que el comercio acepta. Ver Medios de pago.
- Name
sites- Type
- array
- is optional
- Description
Sitios de venta del comercio, con sus propias integraciones y medios de pago. Ver Sitios.
- Name
notification- Type
- object
- is optional
- Description
URL donde quieres recibir el resultado del proceso.
Cuerpo mínimo
Estos son todos los campos que Onboarding exige para registrar un comercio. Todo lo demás es opcional.
Cuerpo mínimo
{
"name": "Comercializadora Acme S.A.S.",
"brand": "Acme",
"languages": ["es"],
"currencies": ["COP"],
"document": {
"type": "NIT",
"number": "9001234567"
},
"address": {
"city": "Bogota",
"country": "CO",
"state": 11
},
"legalRepresentative": {
"name": "Ada",
"surname": "Lovelace"
},
"control": {
"reseller": 1
}
}
Cuerpo completo
Un registro real suele incluir también las colecciones. Este ejemplo muestra la forma general; el detalle de cada colección está en su propia página.
Los campos del comercio y las colecciones conviven en el mismo nivel del cuerpo.
Las colecciones son independientes entre sí: puedes enviar solo sites, solo paymentMethods, ambas o ninguna. Cada elemento que envías se registra dentro de la misma operación, de modo que un comercio con sus sitios y sus medios de pago se crea con una sola petición.
El bloque notification es opcional y se explica más abajo.
Cuerpo completo
{
"name": "Comercializadora Acme S.A.S.",
"brand": "Acme",
"active": true,
"url": "https://acme.example.com",
"mcc": "5411",
"size": "M",
"timezone": "America/Bogota",
"languages": ["es", "en"],
"currencies": ["COP", "USD"],
"document": {
"type": "NIT",
"number": "9001234567"
},
"address": {
"street": "Carrera 43A # 1-50, Torre 2",
"city": "Bogota",
"country": "CO",
"state": 11,
"phone": "6013905000",
"postalCode": "110111"
},
"legalRepresentative": {
"name": "Ada",
"surname": "Lovelace",
"documentType": "CC",
"document": "1020304050"
},
"billing": {
"contact": "Contabilidad Acme",
"mail": "[email protected]",
"ciiu": "4791",
"taxType": 1,
"taxRegime": 1,
"organizationType": 1
},
"control": {
"reseller": 1,
"seller": 1
},
"integrations": [
{
"type": "kount",
"settings": {
"sandbox": false,
"website": "ACME",
"merchant": "201000"
}
}
],
"paymentMethods": [
{
"code": "CR_VS",
"financialEntity": 7,
"accountNumber": "1234567890",
"accountType": 2,
"commissionModel": "P",
"commissionValue": 2.5
}
],
"notification": {
"url": "https://acme.example.com/hooks/onboarding"
}
}
La URL de notificación
Si envías notification.url, Onboarding te avisará en esa dirección cuando el proceso termine, tanto si termina bien como si falla.
- Name
notification.url- Type
- string
- is optional
- Description
URL pública sobre
httpsdonde recibirás el webhook, sin credenciales embebidas.
Onboarding valida solo la forma de la URL en el momento de aceptar la petición. La accesibilidad real del destino se comprueba justo antes de cada envío, de modo que una URL que apunte a una red no pública se acepta pero nunca se entrega. El detalle está en Notificación.
La respuesta
Si el contenido es válido, la respuesta es 202.
- Name
status- Type
- object
- is Required
- REQUERIDO
- Description
Estado de la petición. En el
202siempre esOK, y significa que la petición fue aceptada.
- Name
processId- Type
- string
- is Required
- REQUERIDO
- Description
Identificador del proceso. Consérvalo: es con lo que consultarás el resultado.
- Name
action- Type
- string
- is Required
- REQUERIDO
- Description
La operación pedida. En una creación,
merchant.create.
Además, dos headers:
Respuesta
{
"status": {
"status": "OK",
"reason": null,
"message": "The request was accepted and will be processed shortly.",
"date": "2026-08-17T10:14:03-05:00"
},
"processId": "01kz0609xy2hd666mnx6b0jxpc",
"action": "merchant.create",
"result": null,
"notification": {
"url": "https://acme.example.com/hooks/onboarding",
"state": "PENDING",
"attempts": 0
}
}
Un 202 con status.status en OK responde a «¿aceptaste mi petición?», no a «¿ya existe el comercio?». En ese instante el comercio todavía no está registrado y result es null.
Qué hacer después
- Guarda el
processIdasociado a la operación en tu sistema. - Consulta el proceso con
GET /api/processes/{processId}hasta que la respuesta deje de traerRetry-After. - Guarda
result.merchantIdcuando el proceso termine bien.
Si registraste una URL de notificación, puedes esperar el webhook en lugar de consultar — pero mantén la consulta como respaldo, porque la entrega no está garantizada.
Errores de la llamada
Estos errores impiden que la petición se acepte. Ninguno crea un proceso, y por eso ninguno trae processId.
Un 422 incluye un objeto errors hermano de status, con una entrada por cada campo rechazado. Las claves son las rutas del propio cuerpo que enviaste, de modo que puedes localizar el problema sin traducir nada.
Respuesta de error
{
"status": {
"status": "FAILED",
"reason": 422,
"message": "The given data was invalid.",
"date": "2026-08-17T10:14:03-05:00"
},
"errors": {
"name": ["The name field is required."],
"currencies.0": ["The selected currencies.0 is invalid."]
}
}
La validación no se detiene en el primer error: la respuesta enumera todos los problemas encontrados, para que puedas corregirlos de una vez. El catálogo completo de errores está en Errores.
¿Qué sigue?
- Consultar el proceso
- Datos del comercio
- Referencia de la API — el contrato completo, campo a campo