Contactos y Cuentas Bancarias
Los Contactos representan a tus clientes o proveedores en el sistema Koywe, almacenando su información y cuentas bancarias vinculadas para operaciones de pago.
¿Qué son los Contactos?
Un Contacto es una persona o entidad comercial con la que interactúas a través de pagos:
- Clientes que te pagan (PAYIN)
- Proveedores a los que tú pagas (PAYOUT)
- Ambos en escenarios de marketplace
¿Por qué Usar Contactos?
Rastrea el historial de pagos por cliente o proveedor
Almacena información KYC/cumplimiento (documentos, IDs fiscales)
Vincula cuentas bancarias para pagos recurrentes fáciles
Genera reportes por contacto o tipo de negocio
Estructura de Contacto
Campos Requeridos
{
"firstName": "Juan", // Nombre
"countrySymbol": "CO", // Código de país
"businessType": "PERSON", // PERSON, COMPANY, etc.
"type": "PERSON" // PERSON, BUSINESS, GOVERNMENT, NGO, FOREIGN
}Campos Opcionales
{
"lastName": "Pérez", // Apellido
"email": "cliente@ejemplo.com", // Correo electrónico
"phone": "+573001234567", // Número de teléfono
"documentType": "CC", // Tipo de documento de ID
"documentNumber": "1234567890", // Número de documento de ID (requerido si se provee documentType)
"taxIdType": "NIT", // Tipo de ID fiscal (deprecado, usar documentType)
"taxIdNumber": "900123456", // Número de ID fiscal (deprecado, usar documentNumber)
"address": {
"street": "Calle 123",
"city": "Bogotá",
"state": "Cundinamarca",
"zipCode": "110111",
"country": "CO"
}
}Crear Contactos
Creación Básica de Contacto
async function createContact(token, orgId, merchantId, contactData) {
const response = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts`,
{
firstName: contactData.firstName,
lastName: contactData.lastName, // Opcional
email: contactData.email, // Opcional
phone: contactData.phone, // Opcional
countrySymbol: contactData.countrySymbol,
documentType: contactData.documentType, // Opcional
documentNumber: contactData.documentNumber, // Opcional (requerido si se provee documentType)
businessType: 'PERSON', // o 'COMPANY'
type: 'PERSON' // PERSON, BUSINESS, GOVERNMENT, NGO, FOREIGN
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
// Uso - Crear contacto de cliente
const customer = await createContact(token, orgId, merchantId, {
firstName: 'Juan',
lastName: 'Pérez',
countrySymbol: 'CO',
email: 'cliente@ejemplo.com',
phone: '+573001234567',
documentType: 'CC',
documentNumber: '1234567890'
});
console.log('Contacto creado:', customer.id);def create_contact(token, org_id, merchant_id, contact_data):
response = requests.post(
f'https://api-sandbox.koywe.com/api/v1/organizations/{org_id}/merchants/{merchant_id}/contacts',
json={
'firstName': contact_data['first_name'],
'lastName': contact_data.get('last_name'), # Opcional
'email': contact_data.get('email'), # Opcional
'phone': contact_data.get('phone'), # Opcional
'countrySymbol': contact_data['country'],
'documentType': contact_data.get('document_type'), # Opcional
'documentNumber': contact_data.get('document_number'),# Opcional (requerido si se provee documentType)
'businessType': 'PERSON',
'type': 'PERSON'
},
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)
return response.json()
# Uso
customer = create_contact(token, org_id, merchant_id, {
'first_name': 'Juan',
'last_name': 'Pérez',
'email': 'cliente@ejemplo.com',
'phone': '+573001234567',
'country': 'CO',
'document_type': 'CC',
'document_number': '1234567890'
})curl -X POST 'https://api-sandbox.koywe.com/api/v1/organizations/TU_ORG_ID/merchants/TU_MERCHANT_ID/contacts' \
-H 'Authorization: Bearer TU_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"firstName": "Juan",
"lastName": "Pérez",
"email": "cliente@ejemplo.com",
"phone": "+573001234567",
"countrySymbol": "CO",
"documentType": "CC",
"documentNumber": "1234567890",
"businessType": "PERSON",
"type": "PERSON"
}'Respuesta:
{
"id": "cnt_abc123",
"firstName": "Juan",
"lastName": "Pérez",
"email": "cliente@ejemplo.com",
"phone": "+573001234567",
"countrySymbol": "CO",
"documentType": "CC",
"documentNumber": "1234567890",
"businessType": "PERSON",
"createdAt": "2025-11-13T10:00:00Z",
"merchantId": "mrc_xyz789"
}Tipos de Documento por País
Colombia (CO)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| Cédula de Ciudadanía | CC | ID Nacional | 1234567890 |
| Cédula de Extranjería | CE | ID Extranjero | 1234567 |
| NIT | NIT | ID Fiscal (empresas) | 900123456-1 |
Brasil (BR)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| CPF | CPF | ID Fiscal Individual | 123.456.789-00 |
| CNPJ | CNPJ | ID Fiscal de Empresa | 12.345.678/0001-90 |
México (MX)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| RFC | RFC | ID Fiscal | XAXX010101000 |
| CURP | CURP | Registro de Población | ABCD123456HDFXXX09 |
Chile (CL)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| RUT | RUT | ID Fiscal | 11.111.111-1 |
Argentina (AR)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| DNI | DNI | ID Nacional | 12345678 |
| CUIT | CUIT | ID Fiscal | 20-12345678-9 |
Perú (PE)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| Documento Nacional de Identidad | DNI | ID Nacional | 12345678 |
| Registro Único de Contribuyentes | RUC | ID Fiscal (empresas) | 20123456789 |
| Carné de Extranjería | CED_EXT | ID de Residente Extranjero | 001234567 |
Bolivia (BO)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| Cédula de Identidad | CED_CIU | ID Nacional | 1234567 |
| Número de Identificación Tributaria | NIT | ID Fiscal (empresas) | 1234567890 |
Venezuela (VE)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| Cédula de Identidad | CED_CIU | ID Nacional (prefijo V/E) | V12345678 |
| Número de Identificación Tributaria | NIT | ID Fiscal (empresas, prefijo J/G) | J123456789 |
Estados Unidos (US)
| Tipo de Documento | Código | Descripción | Ejemplo |
|---|---|---|---|
| Employer Identification Number | EIN | ID Fiscal de Empleador | 12-3456789 |
Cuentas Bancarias
Vincular Cuentas Bancarias a Contactos
Para operaciones PAYOUT, necesitas vincular una cuenta bancaria al contacto:
Asociación Automática: Las cuentas bancarias se vinculan automáticamente con la información del contacto. El nombre del titular se toma del firstName y lastName (cuando se proporciona) del contacto. Los códigos bancarios pueden deducirse de los números de cuenta para la mayoría de los países.
Campos Opcionales con Valores por Defecto
| Campo | Tipo | Valor por Defecto | Descripción |
|---|---|---|---|
type | string | VIRTUAL | Tipo de cuenta: SAVINGS, CHECKING, o VIRTUAL. Requerido para Colombia. Opcional para la mayoría de países. |
isVirtual | boolean | false | Si es una cuenta virtual. |
isTracked | boolean | false | Si la cuenta tiene seguimiento para monitoreo de saldo. |
Campos Requeridos por País
| País | entity (código banco) | Notas |
|---|---|---|
| Colombia (CO) | Requerido | Debe proporcionar código de banco |
| Chile (CL) | Requerido | Debe proporcionar código de banco |
| Perú (PE) | Opcional | Auto-deducido del número de cuenta (CCI) |
| Argentina (AR) | Opcional | Auto-deducido de CVU/CBU |
| México (MX) | Opcional | Auto-deducido de CLABE |
| Brasil (BR) | Opcional | Auto-deducido |
async function addBankAccountToContact(token, orgId, merchantId, contactId, bankData) {
const response = await axios.post(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}/accounts`,
{
name: bankData.name,
kind: 'BANK',
isDefault: bankData.isDefault,
countrySymbol: bankData.country,
currencySymbol: bankData.currency,
entity: bankData.entity, // Requerido para CO, CL. Opcional para otros (auto-deducido)
accountNumber: bankData.accountNumber,
type: bankData.type // Requerido para Colombia: 'SAVINGS' o 'CHECKING'
},
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
// Uso - Colombia (entity requerido)
const bankAccountCO = await addBankAccountToContact(token, orgId, merchantId, 'cnt_abc123', {
name: 'Bancolombia COP',
isDefault: true,
country: 'CO',
currency: 'COP',
entity: 'BANCOLOMBIA', // Requerido para Colombia y Chile
accountNumber: '1234567890',
type: 'SAVINGS' // Requerido para Colombia
});
// Uso - Perú (entity auto-deducido del CCI)
const bankAccountPE = await addBankAccountToContact(token, orgId, merchantId, 'cnt_def456', {
name: 'Peru PEN',
isDefault: false,
country: 'PE',
currency: 'PEN',
accountNumber: '00219100012345678901' // CCI de 20 dígitos - código banco auto-deducido
});
console.log('Cuenta bancaria agregada:', bankAccountCO.id);def add_bank_account_to_contact(token, org_id, merchant_id, contact_id, bank_data):
payload = {
'name': bank_data['name'],
'kind': 'BANK',
'isDefault': bank_data['is_default'],
'countrySymbol': bank_data['country'],
'currencySymbol': bank_data['currency'],
'accountNumber': bank_data['account_number']
}
# entity requerido para CO, CL; opcional para otros
if bank_data.get('entity'):
payload['entity'] = bank_data['entity']
# type requerido para Colombia; opcional para otros países (por defecto VIRTUAL)
if bank_data.get('type'):
payload['type'] = bank_data['type']
response = requests.post(
f'https://api-sandbox.koywe.com/api/v1/organizations/{org_id}/merchants/{merchant_id}/contacts/{contact_id}/accounts',
json=payload,
headers={
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
)
return response.json()
# Uso - Colombia (entity requerido)
bank_account_co = add_bank_account_to_contact(token, org_id, merchant_id, 'cnt_abc123', {
'country': 'CO',
'currency': 'COP',
'entity': 'BANCOLOMBIA', # Requerido para Colombia
'account_number': '1234567890',
'type': 'SAVINGS' # Requerido para Colombia
})
# Uso - Chile (entity requerido)
bank_account_cl = add_bank_account_to_contact(token, org_id, merchant_id, 'cnt_ghi789', {
'country': 'CL',
'currency': 'CLP',
'entity': 'BANCO_ESTADO', # Requerido para Chile
'account_number': '12345678901'
})# Colombia - entity (código banco) requerido
curl -X POST 'https://api-sandbox.koywe.com/api/v1/organizations/TU_ORG_ID/merchants/TU_MERCHANT_ID/contacts/cnt_abc123/accounts' \
-H 'Authorization: Bearer TU_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"name": "Bancolombia COP",
"kind": "BANK",
"isDefault": true,
"countrySymbol": "CO",
"currencySymbol": "COP",
"entity": "BANCOLOMBIA",
"accountNumber": "1234567890",
"type": "SAVINGS"
}'Requisitos por País: Consulta Cuentas Externas del Comercio para reglas de validación detalladas por país. Las cuentas bancarias de contactos siguen las mismas validaciones (CLABE para México, CCI para Perú, CVU/CBU para Argentina, etc.).
Recuperar Contactos
Listar Todos los Contactos
async function listContacts(token, orgId, merchantId, options = {}) {
const response = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts`,
{
params: {
search: options.search, // Opcional: buscar por nombre o email
limit: options.limit || 50,
page: options.page || 1
},
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.data;
}
// Uso
const contacts = await listContacts(token, orgId, merchantId, {
search: 'juan',
limit: 20
});
console.log(`Se encontraron ${contacts.length} contactos`);Obtener Contacto Específico
async function getContact(token, orgId, merchantId, contactId) {
const response = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.data;
}
// Uso
const contact = await getContact(token, orgId, merchantId, 'cnt_abc123');
console.log('Contacto:', contact);Obtener Cuentas Bancarias del Contacto
async function getContactBankAccounts(token, orgId, merchantId, contactId) {
const response = await axios.get(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}/accounts`,
{
headers: { 'Authorization': `Bearer ${token}` }
}
);
return response.data;
}
// Uso
const bankAccounts = await getContactBankAccounts(token, orgId, merchantId, 'cnt_abc123');
console.log('Cuentas bancarias:', bankAccounts);Actualizar Contactos
async function updateContact(token, orgId, merchantId, contactId, updates) {
const response = await axios.put(
`https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}`,
updates,
{
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
// Uso - Actualizar teléfono o dirección
const updated = await updateContact(token, orgId, merchantId, 'cnt_abc123', {
phone: '+573009876543',
address: {
street: 'Calle 456',
city: 'Medellín'
}
});Requisitos de Validación
Persona vs Empresa
Para PERSON (individual):
- Usa tipos de documento individual (CC, DNI, CPF, etc.)
businessType:"PERSON"firstNamedel individuo (y opcionalmentelastName)
Para COMPANY (empresa):
- Usa tipos de documento de empresa (NIT, CNPJ, CUIT, etc.)
businessType:"COMPANY"type:"BUSINESS"- Nombre legal de la empresa como
firstName
Formatos de Número de Documento
Los números de documento deben coincidir con el formato esperado para cada país:
- Colombia CC: 6-10 dígitos
- Brasil CPF: 11 dígitos (con o sin formato)
- México RFC: 12-13 caracteres
- Chile RUT: Formato XX.XXX.XXX-X
Mejores Prácticas
Cuándo Crear Contactos
Crear contactos para:
- Clientes haciendo pagos (PAYIN) - para seguimiento y cumplimiento
- Proveedores recibiendo pagos (PAYOUT) - requerido para vinculación de cuenta bancaria
- Transacciones recurrentes con la misma entidad
Reutilizar Contactos
Reutiliza contactos existentes para el mismo cliente/proveedor para:
- Mantener historial de pagos
- Evitar registros duplicados
- Simplificar reconciliación
// Verificar si el contacto existe antes de crear
async function getOrCreateContact(token, orgId, merchantId, email) {
// Intentar encontrar existente
const contacts = await listContacts(token, orgId, merchantId, { search: email });
if (contacts.length > 0) {
return contacts[0]; // Devolver existente
}
// Crear nuevo si no se encuentra
return await createContact(token, orgId, merchantId, {
email: email,
// ... otros campos
});
}Privacidad de Datos
Consideraciones de Seguridad:
- Almacena solo información necesaria
- Sigue regulaciones GDPR/protección de datos
- No almacenes datos sensibles en campos de metadata
- Implementa controles de acceso apropiados
Escenarios Comunes
Escenario 1: Pago de Cliente E-Commerce
// 1. Crear contacto de cliente
const customer = await createContact(token, orgId, merchantId, {
firstName: 'María',
lastName: 'García',
countrySymbol: 'CO',
businessType: 'PERSON',
type: 'PERSON',
email: 'cliente@ejemplo.com',
documentType: 'CC',
documentNumber: '1234567890',
phone: '+573001234567'
});
// 2. Crear orden PAYIN vinculada al contacto
const order = await createPayinOrder(token, orgId, merchantId, {
contactId: customer.id,
amount: 50000,
currency: 'COP',
// ... otros campos
});Escenario 2: Pago a Proveedor
// 1. Crear contacto de proveedor
const provider = await createContact(token, orgId, merchantId, {
firstName: 'Servicios ABC SAS',
countrySymbol: 'CO',
businessType: 'COMPANY',
type: 'BUSINESS',
email: 'proveedor@ejemplo.com',
documentType: 'NIT',
documentNumber: '900123456-1'
});
// 2. Agregar cuenta bancaria del proveedor
const bankAccount = await addBankAccountToContact(token, orgId, merchantId, provider.id, {
name: 'Bancolombia COP',
kind: 'BANK',
isDefault: true,
countrySymbol: 'CO',
currencySymbol: 'COP',
entity: 'BANCOLOMBIA',
accountNumber: '1234567890',
type: 'CHECKING'
});
// 3. Crear orden PAYOUT
const payout = await createPayoutOrder(token, orgId, merchantId, {
contactId: provider.id,
destinationAccountId: bankAccount.id, // Vincular a cuenta bancaria
amount: 500000,
currency: 'COP'
});