Skip to Content
Core ConceptsContacts & Bank Accounts

Contacts & Bank Accounts

Contacts represent your customers or providers in the Koywe system, storing their information and linked bank accounts for payment operations.

What are Contacts?

A Contact is a person or business entity that you interact with through payments:

  • Customers who pay you (PAYIN)
  • Providers who you pay (PAYOUT)
  • Both in marketplace scenarios

Why Use Contacts?

📈Tracking

Track payment history per customer or provider

🛡️Compliance

Store KYC/compliance information (documents, tax IDs)

💸Simplified Payouts

Link bank accounts for easy recurring payments

🧾Reporting

Generate reports per contact or business type


Contact Structure

Required Fields

{ "firstName": "Juan", // First name "countrySymbol": "CO", // Country code "businessType": "PERSON", // PERSON, COMPANY, etc. "type": "PERSON" // PERSON, BUSINESS, GOVERNMENT, NGO, FOREIGN }

Optional Fields

{ "lastName": "Pérez", // Last name "email": "customer@example.com", // Email address "phone": "+573001234567", // Phone number "documentType": "CC", // ID document type "documentNumber": "1234567890", // ID document number (required if documentType is provided) "taxIdType": "NIT", // Tax ID type (deprecated, use documentType) "taxIdNumber": "900123456", // Tax ID number (deprecated, use documentNumber) "address": { "street": "Calle 123", "city": "Bogotá", "state": "Cundinamarca", "zipCode": "110111", "country": "CO" } }

Creating Contacts

Basic Contact Creation

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, // Optional email: contactData.email, // Optional phone: contactData.phone, // Optional countrySymbol: contactData.countrySymbol, documentType: contactData.documentType, // Optional documentNumber: contactData.documentNumber, // Optional (required if documentType is provided) businessType: 'PERSON', // or 'COMPANY' type: 'PERSON' // PERSON, BUSINESS, GOVERNMENT, NGO, FOREIGN }, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } } ); return response.data; } // Usage - Creating a customer contact const customer = await createContact(token, orgId, merchantId, { firstName: 'Juan', lastName: 'Pérez', countrySymbol: 'CO', email: 'customer@example.com', phone: '+573001234567', documentType: 'CC', documentNumber: '1234567890' }); console.log('Contact created:', 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'), # Optional 'email': contact_data.get('email'), # Optional 'phone': contact_data.get('phone'), # Optional 'countrySymbol': contact_data['country'], 'documentType': contact_data.get('document_type'), # Optional 'documentNumber': contact_data.get('document_number'),# Optional (required if documentType is provided) 'businessType': 'PERSON', 'type': 'PERSON' }, headers={ 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } ) return response.json() # Usage customer = create_contact(token, org_id, merchant_id, { 'first_name': 'Juan', 'last_name': 'Pérez', 'email': 'customer@example.com', 'phone': '+573001234567', 'country': 'CO', 'document_type': 'CC', 'document_number': '1234567890' })
curl -X POST 'https://api-sandbox.koywe.com/api/v1/organizations/YOUR_ORG_ID/merchants/YOUR_MERCHANT_ID/contacts' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "firstName": "Juan", "lastName": "Pérez", "email": "customer@example.com", "phone": "+573001234567", "countrySymbol": "CO", "documentType": "CC", "documentNumber": "1234567890", "businessType": "PERSON", "type": "PERSON" }'

Response:

{ "id": "cnt_abc123", "firstName": "Juan", "lastName": "Pérez", "email": "customer@example.com", "phone": "+573001234567", "countrySymbol": "CO", "documentType": "CC", "documentNumber": "1234567890", "businessType": "PERSON", "createdAt": "2025-11-13T10:00:00Z", "merchantId": "mrc_xyz789" }

Document Types by Country

Colombia (CO)

Document TypeCodeDescriptionExample
Cédula de CiudadaníaCCNational ID1234567890
Cédula de ExtranjeríaCEForeign ID1234567
NITNITTax ID (companies)900123456-1

Brazil (BR)

Document TypeCodeDescriptionExample
CPFCPFIndividual Tax ID123.456.789-00
CNPJCNPJCompany Tax ID12.345.678/0001-90

Mexico (MX)

Document TypeCodeDescriptionExample
RFCRFCTax IDXAXX010101000
CURPCURPPopulation RegistryABCD123456HDFXXX09

Chile (CL)

Document TypeCodeDescriptionExample
RUTRUTTax ID11.111.111-1

Argentina (AR)

Document TypeCodeDescriptionExample
DNIDNINational ID12345678
CUITCUITTax ID20-12345678-9

Bank Accounts

Linking Bank Accounts to Contacts

For PAYOUT operations, you need to link a bank account to the contact:

Automatic Association: Bank accounts are automatically linked to the contact’s information. The holder name is taken from the contact’s firstName and lastName (when provided). Bank codes can be deduced from account numbers for most countries.

Optional Fields with Defaults

FieldTypeDefaultDescription
typestringVIRTUALAccount type: SAVINGS, CHECKING, or VIRTUAL. Required for Colombia. Optional for most countries.
isVirtualbooleanfalseWhether this is a virtual account.
isTrackedbooleanfalseWhether this account is tracked for balance monitoring.

Country-Specific Required Fields

Countryentity (bankCode)Notes
Colombia (CO)RequiredMust provide bank code
Chile (CL)RequiredMust provide bank code
Peru (PE)OptionalAuto-deduced from account number (CCI)
Argentina (AR)OptionalAuto-deduced from CVU/CBU
Mexico (MX)OptionalAuto-deduced from CLABE
Brazil (BR)OptionalAuto-deduced
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, // Required for CO, CL. Optional for others (auto-deduced) accountNumber: bankData.accountNumber, type: bankData.type // Required for Colombia: 'SAVINGS' or 'CHECKING' }, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } } ); return response.data; } // Usage - Colombia (entity required) const bankAccountCO = await addBankAccountToContact(token, orgId, merchantId, 'cnt_abc123', { name: 'Bancolombia COP', isDefault: true, country: 'CO', currency: 'COP', entity: 'BANCOLOMBIA', // Required for Colombia and Chile accountNumber: '1234567890', type: 'SAVINGS' // Required for Colombia }); // Usage - Peru (entity auto-deduced from CCI) const bankAccountPE = await addBankAccountToContact(token, orgId, merchantId, 'cnt_def456', { name: 'Peru PEN', isDefault: false, country: 'PE', currency: 'PEN', accountNumber: '00219100012345678901' // 20-digit CCI - bank code auto-deduced }); console.log('Bank account added:', 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 required for CO, CL; optional for others if bank_data.get('entity'): payload['entity'] = bank_data['entity'] # type required for Colombia; optional for other countries (defaults to 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() # Usage - Colombia (entity required) bank_account_co = add_bank_account_to_contact(token, org_id, merchant_id, 'cnt_abc123', { 'country': 'CO', 'currency': 'COP', 'entity': 'BANCOLOMBIA', # Required for Colombia and Chile 'account_number': '1234567890', 'type': 'SAVINGS' # Required for Colombia }) # Usage - Chile (entity required) bank_account_cl = add_bank_account_to_contact(token, org_id, merchant_id, 'cnt_ghi789', { 'country': 'CL', 'currency': 'CLP', 'entity': 'BANCO_ESTADO', # Required for Chile 'account_number': '12345678901' })
# Colombia - entity required curl -X POST 'https://api-sandbox.koywe.com/api/v1/organizations/YOUR_ORG_ID/merchants/YOUR_MERCHANT_ID/contacts/cnt_abc123/accounts' \ -H 'Authorization: Bearer YOUR_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "name": "Bancolombia COP", "kind": "BANK", "isDefault": true, "countrySymbol": "CO", "currencySymbol": "COP", "entity": "BANCOLOMBIA", "accountNumber": "1234567890", "type": "SAVINGS" }'

Country-Specific Requirements: See Merchant External Accounts for detailed validation rules by country. Contact bank accounts follow the same validations (CLABE for Mexico, CCI for Peru, CVU/CBU for Argentina, etc.).


Retrieving Contacts

List All Contacts

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, // Optional: search by name or email limit: options.limit || 50, page: options.page || 1 }, headers: { 'Authorization': `Bearer ${token}` } } ); return response.data; } // Usage const contacts = await listContacts(token, orgId, merchantId, { search: 'juan', limit: 20 }); console.log(`Found ${contacts.length} contacts`);

Get Specific Contact

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; } // Usage const contact = await getContact(token, orgId, merchantId, 'cnt_abc123'); console.log('Contact:', contact);

Get Contact’s Bank Accounts

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; } // Usage const bankAccounts = await getContactBankAccounts(token, orgId, merchantId, 'cnt_abc123'); console.log('Bank accounts:', bankAccounts);

Updating Contacts

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; } // Usage - Update phone number or address const updated = await updateContact(token, orgId, merchantId, 'cnt_abc123', { phone: '+573009876543', address: { street: 'Calle 456', city: 'Medellín' } });

Validation Requirements

Person vs Company

For PERSON (individual):

  • Use individual document types (CC, DNI, CPF, etc.)
  • businessType: "PERSON"
  • Individual’s firstName (and optionally lastName)

For COMPANY (business):

  • Use company document types (NIT, CNPJ, CUIT, etc.)
  • businessType: "COMPANY"
  • type: "BUSINESS"
  • Company legal name as firstName

Document Number Formats

Document numbers must match the expected format for each country:

  • Colombia CC: 6-10 digits
  • Brazil CPF: 11 digits (with or without formatting)
  • Mexico RFC: 12-13 characters
  • Chile RUT: Format XX.XXX.XXX-X

Best Practices

When to Create Contacts

Create contacts for:

  • Customers making payments (PAYIN) - for tracking and compliance
  • Providers receiving payments (PAYOUT) - required for bank account linking
  • Recurring transactions with the same entity

Reusing Contacts

Reuse existing contacts for the same customer/provider to:

  • Maintain payment history
  • Avoid duplicate records
  • Simplify reconciliation
// Check if contact exists before creating async function getOrCreateContact(token, orgId, merchantId, email) { // Try to find existing const contacts = await listContacts(token, orgId, merchantId, { search: email }); if (contacts.length > 0) { return contacts[0]; // Return existing } // Create new if not found return await createContact(token, orgId, merchantId, { email: email, // ... other fields }); }

Data Privacy

Security Considerations:

  • Store only necessary information
  • Follow GDPR/data protection regulations
  • Don’t store sensitive data in metadata fields
  • Implement proper access controls

Common Scenarios

Scenario 1: E-Commerce Customer Payment

// 1. Create customer contact const customer = await createContact(token, orgId, merchantId, { firstName: 'María', lastName: 'García', countrySymbol: 'CO', businessType: 'PERSON', type: 'PERSON', email: 'customer@example.com', documentType: 'CC', documentNumber: '1234567890', phone: '+573001234567' }); // 2. Create PAYIN order linked to contact const order = await createPayinOrder(token, orgId, merchantId, { contactId: customer.id, amount: 50000, currency: 'COP', // ... other fields });

Scenario 2: Provider Payout

// 1. Create provider contact const provider = await createContact(token, orgId, merchantId, { firstName: 'Servicios ABC SAS', countrySymbol: 'CO', businessType: 'COMPANY', type: 'BUSINESS', email: 'provider@example.com', documentType: 'NIT', documentNumber: '900123456-1' }); // 2. Add provider's bank account 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. Create PAYOUT order const payout = await createPayoutOrder(token, orgId, merchantId, { contactId: provider.id, destinationAccountId: bankAccount.id, // Link to bank account amount: 500000, currency: 'COP' });

Next Steps

Last updated on