diff --git a/README.md b/README.md index 54053e2..40d1be9 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ - [create](#create) - [update](#update) - [delete](#delete) + - [Entity onboardings](#entity-onboardings) - [Webhook Signature Validation](#webhook-signature-validation) - [Idempotency Keys](#idempotency-keys) - [Serialization](#serialization) @@ -165,6 +166,95 @@ const deletedIdentifier = await fintocClient.webhookEndpoints.delete('we_8anqVLl The `delete` method of the managers deletes an existing instance of the resource using its identifier to find it and returns the identifier. +### Entity onboardings + +[Entity onboardings](https://docs.fintoc.com/reference/entity-onboardings) are nested under an entity, so every call takes the `entity_id` of the entity that owns them. + +```javascript +const entityId = 'ent_8anBwgZktbZH6ydyHa6Tm0eM'; + +const onboardings = await fintocClient.v2.entities.onboardings.list({ entity_id: entityId }); +const onboarding = await fintocClient.v2.entities.onboardings.get( + 'onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K', + { entity_id: entityId }, +); +``` + +To create one, pass the `type` of onboarding to run (`account_holder` or `settlement_recipient`) and the onboarding `data`: + +```javascript +const onboarding = await fintocClient.v2.entities.onboardings.create({ + entity_id: entityId, + type: 'account_holder', + data: { + company_information: { + incorporation_date: '2020-01-15', + business_activity: 'Servicios financieros', + fiscal_address: 'Av. Reforma 123, CDMX', + business_address: 'Av. Insurgentes 456, CDMX', + settlement_account: '646180357600000013', + phone: '+521111111111', + }, + legal_representatives: [ + { + first_name: 'Ada', + last_name: 'Lovelace', + email: 'ada@example.com', + nationality: 'mx', + identification_number: 'AAAA010101HDFAAA01', + position: 'Director General', + }, + ], + transactional_profile: { + resource_origins: ['trusts', 'investments'], + monthly_amount_range: '1_500000', + monthly_operations_range: '1_15000', + }, + shareholders: [ + { + type: 'natural_person', + name: 'Ada', + last_name: 'Lovelace', + nationality: 'mx', + percentage: 100, + holder_id: 'AAAA010101AAA', + }, + ], + }, +}); +``` + +Documents are uploaded one slot at a time, as `multipart/form-data`: + +```javascript +const file = { + data: fs.readFileSync('csf.pdf'), + filename: 'csf.pdf', + contentType: 'application/pdf', +}; +const onboardingId = 'onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K'; + +await fintocClient.v2.entities.onboardings.uploadDocument( + onboardingId, 'tax_registration_certificate', file, { entity_id: entityId }, +); +await fintocClient.v2.entities.onboardings.uploadShareholderDocument( + onboardingId, 'onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K', file, { entity_id: entityId }, +); +await fintocClient.v2.entities.onboardings.uploadLegalRepresentativeDocument( + onboardingId, 'onblr_0ujsswThIGTUYm2K8FjOOfXtY1K', 'identification', file, + { entity_id: entityId }, +); +``` + +Once every required field and document is complete, `submittable` turns `true` and the onboarding can be sent for review: + +```javascript +const submitted = await fintocClient.v2.entities.onboardings.submit( + onboardingId, + { entity_id: entityId }, +); +``` + ### Webhook Signature Validation To ensure the authenticity of incoming webhooks from Fintoc, you should always validate the signature. The SDK provides a `WebhookSignature` class to verify the `Fintoc-Signature` header diff --git a/src/spec/integration.spec.ts b/src/spec/integration.spec.ts index 5e954b0..0bb59c3 100644 --- a/src/spec/integration.spec.ts +++ b/src/spec/integration.spec.ts @@ -1573,35 +1573,47 @@ test('fintoc.v2.entities.onboardings.create()', async (t) => { const entityId = 'ent_12345'; const onboardingData = { entity_id: entityId, - company_information: { legal_name: 'ACME SpA' }, - legal_representatives: [ - { - first_name: 'Jane', - last_name: 'Doe', - email: 'jane@acme.com', - nationality: 'cl', - identification_number: '12.345.678-9', - position: 'Director General', + type: 'account_holder', + data: { + company_information: { business_activity: 'Servicios financieros' }, + legal_representatives: [ + { + first_name: 'Jane', + last_name: 'Doe', + email: 'jane@acme.com', + nationality: 'mx', + identification_number: 'AAAA010101HDFAAA01', + position: 'Director General', + }, + ], + transactional_profile: { + resource_origins: ['trusts', 'investments'], + monthly_amount_range: '1_500000', + monthly_operations_range: '1_15000', }, - ], - transactional_profile: { - resource_origins: ['sales'], - monthly_amount_range: '0-1000', - monthly_operations_range: '0-10', + shareholders: [ + { + type: 'natural_person', + name: 'Jane', + last_name: 'Doe', + holder_id: 'AAAA010101AAA', + nationality: 'mx', + percentage: 100, + }, + ], }, - shareholders: [ - { - type: 'natural_person', name: 'Jane', last_name: 'Doe', holder_id: 'h1', nationality: 'CL', percentage: 100, - }, - ], }; const onboarding = await ctx.fintoc.v2.entities.onboardings.create(onboardingData); t.is(onboarding.method, 'post'); t.is(onboarding.url, `v2/entities/${entityId}/onboardings`); - t.is(onboarding.json.company_information.legal_name, 'ACME SpA'); - t.is(onboarding.json.legal_representatives[0].first_name, 'Jane'); - t.deepEqual(onboarding.json.transactional_profile.resource_origins, ['sales']); + t.is(onboarding.json.type, 'account_holder'); + t.is(onboarding.json.data.company_information.business_activity, 'Servicios financieros'); + t.is(onboarding.json.data.legal_representatives[0].first_name, 'Jane'); + t.deepEqual( + onboarding.json.data.transactional_profile.resource_origins, + ['trusts', 'investments'], + ); }); test('fintoc.v2.entities.onboardings.submit()', async (t) => {