Core Concepts

Contacts & Bank Accounts

Managing customer and provider information

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

1{
2 "email": "customer@example.com", // Mandatory
3 "fullName": "Juan Pérez", // Full legal name
4 "countrySymbol": "CO", // Country code
5 "businessType": "PERSON" // PERSON, COMPANY, etc.
6}

Optional Fields

1{
2 "phone": "+573001234567", // Phone number
3 "documentType": "CC", // ID document type
4 "documentNumber": "1234567890", // ID document number
5 "taxIdType": "NIT", // Tax ID type
6 "taxIdNumber": "900123456", // Tax ID number
7 "address": {
8 "street": "Calle 123",
9 "city": "Bogotá",
10 "state": "Cundinamarca",
11 "zipCode": "110111",
12 "country": "CO"
13 }
14}

Creating Contacts

Basic Contact Creation

1async function createContact(token, orgId, merchantId, contactData) {
2 const response = await axios.post(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts`,
4 {
5 email: contactData.email,
6 phone: contactData.phone,
7 fullName: contactData.fullName,
8 countrySymbol: contactData.country,
9 documentType: contactData.documentType,
10 documentNumber: contactData.documentNumber,
11 businessType: 'PERSON' // or 'COMPANY'
12 },
13 {
14 headers: {
15 'Authorization': `Bearer ${token}`,
16 'Content-Type': 'application/json'
17 }
18 }
19 );
20
21 return response.data;
22}
23
24// Usage - Creating a customer contact
25const customer = await createContact(token, orgId, merchantId, {
26 email: 'customer@example.com',
27 phone: '+573001234567',
28 fullName: 'Juan Pérez',
29 country: 'CO',
30 documentType: 'CC',
31 documentNumber: '1234567890'
32});
33
34console.log('Contact created:', customer.id);

Response:

1{
2 "id": "cnt_abc123",
3 "email": "customer@example.com",
4 "phone": "+573001234567",
5 "fullName": "Juan Pérez",
6 "countrySymbol": "CO",
7 "documentType": "CC",
8 "documentNumber": "1234567890",
9 "businessType": "PERSON",
10 "createdAt": "2025-11-13T10:00:00Z",
11 "merchantId": "mrc_xyz789"
12}

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 fullName. Bank codes can be deduced from account numbers for most countries.

1async function addBankAccountToContact(token, orgId, merchantId, contactId, bankData) {
2 const response = await axios.post(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}/bank-accounts`,
4 {
5 countrySymbol: bankData.country,
6 currencySymbol: bankData.currency,
7 bankCode: bankData.bankCode, // Optional for most countries (deduced)
8 accountNumber: bankData.accountNumber,
9 accountType: bankData.accountType // Required for Colombia: 'checking' or 'savings'
10 },
11 {
12 headers: {
13 'Authorization': `Bearer ${token}`,
14 'Content-Type': 'application/json'
15 }
16 }
17 );
18
19 return response.data;
20}
21
22// Usage
23const bankAccount = await addBankAccountToContact(token, orgId, merchantId, 'cnt_abc123', {
24 country: 'CO',
25 currency: 'COP',
26 bankCode: 'BANCOLOMBIA',
27 accountNumber: '1234567890',
28 accountType: 'savings'
29});
30
31console.log('Bank account added:', bankAccount.id);
32console.log('Holder name auto-linked from contact');

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

Node.js
1async function listContacts(token, orgId, merchantId, options = {}) {
2 const response = await axios.get(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts`,
4 {
5 params: {
6 search: options.search, // Optional: search by name or email
7 limit: options.limit || 50,
8 page: options.page || 1
9 },
10 headers: { 'Authorization': `Bearer ${token}` }
11 }
12 );
13
14 return response.data;
15}
16
17// Usage
18const contacts = await listContacts(token, orgId, merchantId, {
19 search: 'juan',
20 limit: 20
21});
22
23console.log(`Found ${contacts.length} contacts`);

Get Specific Contact

Node.js
1async function getContact(token, orgId, merchantId, contactId) {
2 const response = await axios.get(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}`,
4 {
5 headers: { 'Authorization': `Bearer ${token}` }
6 }
7 );
8
9 return response.data;
10}
11
12// Usage
13const contact = await getContact(token, orgId, merchantId, 'cnt_abc123');
14console.log('Contact:', contact);

Get Contact’s Bank Accounts

Node.js
1async function getContactBankAccounts(token, orgId, merchantId, contactId) {
2 const response = await axios.get(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}/bank-accounts`,
4 {
5 headers: { 'Authorization': `Bearer ${token}` }
6 }
7 );
8
9 return response.data;
10}
11
12// Usage
13const bankAccounts = await getContactBankAccounts(token, orgId, merchantId, 'cnt_abc123');
14console.log('Bank accounts:', bankAccounts);

Updating Contacts

Node.js
1async function updateContact(token, orgId, merchantId, contactId, updates) {
2 const response = await axios.put(
3 `https://api-sandbox.koywe.com/api/v1/organizations/${orgId}/merchants/${merchantId}/contacts/${contactId}`,
4 updates,
5 {
6 headers: {
7 'Authorization': `Bearer ${token}`,
8 'Content-Type': 'application/json'
9 }
10 }
11 );
12
13 return response.data;
14}
15
16// Usage - Update phone number or address
17const updated = await updateContact(token, orgId, merchantId, 'cnt_abc123', {
18 phone: '+573009876543',
19 address: {
20 street: 'Calle 456',
21 city: 'Medellín'
22 }
23});

Validation Requirements

Person vs Company

For PERSON (individual):

  • Use individual document types (CC, DNI, CPF, etc.)
  • businessType: "PERSON"
  • Individual’s full name

For COMPANY (business):

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

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
Node.js
1// Check if contact exists before creating
2async function getOrCreateContact(token, orgId, merchantId, email) {
3 // Try to find existing
4 const contacts = await listContacts(token, orgId, merchantId, { search: email });
5
6 if (contacts.length > 0) {
7 return contacts[0]; // Return existing
8 }
9
10 // Create new if not found
11 return await createContact(token, orgId, merchantId, {
12 email: email,
13 // ... other fields
14 });
15}

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// 1. Create customer contact
2const customer = await createContact(token, orgId, merchantId, {
3 email: 'customer@example.com',
4 fullName: 'María García',
5 country: 'CO',
6 documentType: 'CC',
7 documentNumber: '1234567890',
8 phone: '+573001234567'
9});
10
11// 2. Create PAYIN order linked to contact
12const order = await createPayinOrder(token, orgId, merchantId, {
13 contactId: customer.id,
14 amount: 50000,
15 currency: 'COP',
16 // ... other fields
17});

Scenario 2: Provider Payout

1// 1. Create provider contact
2const provider = await createContact(token, orgId, merchantId, {
3 email: 'provider@example.com',
4 fullName: 'Servicios ABC SAS',
5 country: 'CO',
6 documentType: 'NIT',
7 documentNumber: '900123456-1',
8 businessType: 'COMPANY'
9});
10
11// 2. Add provider's bank account
12const bankAccount = await addBankAccountToContact(token, orgId, merchantId, provider.id, {
13 country: 'CO',
14 currency: 'COP',
15 bankCode: 'BANCOLOMBIA',
16 accountNumber: '1234567890',
17 accountType: 'checking'
18 // holderName auto-linked from provider.fullName
19});
20
21// 3. Create PAYOUT order
22const payout = await createPayoutOrder(token, orgId, merchantId, {
23 contactId: provider.id,
24 destinationAccountId: bankAccount.id, // Link to bank account
25 amount: 500000,
26 currency: 'COP'
27});

Next Steps