Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
53 changes: 29 additions & 24 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down
Loading