From 184f348667cb7ebc58147f67b1d4dbfc9c187c6c Mon Sep 17 00:00:00 2001 From: Francisca Otero Date: Thu, 5 Nov 2026 12:05:03 +0000 Subject: [PATCH] feat(organizations): add organizations create Co-authored-by: fin-compose[bot] <255610621+fin-compose[bot]@users.noreply.github.com> --- README.md | 20 +++++++++++++ fintoc/core.py | 2 ++ fintoc/managers/__init__.py | 1 + fintoc/managers/organizations_manager.py | 11 +++++++ fintoc/resources/__init__.py | 1 + fintoc/resources/organization.py | 7 +++++ tests/test_integration.py | 38 ++++++++++++++++++++++++ 7 files changed, 80 insertions(+) create mode 100644 fintoc/managers/organizations_manager.py create mode 100644 fintoc/resources/organization.py diff --git a/README.md b/README.md index 3039843..ed34a6a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ - [Entity onboardings](#entity-onboardings) - [Links](#links) - [Payouts](#payouts) + - [Organizations](#organizations) - [Payment methods](#payment-methods) - [Transfer batches](#transfer-batches) - [Webhook Signature Validation](#webhook-signature-validation) @@ -307,6 +308,25 @@ charges = client.payouts.resources.list( ) ``` +#### Organizations + +Partnerships can create an organization for a company they refer. This endpoint only +supports `live` mode and requires the [JWS Signature](#generate-the-jws-signature): + +```python +organization = client.organizations.create( + name="Empresa SpA", + tax_id="111111111", + founder_email="founder@example.com", + products={ + "business_accounts": { + "company_basics": {"incorporation_type": "one_day_company"}, + }, + }, + external_reference="SOL-123", +) +``` + #### Payment methods Mexican direct debit mandates are created with a `multipart/form-data` request, so the diff --git a/fintoc/core.py b/fintoc/core.py index 1c3d140..b623244 100644 --- a/fintoc/core.py +++ b/fintoc/core.py @@ -13,6 +13,7 @@ InvoicesManager, LinkIntentsManager, LinksManager, + OrganizationsManager, PaymentIntentsManager, PaymentLinksManager, PayoutsManager, @@ -84,6 +85,7 @@ def __init__(self, api_key, api_version=None, jws_private_key=None): self.link_intents = LinkIntentsManager("/v1/link_intents", self._client) self.payouts = PayoutsManager("/v1/payouts", self._client) self.tax_statements = TaxStatementsManager("/v1/tax_statements", self._client) + self.organizations = OrganizationsManager("/v1/organizations", self._client) self.v2 = _FintocV2(self._client) diff --git a/fintoc/managers/__init__.py b/fintoc/managers/__init__.py index 3b61a48..c52e8fc 100644 --- a/fintoc/managers/__init__.py +++ b/fintoc/managers/__init__.py @@ -10,6 +10,7 @@ from .link_intents_manager import LinkIntentsManager from .links_manager import LinksManager from .movements_manager import MovementsManager +from .organizations_manager import OrganizationsManager from .payment_intents_manager import PaymentIntentsManager from .payment_links_manager import PaymentLinksManager from .payout_resources_manager import PayoutResourcesManager diff --git a/fintoc/managers/organizations_manager.py b/fintoc/managers/organizations_manager.py new file mode 100644 index 0000000..1b39027 --- /dev/null +++ b/fintoc/managers/organizations_manager.py @@ -0,0 +1,11 @@ +"""Module to hold the organizations manager.""" + +from fintoc.mixins import ManagerMixin + + +class OrganizationsManager(ManagerMixin): + + """Represents an organizations manager.""" + + resource = "organization" + methods = ["create"] diff --git a/fintoc/resources/__init__.py b/fintoc/resources/__init__.py index 2d05872..c46f711 100644 --- a/fintoc/resources/__init__.py +++ b/fintoc/resources/__init__.py @@ -15,6 +15,7 @@ from .link import Link from .link_intent import LinkIntent from .movement import Movement +from .organization import Organization from .other_taxes import OtherTaxes from .payment_intent import PaymentIntent from .payment_link import PaymentLink diff --git a/fintoc/resources/organization.py b/fintoc/resources/organization.py new file mode 100644 index 0000000..de69095 --- /dev/null +++ b/fintoc/resources/organization.py @@ -0,0 +1,7 @@ +"""Module to hold the Organization resource.""" + +from fintoc.mixins import ResourceMixin + + +class Organization(ResourceMixin): + """Represents a Fintoc Organization.""" diff --git a/tests/test_integration.py b/tests/test_integration.py index d2db2ea..66c64cd 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -16,6 +16,7 @@ LinkIntent, MandateDocument, Onboarding, + Organization, PaymentEligibility, PaymentIntent, PaymentMethod, @@ -1720,6 +1721,43 @@ def test_payout_get(self): assert payout.method == "get" assert payout.url == f"v1/payouts/{payout_id}" + def test_organization_create(self): + """Test creating a referred organization.""" + organization_data = { + "name": "Empresa SpA", + "tax_id": "111111111", + "founder_email": "founder@example.com", + "products": { + "business_accounts": { + "company_basics": {"incorporation_type": "one_day_company"}, + "shareholders": [ + {"type": "natural_person", "name": "Test", "percentage": 60} + ], + } + }, + "external_reference": "SOL-123", + "metadata": {"request_id": "abc"}, + } + + organization = self.fintoc.organizations.create(**organization_data) + + assert isinstance(organization, Organization) + assert organization.method == "post" + assert organization.url == "v1/organizations" + assert organization.json.name == organization_data["name"] + assert organization.json.tax_id == organization_data["tax_id"] + assert organization.json.founder_email == organization_data["founder_email"] + business_accounts = organization.json.products.business_accounts + assert business_accounts.company_basics.incorporation_type == ( + "one_day_company" + ) + assert business_accounts.shareholders[0].percentage == 60 + + def test_organizations_only_support_create(self): + """Test that organizations only expose the create operation.""" + with pytest.raises(AttributeError): + self.fintoc.organizations.list() + @pytest.mark.parametrize( "resource_type,klass", [