diff --git a/README.md b/README.md index 977d7a4..fa3fd49 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ - [delete](#delete) - [V2 Endpoints](#v2-endpoints) - [Nested actions or resources](#nested-actions-or-resources) + - [Entity onboardings](#entity-onboardings) - [Webhook Signature Validation](#webhook-signature-validation) - [Idempotency Keys](#idempotency-keys) - [Generate the JWS Signature](#gnerate-the-jws-signature) @@ -175,6 +176,92 @@ transfer = client.v2.simulate.receive_transfer( ) ``` +#### 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. + +```python +onboardings = client.v2.entities.onboardings.list(entity_id="ent_8anBwgZktbZH6ydyHa6Tm0eM") +onboarding = client.v2.entities.onboardings.get( + "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", entity_id="ent_8anBwgZktbZH6ydyHa6Tm0eM" +) +``` + +To create one, pass the `type` of onboarding to run (`account_holder` or +`settlement_recipient`) and the onboarding `data`: + +```python +onboarding = client.v2.entities.onboardings.create( + entity_id="ent_8anBwgZktbZH6ydyHa6Tm0eM", + 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. The file can be a path or a binary file-like +object: + +```python +entity_id = "ent_8anBwgZktbZH6ydyHa6Tm0eM" +onboarding_id = "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K" + +client.v2.entities.onboardings.upload_document( + onboarding_id, "tax_registration_certificate", "csf.pdf", entity_id=entity_id +) +client.v2.entities.onboardings.upload_shareholder_document( + onboarding_id, "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "id.png", entity_id=entity_id +) +client.v2.entities.onboardings.upload_legal_representative_document( + onboarding_id, + "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", + "identification", + "id.png", + entity_id=entity_id, +) +``` + +Once every required field and document is complete, `submittable` turns `True` and the +onboarding can be sent for review: + +```python +onboarding = client.v2.entities.onboardings.submit(onboarding_id, entity_id=entity_id) +``` + ### 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/tests/test_integration.py b/tests/test_integration.py index 5232145..c396d6a 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1296,43 +1296,46 @@ def test_v2_entity_onboarding_get(self): def test_v2_entity_onboarding_create(self): """Test creating an onboarding for an entity using v2 API.""" entity_id = "ent_12345" - company_information = {"legal_name": "Acme SpA"} - legal_representatives = [{"first_name": "Ada", "last_name": "Lovelace"}] - transactional_profile = {"monthly_amount_range": "0-1000"} - shareholders = [ - { - "type": "natural_person", - "name": "Ada", - "last_name": "Lovelace", - "holder_id": "1-9", - "nationality": "CL", - "percentage": 100, - } - ] + data = { + "company_information": {"business_activity": "Servicios financieros"}, + "legal_representatives": [{"first_name": "Ada", "last_name": "Lovelace"}], + "transactional_profile": {"monthly_amount_range": "1_500000"}, + "shareholders": [ + { + "type": "natural_person", + "name": "Ada", + "last_name": "Lovelace", + "holder_id": "AAAA010101AAA", + "nationality": "mx", + "percentage": 100, + } + ], + } onboarding = self.fintoc.v2.entities.onboardings.create( entity_id=entity_id, - company_information=company_information, - legal_representatives=legal_representatives, - transactional_profile=transactional_profile, - shareholders=shareholders, + type="account_holder", + data=data, ) assert onboarding.method == "post" assert onboarding.url == f"v2/entities/{entity_id}/onboardings" + assert onboarding.json.type == "account_holder" + assert ( + onboarding.json.data.company_information.business_activity + == data["company_information"]["business_activity"] + ) assert ( - onboarding.json.company_information.legal_name - == company_information["legal_name"] + onboarding.json.data.legal_representatives[0].first_name + == data["legal_representatives"][0]["first_name"] ) assert ( - onboarding.json.legal_representatives[0].first_name - == legal_representatives[0]["first_name"] + onboarding.json.data.transactional_profile.monthly_amount_range + == data["transactional_profile"]["monthly_amount_range"] ) assert ( - onboarding.json.transactional_profile.monthly_amount_range - == transactional_profile["monthly_amount_range"] + onboarding.json.data.shareholders[0].name == data["shareholders"][0]["name"] ) - assert onboarding.json.shareholders[0].name == shareholders[0]["name"] def test_v2_entity_onboarding_submit(self): """Test submitting an onboarding for an entity using v2 API.""" @@ -1443,6 +1446,7 @@ def test_v2_onboarding_objetization(self): "id": "onbprc_12345", "object": "onboarding", "entity_id": "ent_12345", + "type": "account_holder", "status": "in_progress", "source": "api", "submitted_at": None, @@ -1494,6 +1498,7 @@ def test_v2_onboarding_objetization(self): assert isinstance(onboarding, Onboarding) assert onboarding.object == "onboarding" + assert onboarding.type == "account_holder" assert onboarding.status == "in_progress" assert onboarding.submittable is True assert isinstance(