# Account holder onboarding Source: https://docs.fintoc.com/guides/business-accounts/entities/account-holder-onboarding The `data` schema and document slots for `account_holder` onboardings in Chile and Mexico, with the request shape, validation errors, and examples. `account_holder` is the onboarding type for opening a client `Entity` as an account holder. After Fintoc approves the review, the `Entity` can own `Account` objects. This page documents the schema you send in `data` when you create an `account_holder` onboarding and the document slots the onboarding opens, for each country. For the end-to-end flow, from creating the `Entity` to submitting for review, follow [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api). This page covers only what is specific to the `account_holder` type. > [!NOTE] > > **Availability** > > `account_holder` supports companies in Chile and Mexico. The `Entity`'s `country_code` selects the schema: see [Chile](#chile) or [Mexico](#mexico). Creating an `account_holder` onboarding for an `Entity` in any other country returns `422 Unprocessable Entity` with the code `country_not_supported`. An `Entity` whose `holder_id` identifies an individual returns `422 Unprocessable Entity` with the code `holder_type_not_supported`. ## The request shape Send `type` and `data` at the top level of the create request. The keys inside `data` depend on the country, and every key is required: ```json Chile theme={null} { "type": "account_holder", "data": { "company_basics": { }, "company_information": { }, "senior_management": { "senior_management": [ ] }, "legal_representatives": [ ], "shareholders": [ ], "transactional_profile": { }, "plaft": { } } } ``` ```json Mexico theme={null} { "type": "account_holder", "data": { "company_information": { }, "legal_representatives": [ ], "transactional_profile": { }, "shareholders": [ ] } } ``` The API reference describes `data` as a free-form object, because its shape depends on `type` and on the country; this page is the schema for `account_holder`. ### Validation errors A request with invalid data returns `400 Bad Request` with a single error, even when several fields fail. Fix the reported field and resend to find the next one. `param` names the failing field with its full path, using a dot for each nested key and brackets for each array index, such as `legal_representatives[0].email`. Some errors carry a `code`: | `code` | Cause | | :- | :- | | `invalid_enum` | A value outside the accepted list. The error lists the accepted values. | | `invalid_rut` | A Chilean tax ID (RUT) that fails validation. Chile only. | | `invalid_shareholder_structure` | A shareholder tree that breaks a structure rule. The `reason` field names the rule. | | `missing_parameter` | A required field that the request omits. | Other validation failures, such as an empty `legal_representatives` array, return `400 Bad Request` with `param` set to the failing field and no `code`. ## Chile A Chilean `account_holder` onboarding sends seven blocks in `data`: `company_basics`, `company_information`, `senior_management`, `legal_representatives`, `shareholders`, `transactional_profile`, and `plaft`. Fintoc's compliance team reviews the documents and answers described in [Know Your Customer (KYC) requirements in Chile](/guides/business-accounts/kyc-requirements/chile). ### company\_basics How the company was incorporated and the name it trades under: | Field | Type | Required | Description | | :- | :- | :- | :- | | `fantasy_name` | string | Optional | Trading name of the company. Accepts `null`. In `test` mode, this field also selects the simulated review outcome. See [Force a review outcome](/guides/business-accounts/entities/onboard-an-entity-by-api#force-a-review-outcome). | | `incorporation_type` | string | Required | Incorporation method. One of `one_day_company` (registered through Empresa en un Día) or `traditional` (incorporated before a notary). Selects the company document slots. | When `incorporation_type` is `one_day_company`, Fintoc verifies at submission that the company's RUT is registered as an Empresa en un Día company. If the company is not, submitting returns `422 Unprocessable Entity` with the code `not_one_day_company`. ### company\_information The company's activity, legal structure, and addresses. Every field is required: | Field | Type | Required | Description | | :- | :- | :- | :- | | `activities_start_date` | string | Required | Date the company started activities before the Chilean Internal Revenue Service (SII), as an ISO 8601 date such as `2019-03-01`. | | `business_activity_code` | string | Required | Six-digit economic activity code from the SII catalog, such as `620200`. A code outside the catalog returns `invalid_enum`. | | `business_address` | string | Required | Physical address where the company operates. | | `company_type` | string | Required | Legal structure of the company. One of `colectiva` (Sociedad Colectiva), `eirl` (Empresa Individual de Responsabilidad Limitada), `en_comandita` (Sociedad en Comandita), `ltda` (Sociedad de Responsabilidad Limitada), `sa` (Sociedad Anónima), or `spa` (Sociedad por Acciones). | | `fiscal_address` | string | Required | Address registered with the SII. | ### senior\_management The company's senior management. `senior_management` is an object with a single key, also named `senior_management`, that holds an array of members. Declare at least one member. Every field is required for every member: | Field | Type | Required | Description | | :- | :- | :- | :- | | `identification_number` | string | Required | Identification number of the member. Must be a valid RUT when `nationality` is `cl`; otherwise returns `invalid_rut`. | | `name` | string | Required | Full name of the member. | | `nationality` | string | Required | Two-letter ISO 3166-1 alpha-2 country code of the member's nationality, in either case. The response returns the value in lowercase. | | `position` | string | Required | Position the member holds in the company, such as `Gerente General`. | An empty array returns `400 Bad Request` with `param` set to `senior_management.senior_management`. ### legal\_representatives The people authorized to act for the company. Declare at least one. Fintoc enforces no maximum: | Field | Type | Required | Description | | :- | :- | :- | :- | | `email` | string | Required | Email address of the legal representative, in RFC 5322 format. | | `first_name` | string | Required | Given name of the legal representative. | | `identification_number` | string | Required | Individual RUT for a Chilean national, or passport number for a foreign national. A company RUT returns `invalid_rut` when `nationality` is `cl`. Must be unique within the onboarding. | | `last_name` | string | Required | Family name of the legal representative. | | `nationality` | string | Required | Two-letter ISO 3166-1 alpha-2 country code of the legal representative's nationality, in either case. The response returns the value in lowercase. | | `phone` | string | Optional | Contact phone number in E.164 format, such as `+56911111111`. Accepts `null`. | | `position` | string | Optional | Role the legal representative holds in the company. The response returns `null` when you omit it. | An empty array returns `400 Bad Request` with `param` set to `legal_representatives`. Two legal representatives with the same `identification_number` return `400 Bad Request` with `param` set to the second entry, such as `legal_representatives[1].identification_number`. ### shareholders The company's ownership tree. Declare at least one shareholder; an empty array returns `invalid_shareholder_structure` with `reason` set to `shareholders_required`. Every node in the tree, at the root and at any depth, takes these fields: | Field | Type | Required | Description | | :- | :- | :- | :- | | `address` | string | Required | Address of the shareholder. | | `children` | array of shareholder | Optional, `legal_entity` only | Shareholders that own this shareholder. Send this only when `type` is `legal_entity`. | | `effective_controller` | boolean | Required | If `true`, the shareholder is an effective controller of the company. Send a JSON boolean. | | `fiscal_address` | string | Required | Address of the shareholder registered with the SII. | | `holder_id` | string | Required | Identification number of the shareholder. Must be a valid RUT when `nationality` is `cl`; otherwise returns `invalid_rut`. | | `last_name` | string | Optional, `natural_person` only | Family name of the shareholder. Send this only when `type` is `natural_person`. Sending it for a `legal_entity` returns `invalid_shareholder_structure` with `reason` set to `invalid_name`. | | `name` | string | Required | Given name when `type` is `natural_person`, or business name when `type` is `legal_entity`. | | `nationality` | string | Required | Two-letter ISO 3166-1 alpha-2 country code of the shareholder's nationality. | | `percentage` | number | Required | Participation the shareholder holds, from `0` to `100`. Send a JSON number; the API rejects a numeric string. | | `type` | string | Required | Kind of shareholder. One of `natural_person` or `legal_entity`. | Four rules constrain the tree. Each structure error returns the code `invalid_shareholder_structure`, with `reason` set to the value in parentheses: * **Each level sums to `100` or less.** Chile sets no minimum sum. A level above `100` fails (`shareholder_participation_exceeded`). * **Only a `legal_entity` nests.** A `natural_person` carrying `children` fails (`only_legal_entity_can_nest`). Fintoc sets no limit on nesting depth. * **Each `holder_id` is unique within its level.** Two shareholders at the root, or under the same parent, with the same `holder_id` fail (`duplicate_shareholder`). The same `holder_id` can appear at different levels. * **At least one effective controller.** Fintoc checks this rule when you submit, not when you create the onboarding. With no shareholder set to `effective_controller: true`, submitting returns `422 Unprocessable Entity` with the code `effective_controller_required`. ### transactional\_profile The sources of the company's equity and funds, and how the company uses Fintoc. Every field is required, and each one is an array that takes at least one value: | Field | Type | Required | Description | | :- | :- | :- | :- | | `business_relationship_purposes` | array of string | Required | Ways the company uses Fintoc. Values in the table below. | | `equity_origins` | array of string | Required | Sources of the company's equity. Values in the table below. | | `resource_origins` | array of string | Required | Sources of the funds the company moves through Fintoc. Values in the table below. | `business_relationship_purposes` accepts these values: | `business_relationship_purposes` value | Purpose | | :- | :- | | `customer_collections` | Collect payments from customers. | | `customer_payouts` | Pay out funds to customers. | | `payroll_payments` | Pay salaries. | | `supplier_payments` | Pay suppliers. | | `tax_payments` | Pay taxes. | | `treasury_management` | Manage the company's treasury. | `equity_origins` accepts these values: | `equity_origins` value | Source of equity | | :- | :- | | `asset_sales` | Proceeds from selling assets. | | `capital_contributions` | Capital contributed by the partners. | | `external_financing` | Financing from banks or third parties. | | `inheritance_or_donations` | Inheritances or donations. | | `investment_returns` | Returns on investments. | | `retained_earnings` | Retained earnings. | `resource_origins` accepts these values: | `resource_origins` value | Source of funds | | :- | :- | | `asset_sales` | Proceeds from selling assets. | | `capital_contributions` | Capital contributions. | | `donations_or_subsidies` | Donations or subsidies. | | `external_financing` | Financing from banks or third parties. | | `investment_returns` | Returns on investments. | | `operating_income` | Operating income of the company. | A value outside these lists, including a Mexican value such as `trusts`, returns `invalid_enum`. ### plaft The company's declaration on anti-money laundering and terrorist financing prevention (PLAFT): | Field | Type | Required | Description | | :- | :- | :- | :- | | `uaf_obligated` | boolean | Required | If `true`, the company must report to Chile's Financial Analysis Unit (UAF), and the onboarding requires the `uaf_registration_certificate` and `plaft_manual_and_policies` slots. | ### Chilean document slots Creating the onboarding opens every company slot that `company_basics.incorporation_type` selects, each one reporting `missing` until you upload a file. The maximum file size is 20 MB for every slot. Fintoc reads the content type of a company slot from the file bytes, and every company slot accepts `application/pdf` only. The top-level `documents` array lists these company slots: | `slot_key` | Opens when | Required to submit | Files | Document | | :- | :- | :- | :- | :- | | `activities_start_certificate` | `incorporation_type` is `traditional` | Yes | One | SII certificate of commencement of activities. | | `current_shareholders_certificate` | `incorporation_type` is `one_day_company` | Yes | One | Current shareholders certificate from the Registro de Empresas y Sociedades. | | `e_rut` | Always | Yes | One | Company electronic RUT card (e-RUT) issued by the SII. | | `good_standing_certificate` | `incorporation_type` is `traditional` | Yes | One | Certificate of good standing with marginal annotations, issued within the last 90 days. | | `incorporation_amendments` | Always | No | Multiple | Amendment deeds and their Diario Oficial publications. | | `incorporation_deed` | Always | Yes | One | Public deed of incorporation. | | `plaft_manual_and_policies` | Always | If `uaf_obligated` is `true` | Multiple | Anti-money laundering prevention manual and policies. | | `power_of_attorney` | Always | No | One | Certificate of authority (personería) stating the legal representatives' powers. | | `uaf_registration_certificate` | Always | If `uaf_obligated` is `true` | One | UAF registration certificate. | Each legal representative gets its own `documents` array with two slots. Fintoc checks the part's declared `Content-Type` for these slots, so send it as one of the accepted types: | `slot_key` | Accepted content types | | :- | :- | | `identification_back` | `application/pdf`, `image/jpeg`, `image/png` | | `identification_front` | `application/pdf`, `image/jpeg`, `image/png` | Chilean shareholders have no document slot. Each shareholder returns `document` set to `null`. A `traditional` company with `uaf_obligated` set to `false` and one legal representative needs six files to submit: `e_rut`, `activities_start_certificate`, `good_standing_certificate`, `incorporation_deed`, and the two identification sides. ### Chilean example This payload declares one legal representative, one senior manager, and two root shareholders. One root shareholder nests a third shareholder. Every value is test data that belongs to no real company or person. ```json theme={null} { "type": "account_holder", "data": { "company_basics": { "incorporation_type": "traditional", "fantasy_name": "Test Company" }, "company_information": { "activities_start_date": "2019-03-01", "business_activity_code": "620200", "company_type": "spa", "business_address": "Av. Apoquindo 100, Santiago", "fiscal_address": "Av. Apoquindo 100, Santiago" }, "senior_management": { "senior_management": [ { "name": "Test Customer 1", "nationality": "cl", "identification_number": "11.111.111-1", "position": "Gerente General" } ] }, "legal_representatives": [ { "first_name": "Test Customer 1", "last_name": "Customer", "email": "jon@snow.com", "nationality": "cl", "identification_number": "11.111.111-1", "position": "Representante legal", "phone": "+56911111111" } ], "shareholders": [ { "type": "natural_person", "name": "Test Customer 1", "last_name": "Customer", "holder_id": "11.111.111-1", "nationality": "cl", "percentage": 60, "address": "Av. Apoquindo 100, Santiago", "fiscal_address": "Av. Apoquindo 100, Santiago", "effective_controller": true }, { "type": "legal_entity", "name": "Test Entity 2", "holder_id": "88.888.888-8", "nationality": "cl", "percentage": 40, "address": "Av. Apoquindo 100, Santiago", "fiscal_address": "Av. Apoquindo 100, Santiago", "effective_controller": false, "children": [ { "type": "natural_person", "name": "Test Customer 2", "last_name": "Customer", "holder_id": "22.222.222-2", "nationality": "cl", "percentage": 100, "address": "Av. Apoquindo 100, Santiago", "fiscal_address": "Av. Apoquindo 100, Santiago", "effective_controller": false } ] } ], "transactional_profile": { "equity_origins": ["capital_contributions"], "business_relationship_purposes": ["customer_collections", "supplier_payments"], "resource_origins": ["operating_income"] }, "plaft": { "uaf_obligated": false } } } ``` ## Mexico A Mexican `account_holder` onboarding sends four blocks in `data`: `company_information`, `legal_representatives`, `transactional_profile`, and `shareholders`. Fintoc's compliance team reviews the documents and answers described in [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico). ### company\_information The company's identity and settlement details. Every field is required: | Field | Type | Required | Description | | :- | :- | :- | :- | | `business_activity` | string | Required | Primary business activity of the company. In `test` mode, this field also selects the simulated review outcome. See [Force a review outcome](/guides/business-accounts/entities/onboard-an-entity-by-api#force-a-review-outcome). | | `business_address` | string | Required | Physical address where the company operates. | | `fiscal_address` | string | Required | Address registered with the Mexican tax authority. | | `incorporation_date` | string | Required | Date the company was incorporated, as an ISO 8601 date. The response returns this value as an ISO 8601 datetime in UTC. | | `phone` | string | Required | Contact phone number in E.164 format: a leading `+` followed by 8 to 15 digits, the first of which cannot be `0`. | | `sector` | string | Required | Industry the company operates in. Values in the table below. | | `settlement_account` | string | Required | Account that receives settlements, as an 18-digit standardized Mexican bank account number (CLABE). | `sector` accepts these values: | `sector` value | Industry | | :- | :- | | `betting_gaming` | Betting and gaming. | | `cross_border_payments` | Cross-border payments. | | `direct_sales` | Direct sales. | | `ecommerce` | E-commerce. | | `education` | Education. | | `insurance` | Insurance. | | `lending` | Lending. | | `other` | Any other industry. | | `property_management` | Property management. | | `psps` | Payment service providers. | | `subscription_businesses` | Subscription businesses. | | `telecommunications` | Telecommunications. | | `ticketing` | Ticketing. | | `utilities` | Utilities. | | `wallets_neobanks` | Digital wallets and neobanks. | > [!WARNING] > > **CLABE validation differs by mode** > > `settlement_account` must have 18 digits. Fintoc accepts the value when the first three digits match a supported Mexican institution and the CLABE control digit checks out. Fintoc also accepts its own CLABEs and skips the control digit for them. In `test` mode, this applies to sandbox bank codes. In `live` mode, this applies to Fintoc's own bank code. A CLABE at a supported Mexican institution behaves the same in both modes. A sandbox CLABE that works in `test` returns an error in `live`. An invalid value returns `400 Bad Request` with `param` set to `company_information.settlement_account`. ### legal\_representatives The people authorized to act for the company. Declare at least one. Fintoc enforces no maximum, and every field is required for every entry: | Field | Type | Required | Description | | :- | :- | :- | :- | | `email` | string | Required | Email address of the legal representative, in RFC 5322 format. | | `first_name` | string | Required | Given name of the legal representative. | | `identification_number` | string | Required | Mexican Unique Population Registry Code (CURP) of the legal representative. | | `last_name` | string | Required | Family name of the legal representative. | | `nationality` | string | Required | Two-letter ISO 3166-1 alpha-2 country code of the legal representative's nationality, in either case. The response returns the value in lowercase. | | `position` | string | Required | Role the legal representative holds in the company, such as `Director General`. | An empty array returns `400 Bad Request` with `param` set to `legal_representatives`. An invalid entry returns `param` with the index of the failing entry, such as `legal_representatives[0].email`. ### transactional\_profile The volume, the source, and the purpose of the money the `Entity` expects to move: | Field | Type | Required | Description | | :- | :- | :- | :- | | `account_purpose` | string | Required | Main use of the account. Values in the table below. | | `account_purpose_details` | string | Required if `account_purpose` is `other` | Description of how the company uses the account. Omitting it when `account_purpose` is `other` returns `400 Bad Request` with `param` set to `transactional_profile.account_purpose_details`. | | `monthly_amount_range` | string | Required | Expected monthly transacted amount in Mexican pesos (MXN). One of `1_2000000` for up to 2,000,000, `2000001_10000000` for 2,000,001 to 10,000,000, or `gt_10000000` for more than 10,000,000. | | `monthly_operations_range` | string | Required | Expected monthly number of operations. One of `1_15000` for 1 to 15,000, `15001_50000` for 15,001 to 50,000, or `gte_50001` for 50,001 or more. | | `resource_origins` | array of string | Required | Where the money the `Entity` moves comes from. Send at least one value from the list below. | > [!NOTE] > > **Former `monthly_amount_range` values** > > Fintoc still accepts the former values `1_500000`, `500001_1000000`, and `gt_1000000`, which counted amounts in US dollars. Fintoc maps `1_500000` to `2000001_10000000`; it maps both `500001_1000000` and `gt_1000000` to `gt_10000000`. The response returns the converted value. Send the MXN values in new integrations. `account_purpose` accepts these values: | `account_purpose` value | Main use of the account | | :- | :- | | `betting_gaming` | Run a betting, raffle, lottery, or similar gaming business. | | `collection_and_dispersion` | Collect payments for your own products or services, and pay suppliers, contractors, or payroll. | | `marketplace` | Collect from buyers and settle to sellers or service providers, as a marketplace or platform. | | `other` | Any other use. Describe it in `account_purpose_details`. | | `own_sales_collection` | Collect payments for your own products or services. | | `psp_aggregator` | Process payments on behalf of other merchants, as an aggregator, payment service provider, or payment gateway. | | `third_party_dispersion` | Disburse third-party funds to people or companies, such as loans, prizes, commissions, or refunds. | `resource_origins` accepts these values: | `resource_origins` value | Source of funds | | :- | :- | | `asset_sales` | Proceeds from selling assets. | | `budget_allocations` | Budget assigned by another organization. | | `donations` | Donations received. | | `investments` | Returns on investments. | | `profits` | Operating profits of the company. | | `royalties` | Royalty payments. | | `sales_income` | Sales or income from the business activity. | | `trusts` | Distributions from a trust. | The response echoes `transactional_profile` with `declaration_accepted` set to `true`, which Fintoc adds when it creates the onboarding. Do not send `declaration_accepted`; the API ignores it. ### shareholders The company's ownership tree. Declare at least one shareholder; an empty array returns `invalid_shareholder_structure` with `reason` set to `shareholders_required`. Every node in the tree, at the root and at any depth, takes these fields: | Field | Type | Required | Description | | :- | :- | :- | :- | | `children` | array of shareholder | Optional, `legal_entity` only | Shareholders that own this shareholder. Send this only when `type` is `legal_entity`. | | `holder_id` | string | Required | Mexican tax ID (RFC) of the shareholder. | | `last_name` | string | Optional, `natural_person` only | Family name of the shareholder. Send this only when `type` is `natural_person`. Sending it for a `legal_entity` returns `invalid_shareholder_structure` with `reason` set to `invalid_name`. | | `name` | string | Required | Given name when `type` is `natural_person`, or business name when `type` is `legal_entity`. | | `nationality` | string | Required | Two-letter ISO 3166-1 alpha-2 country code of the shareholder's nationality, in either case. | | `percentage` | number | Required | Participation the shareholder holds, from `0` to `100`. Send a JSON number; the API rejects a numeric string. | | `type` | string | Required | Kind of shareholder. One of `natural_person` or `legal_entity`. | Two rules constrain the tree. Each structure error returns the code `invalid_shareholder_structure`, with `reason` set to the value in parentheses: * **The root sums to between `76` and `100`.** The root percentages must sum to at least `76` (`participation_below_threshold`) and at most `100` (`shareholder_participation_exceeded`). Each `children` array must sum to `100` or less, with no minimum. * **Only a `legal_entity` nests.** A `natural_person` carrying `children` fails (`only_legal_entity_can_nest`). A `legal_entity` with no `children` is valid. Fintoc sets no limit on nesting depth. ### Mexican document slots Creating the onboarding opens every slot the type requires, each one reporting `missing` until you upload a file. Every slot is required before you can submit. The maximum file size is 20 MB for every slot. For company slots and shareholder documents, Fintoc reads the content type from the file bytes. The content type your upload declares does not matter. The two legal representative slots check both values. Send the part's `Content-Type` as one of the accepted types for that slot, because Fintoc rejects the upload before it inspects the bytes. The onboarding opens five company slots, listed in the top-level `documents` array: | `slot_key` | Accepted content types | | :- | :- | | `articles_of_incorporation` | `application/pdf` | | `proof_of_address` | `application/pdf`, `image/jpeg`, `image/png` | | `settlement_bank_statement` | `application/pdf` | | `shareholder_structure` | `application/pdf` | | `tax_registration_certificate` | `application/pdf` | Each legal representative gets its own `documents` array with two slots: | `slot_key` | Accepted content types | | :- | :- | | `identification` | `application/pdf`, `image/jpeg`, `image/png` | | `power_of_attorney` | `application/pdf` | Each shareholder gets a single `document` object rather than an array, because a shareholder holds exactly one document. Fintoc picks the slot from the shareholder's `type`, so the upload path carries no `slot_key`: | Shareholder `type` | `slot_key` | Accepted content types | | :- | :- | :- | | `legal_entity` | `articles_of_incorporation` | `application/pdf`, `image/jpeg`, `image/png` | | `natural_person` | `identification` | `application/pdf`, `image/jpeg`, `image/png` | A company with one legal representative and three shareholders therefore opens ten slots: five company slots, two for the representative, and one per shareholder. Every Mexican `account_holder` slot accepts a single file, so uploading again with `PUT` replaces the existing file. Each uploaded entry in the top-level `documents` array carries an `id` that you can pass to `DELETE .../documents/{slot_key}/{document_id}` to remove the file. See [Manage files in a slot](/guides/business-accounts/entities/onboard-an-entity-by-api#manage-files-in-a-slot). ### Mexican example This payload declares one legal representative and two root shareholders. One root shareholder nests a third shareholder. Every value is test data that belongs to no real company or person. The `settlement_account` is a documented test CLABE. Fintoc accepts it because its bank code and control digit are valid. An all-zeros CLABE returns `400 Bad Request`, because `000` is not a supported bank code. ```json theme={null} { "type": "account_holder", "data": { "company_information": { "business_activity": "Servicios financieros", "sector": "ecommerce", "business_address": "Av. Insurgentes 456, CDMX", "fiscal_address": "Av. Reforma 123, CDMX", "incorporation_date": "2020-01-15", "phone": "+521111111111", "settlement_account": "646969000000000000" }, "legal_representatives": [ { "first_name": "Test Customer 1", "last_name": "Customer", "email": "rep@example.com", "nationality": "mx", "identification_number": "AAAA010101HDFAAA01", "position": "Director General" } ], "transactional_profile": { "resource_origins": ["trusts", "investments"], "monthly_amount_range": "1_2000000", "monthly_operations_range": "1_15000", "account_purpose": "own_sales_collection" }, "shareholders": [ { "type": "natural_person", "name": "Test Customer 2", "last_name": "Customer", "holder_id": "AAAA010101AAA", "nationality": "mx", "percentage": 60 }, { "type": "legal_entity", "name": "Test Entity 2", "holder_id": "AAA010101AAA", "nationality": "mx", "percentage": 40, "children": [ { "type": "natural_person", "name": "Test Customer 3", "last_name": "Customer", "holder_id": "AAAA010101AAA", "nationality": "mx", "percentage": 80 } ] } ] } } ``` ## What's next * [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api) for the full flow, including the uploads, the submission, and the review. * [KYC requirements in Chile](/guides/business-accounts/kyc-requirements/chile) and [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico) for the documents Fintoc's compliance team reviews. * [The Onboarding object](/api/business-accounts-api/onboardings/onboarding-object) for the response attributes. # Onboard an entity by API Source: https://docs.fintoc.com/guides/business-accounts/entities/onboard-an-entity-by-api Use the API to create a client `Entity` in Chile or Mexico, upload its documents, submit the onboarding for review, and get the `Entity`'s main account. Use the API to create and onboard an `Entity` that can own `Account` objects after approval, without using the dashboard. This flow is for platforms that create an `Entity` for each client, such as marketplaces or wallets that hold balances under each client's legal name. To create `Account` objects under your own root `Entity`, see [Create more accounts](/guides/business-accounts/manage-accounts/creating-more-accounts) instead. > [!NOTE] > > **Availability** > > Onboarding by API supports client `Entity` objects in Chile and Mexico. This guide covers the `account_holder` type, which opens a company as an account holder. An `Entity` that only receives its share of split payments uses the `settlement_recipient` type instead. See [Accept split payments](/guides/payments/accept-a-payment/accept-split-payments#step-2-onboard-the-entity). > [!WARNING] > > **Complete the flow through the API** > > An onboarding you create through the API carries `source` set to `api` and stays in that channel. You cannot continue that onboarding from the dashboard: uploading the documents, submitting for review, and tracking the result all happen through the API. ```mermaid theme={null} flowchart LR A[Create entity] --> B[Create onboarding] B --> C[Upload company documents] C --> D[Upload representative documents] D --> E[Upload shareholder documents] E --> F[Submit for review] F -->|entity.onboarding.approved| G[Fintoc creates the main account] F -->|entity.onboarding.rejected| H[Contact Fintoc support] ``` The flow is the same in both countries. The tabs in each step show what changes between Chile and Mexico: the tax ID, the `data` fields, the document slots, and the account number format. Chilean onboardings have no shareholder documents, so they skip Step 5. ## Before you start You need a secret key from the [dashboard](https://dashboard.fintoc.com/), under **Developers → API Keys**. The key you send selects the mode: `sk_test_...` runs in `test`, and `sk_live_...` runs in `live`. Use `test` mode to build and verify your integration. Use `live` mode to onboard each real client. These are separate activities, not two phases of one flow. A `test` onboarding is a different object from a `live` onboarding and never becomes a `live` onboarding. Onboarding a client in `test` does not advance that client's `live` onboarding. The examples below use a test key. Your organization also needs its own root `Entity` (`is_root` set to `true`) in the same mode as the API key you send. Fintoc checks this requirement when you create a client `Entity`. To onboard clients in `live`, your organization needs a `live` root `Entity`. To build in `test`, your organization needs a `test` root `Entity`. ## Step 1: Create the entity An `Entity` is the legal account holder. Create one for your client with their legal name and tax ID. The `account_holder` type onboards companies only, so `holder_id` must identify a company. > [tab] Chile > > Set `country_code` to `cl`, and set `holder_id` to the company's Chilean tax ID (RUT). `holder_id` is required and must be a valid RUT, with or without dots and hyphen. An invalid RUT returns `400 Bad Request` with the code `invalid_holder_id`. > > ```bash cURL theme={null} > curl --request POST \ > --url https://api.fintoc.com/v2/entities \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --header 'content-type: application/json' \ > --data ' > { > "country_code": "cl", > "holder_name": "Test Entity 1", > "holder_id": "77.777.777-7" > } > ' > ``` > > ```json Response theme={null} > { > "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "object": "entity", > "country_code": "cl", > "holder_id": "777777777", > "holder_name": "Test Entity 1", > "is_root": false, > "mode": "test", > "status": "waiting_initialization" > } > ``` > > Fintoc stores the RUT without dots or hyphen. A RUT that belongs to an individual creates the `Entity`, but creating its `account_holder` onboarding returns `422 Unprocessable Entity` with the code `holder_type_not_supported`. > [tab] Mexico > > Set `country_code` to `mx`, and set `holder_id` to the company's Mexican tax ID (RFC). > > ```bash cURL theme={null} > curl --request POST \ > --url https://api.fintoc.com/v2/entities \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --header 'content-type: application/json' \ > --data ' > { > "country_code": "mx", > "holder_name": "Test Entity 1", > "holder_id": "AAA010101AAA" > } > ' > ``` > > ```json Response theme={null} > { > "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "object": "entity", > "country_code": "mx", > "holder_id": "AAA010101AAA", > "holder_name": "Test Entity 1", > "is_root": false, > "mode": "test", > "status": "waiting_initialization" > } > ``` > > A 13-character RFC belongs to an individual. That `Entity` is created, but creating its `account_holder` onboarding returns `422 Unprocessable Entity` with the code `holder_type_not_supported`. Save the `Entity` ID (`ent_...`); every onboarding call uses this value. See [The Entity object](/api/business-accounts-api/entities/entity-object) for the full attribute list. If your organization has no root `Entity` in the mode of your API key, Fintoc rejects the request with `422 Unprocessable Entity`, `type` set to `invalid_request_error`, and `code` set to `organization_without_operational_root_entity`: ```json Error response theme={null} { "error": { "type": "invalid_request_error", "code": "organization_without_operational_root_entity", "message": "The organization does not have an operational root entity", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` Check that you are using the key for the right mode. If your organization has no root `Entity` in that mode, contact Fintoc support before you create client `Entity` objects. ## Step 2: Create the onboarding The `Onboarding` holds the Know Your Customer review for one `Entity`. The review covers the company, its legal representatives, its transactional profile, and its shareholders. Create one onboarding per `Entity`. The request body has two top-level fields, both required. Set `type` to `account_holder`, the type this guide covers. The other accepted value, `settlement_recipient`, has its own flow in [Accept split payments](/guides/payments/accept-a-payment/accept-split-payments#step-2-onboard-the-entity). Send the review data in `data`. The keys of `data` depend on the `Entity`'s country, and every key is required. See [Account holder onboarding](/guides/business-accounts/entities/account-holder-onboarding) for every field, enum value, and validation rule. Omitting `type` or `data` returns `400 Bad Request` with the code `missing_parameter`. A `type` outside the accepted values returns `400 Bad Request` with the code `invalid_enum`. The error message names the accepted values. An `Entity` holds at most one onboarding per mode, so the same `Entity` can hold one `live` onboarding and one `test` onboarding at the same time. A second onboarding in the same mode returns `409 Conflict`, even when the first one is already `rejected`. > [tab] Chile > > A Chilean onboarding sends seven keys in `data`: `company_basics`, `company_information`, `senior_management`, `legal_representatives`, `shareholders`, `transactional_profile`, and `plaft`. > > ```bash cURL theme={null} > curl --request POST \ > --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --header 'content-type: application/json' \ > --data ' > { > "type": "account_holder", > "data": { > "company_basics": { > "incorporation_type": "traditional", > "fantasy_name": "Test Company" > }, > "company_information": { > "activities_start_date": "2019-03-01", > "business_activity_code": "620200", > "company_type": "spa", > "business_address": "Av. Apoquindo 100, Santiago", > "fiscal_address": "Av. Apoquindo 100, Santiago" > }, > "senior_management": { > "senior_management": [ > { > "name": "Test Customer 1", > "nationality": "cl", > "identification_number": "11.111.111-1", > "position": "Gerente General" > } > ] > }, > "legal_representatives": [ > { > "first_name": "Test Customer 1", > "last_name": "Customer", > "email": "jon@snow.com", > "nationality": "cl", > "identification_number": "11.111.111-1", > "position": "Representante legal", > "phone": "+56911111111" > } > ], > "shareholders": [ > { > "type": "natural_person", > "name": "Test Customer 1", > "last_name": "Customer", > "holder_id": "11.111.111-1", > "nationality": "cl", > "percentage": 60, > "address": "Av. Apoquindo 100, Santiago", > "fiscal_address": "Av. Apoquindo 100, Santiago", > "effective_controller": true > }, > { > "type": "legal_entity", > "name": "Test Entity 2", > "holder_id": "88.888.888-8", > "nationality": "cl", > "percentage": 40, > "address": "Av. Apoquindo 100, Santiago", > "fiscal_address": "Av. Apoquindo 100, Santiago", > "effective_controller": false, > "children": [ > { > "type": "natural_person", > "name": "Test Customer 2", > "last_name": "Customer", > "holder_id": "22.222.222-2", > "nationality": "cl", > "percentage": 100, > "address": "Av. Apoquindo 100, Santiago", > "fiscal_address": "Av. Apoquindo 100, Santiago", > "effective_controller": false > } > ] > } > ], > "transactional_profile": { > "equity_origins": ["capital_contributions"], > "business_relationship_purposes": ["customer_collections", "supplier_payments"], > "resource_origins": ["operating_income"] > }, > "plaft": { > "uaf_obligated": false > } > } > } > ' > ``` > > ```json Response (abridged) theme={null} > { > "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding", > "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "type": "account_holder", > "status": "in_progress", > "source": "api", > "submittable": false, > "submitted_at": null, > "reviewed_at": null, > "legal_representatives": [ > { > "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding_legal_representative", > "documents": [ > { "slot_key": "identification_front", "status": "missing" }, > { "slot_key": "identification_back", "status": "missing" } > ] > } > ], > "shareholders": [ > { > "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding_shareholder", > "type": "natural_person", > "parent_id": null, > "effective_controller": true, > "document": null > }, > { > "id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM", > "object": "onboarding_shareholder", > "type": "legal_entity", > "parent_id": null, > "effective_controller": false, > "document": null > }, > { > "id": "onbsh_9bnCxhAlucAI7zezIb7Un1fN", > "object": "onboarding_shareholder", > "type": "natural_person", > "parent_id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM", > "effective_controller": false, > "document": null > } > ], > "documents": [ > { "slot_key": "e_rut", "status": "missing" }, > { "slot_key": "activities_start_certificate", "status": "missing" }, > { "slot_key": "good_standing_certificate", "status": "missing" }, > { "slot_key": "power_of_attorney", "status": "missing" }, > { "slot_key": "incorporation_deed", "status": "missing" }, > { "slot_key": "incorporation_amendments", "status": "missing" }, > { "slot_key": "uaf_registration_certificate", "status": "missing" }, > { "slot_key": "plaft_manual_and_policies", "status": "missing" } > ] > } > ``` > > Four details to note in the Chilean response: > > * `documents` depends on `company_basics.incorporation_type`. A `traditional` company opens the slots above. A `one_day_company` (Empresa en un Día) opens `current_shareholders_certificate` instead of `activities_start_certificate` and `good_standing_certificate`. > * `documents` always lists `uaf_registration_certificate` and `plaft_manual_and_policies`. You upload them only when `plaft.uaf_obligated` is `true`. > * Each legal representative has its own `documents` array with two slots: the front and the back of the identity document. > * Each shareholder has `document` set to `null`, because Chile requires no document per shareholder. > > The legal representative's `identification_number` and each shareholder's `holder_id` take a Chilean tax ID (RUT) when `nationality` is `cl`. A foreign legal representative uses a passport number. > [tab] Mexico > > A Mexican onboarding sends four keys in `data`: `company_information`, `legal_representatives`, `transactional_profile`, and `shareholders`. > > ```bash cURL theme={null} > curl --request POST \ > --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --header 'content-type: application/json' \ > --data ' > { > "type": "account_holder", > "data": { > "company_information": { > "business_activity": "Servicios financieros", > "sector": "ecommerce", > "business_address": "Av. Insurgentes 456, CDMX", > "fiscal_address": "Av. Reforma 123, CDMX", > "incorporation_date": "2020-01-15", > "phone": "+521111111111", > "settlement_account": "646969000000000000" > }, > "legal_representatives": [ > { > "first_name": "Test Customer 1", > "last_name": "Customer", > "email": "rep@example.com", > "nationality": "mx", > "identification_number": "AAAA010101HDFAAA01", > "position": "Director General" > } > ], > "transactional_profile": { > "resource_origins": ["trusts", "investments"], > "monthly_amount_range": "1_2000000", > "monthly_operations_range": "1_15000", > "account_purpose": "own_sales_collection" > }, > "shareholders": [ > { > "type": "natural_person", > "name": "Test Customer 2", > "last_name": "Customer", > "holder_id": "AAAA010101AAA", > "nationality": "mx", > "percentage": 60 > }, > { > "type": "legal_entity", > "name": "Test Entity 2", > "holder_id": "AAA010101AAA", > "nationality": "mx", > "percentage": 40, > "children": [ > { > "type": "natural_person", > "name": "Test Customer 3", > "last_name": "Customer", > "holder_id": "AAAA010101AAA", > "nationality": "mx", > "percentage": 80 > } > ] > } > ] > } > } > ' > ``` > > ```json Response (abridged) theme={null} > { > "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding", > "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "type": "account_holder", > "status": "in_progress", > "source": "api", > "submittable": false, > "submitted_at": null, > "reviewed_at": null, > "legal_representatives": [ > { > "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding_legal_representative", > "documents": [ > { "slot_key": "identification", "status": "missing" }, > { "slot_key": "power_of_attorney", "status": "missing" } > ] > } > ], > "shareholders": [ > { > "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding_shareholder", > "type": "natural_person", > "parent_id": null, > "document": { "slot_key": "identification", "status": "missing" } > }, > { > "id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM", > "object": "onboarding_shareholder", > "type": "legal_entity", > "parent_id": null, > "document": { "slot_key": "articles_of_incorporation", "status": "missing" } > }, > { > "id": "onbsh_9bnCxhAlucAI7zezIb7Un1fN", > "object": "onboarding_shareholder", > "type": "natural_person", > "parent_id": "onbsh_8anBwgZktbZH6ydyHa6Tm0eM", > "document": { "slot_key": "identification", "status": "missing" } > } > ], > "documents": [ > { "slot_key": "tax_registration_certificate", "status": "missing" }, > { "slot_key": "settlement_bank_statement", "status": "missing" }, > { "slot_key": "proof_of_address", "status": "missing" }, > { "slot_key": "shareholder_structure", "status": "missing" }, > { "slot_key": "articles_of_incorporation", "status": "missing" } > ] > } > ``` > > Every Mexican onboarding opens five company slots, two slots per legal representative, and one slot per shareholder. The onboarding above declares one legal representative and three shareholders, so it opens ten slots in total. > > Some fields use Mexico-specific identifiers. The legal representative's `identification_number` is a Mexican Unique Population Registry Code (CURP). The `settlement_account` is an 18-digit standardized Mexican bank account number (CLABE). The `settlement_account` above is a documented test value that belongs to no real account. Fintoc accepts it because its bank code and control digit are valid. An all-zeros CLABE returns `400 Bad Request`, because `000` is not a supported bank code. > > `transactional_profile.account_purpose` is required. When you set it to `other`, also send `account_purpose_details` with a description of how the company uses the account. A block labeled `Response (abridged)` shows only the fields that the step changes, not the whole object. The full response also returns `data`, which echoes the step data you sent, except `legal_representatives` and `shareholders`. Each legal representative and shareholder also carries the identity fields from the request. See [The Onboarding object](/api/business-accounts-api/onboardings/onboarding-object) for the full shape. Three details apply in both countries: * `submittable` is `false` until every required field and document is in place. * `documents` lists each company document slot and its `status`, either `missing` or `uploaded`. Read this array to identify outstanding documents. * A `legal_entity` shareholder can include nested `children`. Steps 3, 4, and 5 fill the slots. ## Step 3: Upload the company documents Upload one file to each company document slot in the `documents` array with `PUT .../documents/{slot_key}`. Send the file as `multipart/form-data` in the `file` field. The maximum file size is 20 MB. A slot accepts either one file or multiple files. On a single-file slot, `PUT` replaces the existing file. On a multi-file slot, `PUT` adds a file and keeps the files already uploaded. See [Manage files in a slot](#manage-files-in-a-slot). > [tab] Chile > > Every Chilean company slot accepts `application/pdf` only. The slots you must fill depend on the data you sent in Step 2: > > | `slot_key` | Opens when | Required to submit | Files | > | :- | :- | :- | :- | > | `e_rut` | Always | Yes | One | > | `activities_start_certificate` | `incorporation_type` is `traditional` | Yes | One | > | `good_standing_certificate` | `incorporation_type` is `traditional` | Yes | One | > | `current_shareholders_certificate` | `incorporation_type` is `one_day_company` | Yes | One | > | `power_of_attorney` | Always | No | One | > | `incorporation_deed` | Always | Yes | One | > | `incorporation_amendments` | Always | No | Multiple | > | `uaf_registration_certificate` | Always | If `uaf_obligated` is `true` | One | > | `plaft_manual_and_policies` | Always | If `uaf_obligated` is `true` | Multiple | > > A `PUT` to a slot the onboarding does not open, such as `current_shareholders_certificate` on a `traditional` company, returns `422 Unprocessable Entity` with the code `unknown_document_slot`. > > ```bash cURL theme={null} > curl --request PUT \ > --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/e_rut \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --form 'file=@e_rut.pdf' > ``` > > ```json Response (abridged) theme={null} > { > "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding", > "documents": [ > { > "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", > "slot_key": "e_rut", > "status": "uploaded", > "filename": "e_rut.pdf", > "uploaded_at": "2026-01-15T14:30:00Z" > } > ] > } > ``` > > Repeat for each remaining required slot. Add the files for `incorporation_amendments` and `plaft_manual_and_policies` one at a time, as [Manage files in a slot](#manage-files-in-a-slot) shows. > [tab] Mexico > > Every Mexican company slot accepts one file and is required to submit. Each slot accepts its own content types: > > | `slot_key` | Accepted content types | > | :- | :- | > | `tax_registration_certificate` | `application/pdf` | > | `settlement_bank_statement` | `application/pdf` | > | `proof_of_address` | `application/pdf`, `image/jpeg`, `image/png` | > | `shareholder_structure` | `application/pdf` | > | `articles_of_incorporation` | `application/pdf` | > > ```bash cURL theme={null} > curl --request PUT \ > --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/tax_registration_certificate \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' \ > --form 'file=@tax_registration_certificate.pdf' > ``` > > ```json Response (abridged) theme={null} > { > "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", > "object": "onboarding", > "documents": [ > { > "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", > "slot_key": "tax_registration_certificate", > "status": "uploaded", > "filename": "tax_registration_certificate.pdf", > "uploaded_at": "2026-01-15T14:30:00Z" > } > ] > } > ``` > > Repeat for each remaining slot: `settlement_bank_statement`, `proof_of_address`, `shareholder_structure`, and `articles_of_incorporation`. A file whose content type the slot does not accept returns `422 Unprocessable Entity` with the code `unsupported_content_type`. The error message lists the content types the slot accepts. ### Manage files in a slot The `documents` array returns one entry per uploaded file. Each uploaded entry carries its own `id`. A multi-file slot with three files appears three times in `documents`, once per file, with the same `slot_key`. A slot with no files appears once, with `status` set to `missing` and no `id`. To add a file to a multi-file slot, call `POST .../documents/{slot_key}` with the same `multipart/form-data` body as `PUT`. The example below uses `incorporation_amendments`, a multi-file slot of a Chilean onboarding that accepts `application/pdf` only. A Mexican `account_holder` onboarding has no multi-file slot: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/incorporation_amendments \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --form 'file=@incorporation_amendment_2025.pdf' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "documents": [ { "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", "slot_key": "incorporation_amendments", "status": "uploaded", "filename": "incorporation_amendment_2024.pdf", "uploaded_at": "2026-01-15T14:30:00Z" }, { "id": "onbdoc_4dqEzjCnweCK9b1bKd9Wp3hP", "slot_key": "incorporation_amendments", "status": "uploaded", "filename": "incorporation_amendment_2025.pdf", "uploaded_at": "2026-01-15T14:32:00Z" } ] } ``` `POST` on a single-file slot returns `422 Unprocessable Entity` with the code `single_file_document_slot`. Use `PUT` to replace the file in a single-file slot. To remove one file, call `DELETE .../documents/{slot_key}/{document_id}` with the file's `id` from the `documents` array: ```bash cURL theme={null} curl --request DELETE \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/tax_registration_certificate/onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "documents": [ { "slot_key": "tax_registration_certificate", "status": "missing" } ] } ``` The `POST` and `DELETE` calls return the updated onboarding. An `id` that does not belong to that slot returns `404 Not Found` with the code `missing_resource`. Once you submit the onboarding, you can no longer add or remove files. To replace one file in a multi-file slot, call `DELETE` for that file and then `POST` the new file. ## Step 4: Upload each legal representative's documents Each legal representative needs two documents. Use the legal representative `id` (`onblr_...`) from the Step 2 response, and pass the slot as the last path segment. The two slots depend on the country: > [tab] Chile > > | `slot_key` | Accepted content types | > | :- | :- | > | `identification_front` | `application/pdf`, `image/jpeg`, `image/png` | > | `identification_back` | `application/pdf`, `image/jpeg`, `image/png` | > > Upload the front and the back of the identity document as two files. The certificate of authority (personería) is not a legal representative slot in Chile. Upload it to the company slot `power_of_attorney` in Step 3. > [tab] Mexico > > | `slot_key` | Accepted content types | > | :- | :- | > | `identification` | `application/pdf`, `image/jpeg`, `image/png` | > | `power_of_attorney` | `application/pdf` | A slot that does not belong to the onboarding's country returns `422 Unprocessable Entity` with the code `unknown_document_slot`. The example uploads the Mexican `identification` slot. A Chilean onboarding uses the same path with `identification_front` or `identification_back`. ```bash cURL theme={null} curl --request PUT \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/legal_representatives/onblr_0ujsswThIGTUYm2K8FjOOfXtY1K/documents/identification \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --form 'file=@identification.pdf' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "legal_representatives": [ { "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_legal_representative", "documents": [ { "slot_key": "identification", "status": "uploaded", "filename": "identification.pdf", "uploaded_at": "2026-01-15T14:30:00Z" }, { "slot_key": "power_of_attorney", "status": "missing" } ] } ] } ``` Repeat for the second slot, and for every other legal representative you declared. ## Step 5: Upload each shareholder's document Only Mexican onboardings require a document per shareholder. A Chilean onboarding skips this step: each Chilean shareholder has `document` set to `null`, and uploading to that shareholder returns `422 Unprocessable Entity` with the code `shareholder_document_not_required`. In Mexico, each declared shareholder needs one document. Use the shareholder `id` (`onbsh_...`) from the Step 2 response. This path carries no slot, because Fintoc derives the slot from the shareholder's `type`: `identification` for a `natural_person`, and `articles_of_incorporation` for a `legal_entity`. The slot accepts `application/pdf`, `image/jpeg`, and `image/png`. ```bash cURL theme={null} curl --request PUT \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/shareholders/onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K/document \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --form 'file=@identification.pdf' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "shareholders": [ { "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_shareholder", "document": { "slot_key": "identification", "status": "uploaded", "filename": "identification.pdf", "uploaded_at": "2026-01-15T14:30:00Z" } } ] } ``` ## Step 6: Submit for review Once `submittable` is `true`, submit the onboarding for Fintoc to review. The onboarding must be `in_progress` and include every required field and document. After submission, the onboarding moves to `submitted` and you can no longer modify it. ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K/submit \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "type": "account_holder", "status": "submitted", "source": "api", "submittable": false, "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": null } ``` `submittable` turns `false` once the onboarding is `submitted`, because a submitted onboarding can no longer accept changes. If a required field or document is missing, or the onboarding is no longer `in_progress`, the call returns a `422 Unprocessable Entity` error. The `param` field names the slot or field that blocks the submission: ```json Error response theme={null} { "error": { "type": "invalid_request_error", "code": "required_document_missing", "message": "A required document is missing.", "param": "tax_registration_certificate", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` A Chilean onboarding runs two more checks when you submit it: * **Empresa en un Día status.** When `incorporation_type` is `one_day_company`, Fintoc verifies that the company's RUT is registered as an Empresa en un Día company. If the company is not, or Fintoc cannot confirm it, the call returns the code `not_one_day_company` with `param` set to `incorporation_type`. If the registry rejects the `Entity`'s RUT as invalid, the call returns the code `invalid_rut` with `param` set to `rut`. * **Effective controller.** At least one shareholder must have `effective_controller` set to `true`. Otherwise, the call returns the code `effective_controller_required` with `param` set to `shareholders`. ## Step 7: Track the review An onboarding moves through `pending`, `in_progress`, `submitted`, and then `approved`, `rejected`, or `cancelled`. Fintoc sends one of these webhook events when it approves or rejects the onboarding: | Event | Onboarding result | | :- | :- | | `entity.onboarding.approved` | The `Entity` passed review and is ready to transact. | | `entity.onboarding.rejected` | The review failed. Contact Fintoc support to review the case. | Subscribe to these events in the dashboard under **Developers → Webhooks**. Each event carries the full reviewed onboarding, including the step data in `data`, the `documents`, and the declared `legal_representatives` and `shareholders`, so you do not need to call the API to read what Fintoc reviewed. See the [Entity onboarding payload](/api/main-resources/events-reference/types-of-events#entity-onboarding-payload). You cannot retry a rejected onboarding through the API. Creating a new onboarding for the same `Entity` returns `409 Conflict`, as Step 2 explains. Fintoc can review a rejected onboarding again and approve it, so your handler may receive `entity.onboarding.approved` after `entity.onboarding.rejected` for the same onboarding. See [Retry after a rejection](/api/main-resources/events-reference/types-of-events#retry-after-a-rejection). If you don't use webhooks, poll the onboarding directly: ```bash cURL theme={null} curl --request GET \ --url https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' ``` ```json Response (abridged) theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "type": "account_holder", "status": "approved", "source": "api", "submittable": false, "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": "2026-01-16T09:00:00Z" } ``` Check `status` to track the onboarding. Once `status` is `approved`, the `Entity` is ready to transact. ## Step 8: Get the main account When the onboarding reaches `approved`, Fintoc creates the `Entity`'s main `Account` with `active` status, together with its root account number. You do not need to create the main `Account`. Before approval, the `Entity` owns no `Account`, so no `Account` is ever `pending`. Both modes behave the same: an approved `test` onboarding creates a `test` main `Account`, and an approved `live` onboarding creates a `live` one. List the entity's accounts to retrieve the main `Account`, then store the `id` (`acc_...`) and the `root_account_number` for that client. The account number format and the currency depend on the country: > [tab] Chile > > A Chilean main `Account` holds `CLP`, and its `root_account_number` is a Chilean bank account number. > > ```bash cURL theme={null} > curl --request GET \ > --url 'https://api.fintoc.com/v2/accounts?entity_id=ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN' \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' > ``` > > ```json Response theme={null} > [ > { > "id": "acc_8anBwgZktbZH6ydyHa6Tm0eM", > "object": "account", > "mode": "test", > "status": "active", > "description": null, > "is_root": true, > "root_account_number": "000000001", > "root_account_number_id": "acno_0ujsswThIGTUYm2K8FjOOfXtY1K", > "available_balance": 0, > "currency": "CLP", > "entity": { > "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "holder_id": "777777777", > "holder_name": "Test Entity 1", > "is_root": false > } > } > ] > ``` > [tab] Mexico > > A Mexican main `Account` holds `MXN`, and its `root_account_number` is an 18-digit standardized Mexican bank account number (CLABE). > > ```bash cURL theme={null} > curl --request GET \ > --url 'https://api.fintoc.com/v2/accounts?entity_id=ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN' \ > --header 'Authorization: YOUR_TEST_SECRET_KEY' \ > --header 'accept: application/json' > ``` > > ```json Response theme={null} > [ > { > "id": "acc_8anBwgZktbZH6ydyHa6Tm0eM", > "object": "account", > "mode": "test", > "status": "active", > "description": null, > "is_root": true, > "root_account_number": "646180111800000004", > "root_account_number_id": "acno_0ujsswThIGTUYm2K8FjOOfXtY1K", > "available_balance": 0, > "currency": "MXN", > "entity": { > "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", > "holder_id": "AAA010101AAA", > "holder_name": "Test Entity 1", > "is_root": false > } > } > ] > ``` ### Create additional accounts The main `Account` is enough to send and receive money. Create more `Account` objects under the same `Entity` when the client needs separate balances, one per cost center. Pass the `Entity` ID as `entity_id`. Each `Account` has its own balance and root account number. Outbound transfer receipts show the client's legal name. See [Create more accounts](/guides/business-accounts/manage-accounts/creating-more-accounts) for account creation details. ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/accounts \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "description": "Client settlement account" } ' ``` ```json Response theme={null} { "id": "acc_9bnCxhAlucAI7zezIb7Un1fN", "object": "account", "mode": "test", "status": "active", "description": "Client settlement account", "is_root": false, "root_account_number": "646180111800000017", "root_account_number_id": "acno_2fJkRm7tBvQxNzYpLc5WsHaDfT3", "available_balance": 0, "currency": "MXN", "entity": { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "holder_name": "Test Entity 1", "holder_id": "AAA010101AAA" } } ``` ## Test the integration In `test` mode, run the full sequence above with your `sk_test_...` key. Create the `Entity` and onboarding, upload a sample file to every required slot, and submit the onboarding. Confirm that `submittable` turns `true` only after every required slot reports `uploaded`. Fintoc selects the mode from the API key you send, not from a request parameter. Onboarding request and response bodies do not carry a `mode` field. Onboardings are isolated per mode. A `test` key cannot read or act on a `live` onboarding, and a `live` key cannot read or act on a `test` onboarding. Both cases return `404 Not Found` with the code `missing_resource`. Fintoc resolves `entity_id` in the API key's mode, so a `test` key must reference an `Entity` that exists in `test` mode. > [!TIP] > > For a Chilean `test` onboarding, set `incorporation_type` to `traditional`. A `one_day_company` triggers the Empresa en un Día check from Step 6 against the `Entity`'s RUT, in `test` mode too, so a test RUT can block the submission. ### Force a review outcome In `live` mode, submitting starts a real Know Your Customer review that Fintoc's compliance team decides. In `test` mode, submitting triggers a simulated review. Use the simulated review to exercise the approved and rejected paths without waiting. Fintoc decides the simulated review from a magic value in the step data you sent. This mechanism works like a test card number: a magic value forces a specific outcome. The field that carries the value depends on the country: > [tab] Chile > > | `company_basics.fantasy_name` | Resulting `status` | Webhook event | > | :- | :- | :- | > | `illegal` | `rejected` | `entity.onboarding.rejected` | > | `suspicious` | `submitted` | No event | > | Any other value, or no `fantasy_name` | `approved` | `entity.onboarding.approved` | > [tab] Mexico > > | `company_information.business_activity` | Resulting `status` | Webhook event | > | :- | :- | :- | > | `illegal` | `rejected` | `entity.onboarding.rejected` | > | `suspicious` | `submitted` | No event | > | Any other value | `approved` | `entity.onboarding.approved` | The `suspicious` case leaves `reviewed_at` set to `null`. Use it to model an onboarding that is still under review, and check how your integration behaves while it waits for a decision. A `test` onboarding follows the same one-per-mode rule, so after a simulated rejection the `Entity` cannot start a new `test` onboarding. To run the flow again, create another `Entity`. > [!WARNING] > > Fintoc compares the whole string exactly, including case and surrounding whitespace. `ILLEGAL`, `Illegal`, and `"illegal "` with a trailing space all fall through to `approved`. ### Read the simulated result `POST .../submit` returns `200 OK` with `status` set to `submitted` and `reviewed_at` set to `null`, in both modes. The simulated review runs after the response, so do not treat the submit response as the review outcome. Poll the onboarding as shown in Step 7, or listen for the webhook event. Fintoc delivers `entity.onboarding.approved` and `entity.onboarding.rejected` to the webhook endpoints registered in `test` mode, and the event carries `"mode": "test"`. ```json Webhook event (abridged) theme={null} { "id": "evt_2xK9mP4nQrStUvWxYz1234567", "object": "event", "type": "entity.onboarding.approved", "mode": "test", "created_at": "2026-01-16T09:00:00.000Z", "data": { "object": "onboarding", "object_name": "onboarding_process", "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "entity": { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "holder_id": "AAA010101AAA", "holder_name": "Test Entity 1", "nationality": "mx" }, "type": "account_holder", "source": "api", "status": "approved", "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": "2026-01-16T09:00:00Z", "data": { "company_information": { "business_activity": "Servicios financieros", "settlement_account": "646969000000000000" } }, "legal_representatives": [ { "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_legal_representative", "first_name": "Test Customer 1", "last_name": "Customer" } ], "shareholders": [ { "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_shareholder", "type": "natural_person" } ], "documents": [ { "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", "slot_key": "tax_registration_certificate", "status": "uploaded" } ] } } ``` The event's `data` carries the reviewed onboarding with the same fields as [The Onboarding object](/api/business-accounts-api/onboardings/onboarding-object), except `submittable`. It also keeps `object_name` and `entity` for backward compatibility. The example shows a Mexican onboarding and trims `data`, `legal_representatives`, `shareholders`, and `documents`. See the [Entity onboarding payload](/api/main-resources/events-reference/types-of-events#entity-onboarding-payload) for the full payload. The rejected event carries the same payload, with the event `type` set to `entity.onboarding.rejected` and `data.status` set to `rejected`. ### What test mode does not simulate In `test` mode, Fintoc reproduces the review outcome and the webhook, and nothing else in the compliance flow: * No rejection reason. A rejected onboarding exposes no field that explains the decision, in the API or in the webhook payload. * No emails. Fintoc sends no submission notification to the legal representatives in `test` mode. ## What's next * [Account holder onboarding](/guides/business-accounts/entities/account-holder-onboarding) for the `data` schema and the document slots of the `account_holder` type, in Chile and Mexico. * [Know Your Customer (KYC) requirements in Chile](/guides/business-accounts/kyc-requirements/chile) and [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico) for the documents Fintoc's compliance team reviews. * [Create more accounts](/guides/business-accounts/manage-accounts/creating-more-accounts) for an approved `Entity`. * Review [The Onboarding object](/api/business-accounts-api/onboardings/onboarding-object) and [the onboarding endpoints](/api/business-accounts-api/onboardings/entities-onboardings-create) in the API reference. # KYC requirements in Chile Source: https://docs.fintoc.com/guides/business-accounts/kyc-requirements/chile The documents and questions Fintoc's Know Your Customer review requires from a company resident in Chile to operate a Cuenta con Provisión de Fondos account. This page lists what Fintoc's Know Your Customer (KYC) review requires from a company resident in Chile, so you can gather everything before you start. For Mexican companies, see [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico). > [!NOTE] > > **Availability** > > The Chilean KYC review covers companies resident in Chile that operate a Cuenta con Provisión de Fondos (CPF) account. The company documents you upload depend on how you incorporated the company: through the Empresa en un Día registry, or through a traditional incorporation before a notary. ## Company documents For a traditional incorporation, upload these documents: | Document | What it must show | | - | - | | [Chilean tax ID certificate (RUT)](https://www.sii.cl/servicios_online/1125-4370.html) | The company's tax ID. | | [Certificado de Inicio de Actividades](https://www.sii.cl/servicios_online/1125-4370.html) | That the company registered the start of its activities. | | Escritura pública de constitución | The partners, the legal name, and the form of administration of the company. | | Escrituras públicas de modificación | Every change to the company since its incorporation, with its publication in the Diario Oficial. Upload one file per document. | | Certificado de vigencia con anotaciones marginales | That the company is in good standing. Fintoc accepts a certificate issued within the last 90 days. | For a company incorporated through Empresa en un Día, upload these documents instead: | Document | What it must show | | - | - | | [Chilean tax ID certificate (RUT)](https://www.sii.cl/servicios_online/1125-4370.html) | The company's tax ID. | | [Certificado de Inicio de Actividades](https://www.sii.cl/servicios_online/1125-4370.html) | That the company registered the start of its activities. | | [Certificado de socios vigentes](https://www.registrodeempresasysociedades.cl/ObtenerCertificadosHome2.aspx) | The company's current partners. | ## People documents Fintoc identifies the people who sign the contract and the people who control the company. Upload these documents: | Document | What it must show | | - | - | | Identity document of each signer | The valid identity document of every legal representative who signs the contract. | | Personería\* | The powers granted to the legal representative, when the deed of incorporation does not grant those powers. | \*Only for traditional incorporation. ## Details you provide Fintoc reads the company details from the documents you upload, and you confirm or correct them in the form. You provide these details: * **Company**: legal name, trade name, nationality, Chilean tax ID (RUT), date of start of activities, economic activity, company type, address, and tax address. The company types are Sociedad Anónima, Sociedad por Acciones (SpA), Sociedad de Responsabilidad Limitada (Ltda), Empresa Individual de Responsabilidad Limitada (EIRL), Sociedad Colectiva, and Sociedad en Comandita. * **Senior management**: name, identification number, and position of at least the general manager. * **Legal representatives**: full name, nationality, identification number, and email address of every required signer. * **Shareholding structure**: type of person, name or legal name, identification number, address, tax address, and participation percentage of every direct or indirect shareholder that holds 10% or more of the company. ## Additional questions You also answer questions that no document covers. Each answer comes from a fixed list of options: * **Source of the company's assets**: trusts, royalties, asset sales, investments, profits, donations, services, or another source you describe. You can select more than one option. * **Purpose and nature of the business relationship**: collecting money or payments for services, disbursing money, holding money in deposit or custody, or another purpose you describe. You can select more than one option. * **Source of the funds you operate**: your own resources from the business, collections from your customers, transfers between the company's own accounts, capital contributions, or another source you describe. You can select more than one option. * **Other effective controllers**: whether any individual controls the company without holding 10% or more of it, directly or indirectly. If you answer yes, you identify each one with the same details as a shareholder. * **Obligation to report to the Unidad de Análisis Financiero (UAF)**: whether the company must report to the UAF. If you answer yes, you also upload the company's UAF registration certificate and its Manual y Políticas de Prevención de Lavado de Activos y Financiamiento del Terrorismo (PLAFT). ## What's next * [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api) to run the KYC review of the Chilean `Entity` objects you open for your clients. * [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico) if you also operate in Mexico. * [Business Accounts overview](/guides/business-accounts/overview) for what you can build once Fintoc approves the review. # KYC requirements Source: https://docs.fintoc.com/guides/business-accounts/kyc-requirements/index The documents you upload and the questions you answer in Fintoc's Know Your Customer review to operate Business Accounts in Chile and Mexico. Before your company can send or receive transfers in production, Fintoc runs a Know Your Customer (KYC) review of your company. This section lists what that review asks for: the documents you upload, and the questions you answer that no document covers. This section covers the review of your own company. To run a KYC review on the `Entity` objects you open for your clients, see [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api). Requirements differ by country: * [KYC requirements in Chile](/guides/business-accounts/kyc-requirements/chile) * [KYC requirements in Mexico](/guides/business-accounts/kyc-requirements/mexico) Gather the documents for your country before you start the form. Fintoc's compliance team reviews your submission and can ask for more information before approving the submission. # KYC requirements in Mexico Source: https://docs.fintoc.com/guides/business-accounts/kyc-requirements/mexico The documents and questions Fintoc's Know Your Customer review requires from a commercial company incorporated in Mexico to operate Business Accounts. This page lists what Fintoc's Know Your Customer (KYC) review requires from a commercial company incorporated in Mexico, so you can gather everything before you start. Fintoc runs this review on commercial companies incorporated in Mexico only. For Chilean companies, see [KYC requirements in Chile](/guides/business-accounts/kyc-requirements/chile). ## Company documents Each file can be up to 20 MB, and company documents must be in PDF. Upload these documents: | Document | What it must show | | - | - | | Constancia de Situación Fiscal | The company's tax status with the Servicio de Administración Tributaria (SAT). Fintoc accepts a certificate issued within the last three months. | | Acta constitutiva | The incorporation of the company. | | Estructura accionaria vigente | The company's current shareholding structure, as recorded in a public instrument. | | Comprobante de domicilio | The company's address. Fintoc accepts a document issued within the last three months. | | Estado de cuenta | The bank account where Fintoc settles your funds. Fintoc accepts a statement issued within the last three months. | ## People documents Fintoc identifies the person who signs the contract and the individuals who ultimately own the company. Upload these documents: | Document | What it must show | | - | - | | Identity document of the legal representative | The valid identity document of the legal representative who signs the contract. | | Poder del representante legal | The public instrument that grants powers to the legal representative. | | Identity document of each beneficial owner | The valid identity document of every individual shareholder that holds more than 25% of the company, directly or indirectly. Upload one file per shareholder. | Upload either both sides of the voter ID card or the passport for each identity document. ## Details you provide Fintoc reads the company details from the documents you upload, and you confirm or correct them in the form. You provide these details: * **Contact**: full name, corporate email address, and phone number of the person who completes the form. Fintoc validates the email address before you continue. * **Company**: Mexican tax ID (RFC) including the homoclave, date of incorporation, serial number of the certificate, business activity, address, and address type. * **Settlement account**: the 18-digit standardized Mexican bank account number (CLABE) where Fintoc settles your funds. * **Legal representative**: full name, nationality, voter ID number or passport number, and position in the company. * **Shareholding structure**: name, type of person, and participation percentage of every shareholder. When a company holds more than 25% of your company, you also declare that shareholder's own shareholding structure. ## Additional questions You also answer questions that no document covers. Each answer comes from a fixed list of options: * **Source of funds**: where the company's income comes from. * **Estimated monthly volume**: the amount in Mexican pesos you expect to move each month. * **Estimated monthly operations**: the number of transactions you expect each month. * **Use of the account**: the option that best describes your operation. * **Registration as a Vulnerable Activity for virtual assets**: whether the SAT registers the company as a Vulnerable Activity for buying, selling, holding, or exchanging virtual assets. This registration is defined in article 17, section XVI of Mexico's anti-money-laundering law. Fintoc does not open accounts for companies with this registration. ## What's next * [KYC requirements in Chile](/guides/business-accounts/kyc-requirements/chile) if you also operate in Chile. * [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api) to run the KYC review of the Mexican `Entity` objects you open for your clients. # Account Source: https://docs.fintoc.com/guides/business-accounts/overview/account-data-model The `Account` data model in the Business Accounts API: the root `Account`, additional accounts, statements, balance, and cost centers per `Entity`. An `Account` holds, sends, and receives money. This page explains the `Account` data model: the root `Account`, additional `Account` objects, statements, and balance. For the API fields, see the [`Account` object reference](/api/business-accounts-api/accounts/account-object). `Account` objects have three constraints: * They are available only to businesses. * They do not support overdrafts. * Each `Account` belongs to exactly one `Entity`. ## Root account Every `Entity` has a **root `Account`**, also called its main account. Fintoc creates your root `Account` together with your root `Entity`, and creates a client `Entity`'s root `Account` when Fintoc approves that `Entity`'s onboarding. You can't modify or delete a root `Account`. ## Multiple accounts You can create additional `Account` objects under your own `Entity` to separate balances by product line. You can also create `Account` objects under your customers' `Entity` objects for per-client sub-accounts. See [Create more accounts](/guides/business-accounts/manage-accounts/creating-more-accounts). ## Cost centers Businesses in Mexico use the term cost center, or "centro de costo", for a balance they track separately. In the Business Accounts API, a cost center is an `Account`. Create one `Account` per cost center, whether that cost center holds funds for one of your product lines or for one of your clients. A cost center is not an `Entity`. An `Entity` is the legal account holder that owns `Account` objects, so creating an `Entity` does not by itself create a balance you can send money from. Create an `Entity` only when the balance must belong to a different legal name, such as a client's. Then create the `Account` under that `Entity`. See [Entity](/guides/business-accounts/overview/entity-data-model). ## Account statements Fintoc generates a monthly statement for every `Account`. You can list and download statements using `GET /v2/accounts/{account_id}/account_statements`. See [Account statements](/guides/business-accounts/manage-accounts/account-statements) for details. ## Balance Every `Account` has an `available_balance`. Fintoc immediately deducts pending outbound transfers from this balance. If a transfer fails, Fintoc restores the funds. # Account Number Source: https://docs.fintoc.com/guides/business-accounts/overview/account-number-data-model The `AccountNumber` data model in the Business Accounts API: how account numbers route inbound transfers to an `Account`, plus the root and rules. An Account Number is the string of digits that senders use to pay you. In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). In Chile, an Account Number is a bank account number on your Cuenta con Provisión de Fondos (CPF). An Account Number points to an `Account`. This page explains the relationship between Account Numbers and `Account` objects. You also learn how to configure Account Numbers and which rules apply to Account Numbers. For the API fields, see the [Account Number object](/api/business-accounts-api/account-numbers/account-number-object) reference. In Fintoc, Account Numbers and `Account` objects are decoupled. Each `Account` can have more than one Account Number. Each `Account` holds a balance. Account Numbers route incoming money. ## What you can do with Account Numbers You can use Account Numbers to: * **Reconcile payments.** Attach `metadata`, such as `customer_id` and `invoice_id`, to an Account Number. When a transfer arrives, the webhook carries that metadata back to you. * **Filter incoming transfers.** Set `options.min_amount` and `options.max_amount` to automatically reject payments above or below those limits. Fintoc applies these limits to Mexican Account Numbers. See [Add logic to Account Numbers](/guides/business-accounts/inbound-transfers/add-logic-to-clabes). * **Retire Account Numbers.** Disable an Account Number you no longer need in either country, or delete a Mexican Account Number to free quota. See [Manage your Account Numbers](/guides/business-accounts/inbound-transfers/manage-your-clabes). ## Root Account Number Fintoc creates every `Account` with one default Account Number, marked as `is_root: true`. Your outbound transfers always originate from this root Account Number. ## Rules Account Numbers follow these rules: * **You cannot reassign an Account Number.** You cannot move an Account Number from its original `Account` to a different `Account`. * **Disabled Account Numbers reject transfers automatically.** The money returns to the sender. See [Add logic to Account Numbers](/guides/business-accounts/inbound-transfers/add-logic-to-clabes). * **Deleting an Account Number releases it.** Fintoc can reassign the Account Number to another Fintoc customer. You can delete Mexican Account Numbers only. See [Manage your Account Numbers](/guides/business-accounts/inbound-transfers/manage-your-clabes). ## Account Number quota By default, you can create up to 1,000,000 Account Numbers per organization. Deleting a Mexican Account Number frees up quota. Deletion cannot be undone. If you need to create more than 1,000,000 Account Numbers, contact your sales representative. # Entity Source: https://docs.fintoc.com/guides/business-accounts/overview/entity-data-model The `Entity` data model in the Business Accounts API: the root `Entity`, `Entity` objects for your clients, cost centers, and the Know Your Customer review. An `Entity` is the legal account holder that owns `Account` objects. Each `Entity` represents an organization with its own legal identity, and each `Entity` can own more than one `Account`. This page explains the `Entity` data model: your root `Entity`, the `Entity` objects you open for your clients, and the Know Your Customer review. For the API fields, see the [`Entity` object](/api/business-accounts-api/entities/entity-object) reference. > [!NOTE] > > An `Entity` is not a cost center. Businesses in Mexico use the term cost center, or "centro de costo", for a balance they track separately, and that balance is an `Account`. See [Account](/guides/business-accounts/overview/account-data-model). ## Root entity Your business has one root `Entity` in each environment: `test` and `live`. Fintoc creates the root `Entity` automatically after you finish onboarding in `live` mode. `Account` objects under your root `Entity` hold your company's money. ## Entities for your clients Create an `Entity` for a client when transfer receipts need to show that client's legal name. For example, a marketplace can pay each seller under the seller's Chilean tax ID (RUT) or Mexican tax ID (RFC). `Entity` objects for your clients are available in Chile and Mexico. ## Know Your Customer review Fintoc's compliance team runs a Know Your Customer review for each client `Entity`. To create the `Entity` and run its review through the API, see [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api). To run the review from the dashboard, and to add `Account` objects to an `Entity` that Fintoc already approved, see [Create more accounts](/guides/business-accounts/manage-accounts/creating-more-accounts). # Business Accounts overview Source: https://docs.fintoc.com/guides/business-accounts/overview/index Use Fintoc's Business Accounts API to receive, send, and reconcile bank transfers in Chile and Mexico with `Entity`, `Account`, and `Transfer` objects. The Business Accounts API lets you receive, send, and reconcile bank transfers in Chile and Mexico. This page introduces the API and its objects. For the full endpoint reference, see the [Business Accounts API reference](/api/business-accounts-api/transfers/transfer-object). With the Business Accounts API, you can: * **Create accounts** and assign them to your orders or customers to reconcile inbound transfers against a known account. * **Receive** bank transfers at an Account Number you assign to a customer or an order. In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). In Chile, an Account Number is a bank account number that Fintoc issues on your Cuenta con Provisión de Fondos (CPF). * **Send** transfers to any account and track each transfer's status via webhooks. Transfers move over the local interbank rails: the Sistema de Pagos Electrónicos Interbancarios in Mexico and the Centro de Compensación Automatizado in Chile. ## How it fits together A minimal integration has four objects: * **[`Entity`](/guides/business-accounts/overview/entity-data-model)**: a legal person or business. Your business is the **root `Entity`**. * **`Account`**: holds a balance. Your company's account is the **root `Account`**. * **Account Number**: the string of digits you share with senders. In Mexico, an Account Number is a CLABE. In Chile, an Account Number is a bank account number. Each `Account` can have more than one Account Number. * **`Transfer`**: a single money movement, inbound or outbound. ## Availability by country Business Accounts API capabilities vary by country: | Capability | Mexico 🇲🇽 | Chile 🇨🇱 | | :- | :- | :- | | Inbound transfers | ✅ | ✅ | | Outbound transfers | ✅ | ✅ | | Accounts | ✅ | ✅ | | Account statements | ✅ | ✅ | | Account Numbers | ✅ (CLABE) | ✅ | | Metadata on an Account Number | ✅ | ✅ | | Disabling an Account Number | ✅ | ✅ | | Inbound amount limits | ✅ | ❌ | | Deleting an Account Number | ✅ | ❌ | | Batch transfers (Dashboard only) | ✅ | ✅ | | Transfer returns | ✅ | ❌ | | Account Number verification | ✅ (CLABE) | ❌ | | `Entity` objects for your own clients | ✅ | ❌ | # Movements Source: https://docs.fintoc.com/guides/business-accounts/overview/movement How `Movement` objects track changes to your `Account` balance in the Business Accounts API, including movement types, `resource_id`, and balance tracking. This page explains how `Movement` objects track changes to your account balance. A `Movement` represents a transaction that changes the balance of your `Account`. Fintoc creates a `Movement` whenever money enters or leaves the account. For field definitions, see the [`Movement` object](/api/business-accounts-api/movements/movement-object) reference. Use `Movement` objects as your audit trail. Each `Movement` records the account balance after Fintoc processes the transaction. The recorded balances let you reconstruct your account balance at any point. ## Movement types The `type` field identifies the source of a `Movement`. The Business Accounts `Movement` object schema documents one value: | Type | Description | Example `resource_id` | | - | - | - | | `transfer` | An inbound or outbound transfer between accounts. The `resource_id` references a `Transfer` object. | `tr_30EsX5bIoUCusF2dduyJGY7KmrL` | For details about `type` and the object referenced by `resource_id`, see the [`Movement` object](/api/business-accounts-api/movements/movement-object) reference. ## Balance tracking Every `Movement` includes the account balance after Fintoc processes the transaction. The recorded value lets you reconstruct your account balance after any transaction. # Transfer Source: https://docs.fintoc.com/guides/business-accounts/overview/transfer-data-model The `Transfer` data model in the Business Accounts API: the `Counterparty`, transfer statuses and webhooks, limits, returns, and authorization requirements. A `Transfer` represents one inbound or outbound money movement. Inbound transfers land on an Account Number; outbound transfers debit an `Account`. This page explains the `Transfer` data model: the `Counterparty`, statuses, limits, returns, and authorization. For the field-by-field reference, see [the `Transfer` object](/api/business-accounts-api/transfers/transfer-object). ## Transfer counterparty Each `Transfer` includes a nested `Counterparty` object that represents the other party in the transfer: either the sender or the recipient, depending on the direction. The `Counterparty` object includes these details: * Counterparty name, such as a customer, supplier, or partner. * Bank account details, such as the account number and bank code. The counterparty's role depends on the transfer direction: * For inbound transfers, the `Counterparty` is the entity that sent funds to your Account Number. * For outbound transfers, the `Counterparty` is the entity that receives funds from your `Account`. Use this structure to view and reconcile transfers consistently in either direction. ## Transfer statuses and webhook notifications A `Transfer` moves through these statuses, and Fintoc emits a webhook for each transition: ![Transfer status lifecycle and the webhook event Fintoc emits at each transition](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/65876da117aa2b5d08bccd474ddcdde2386fd12e362f6d76e18362625c371874-image.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=26eef6ccbefe18a20b407ecd5d96c2a3) Chilean outbound transfers can also reach `partially_succeeded` when only some parts of a transfer over \$7,000,000 CLP settle, or `reversed` after a settled transfer is reversed. Fintoc emits `transfer.outbound.partially_succeeded` and `transfer.outbound.reversed` for these transitions. A `Transfer` reports one of these statuses: | Status | Description | | :- | :- | | `pending` | Fintoc is processing the transfer. | | `succeeded` | The transfer settled. | | `partially_succeeded` | 🇨🇱 Only some parts of a split outbound transfer settled. | | `rejected` | The receiving party rejected an inbound transfer while it was `pending`. The transfer never settled. | | `failed` | Fintoc could not process the transfer, or the receiving party rejected an outbound transfer. For Chilean transfers, `error_reason` explains why. | | `return_pending` | A return is in progress. | | `returned` | The transfer settled, and then returned to the sender. | | `reject_failed` | Fintoc started a rejection while the transfer was `pending` and could not complete it. | | `reverse_pending` | A reversal is in progress. | | `reversed` | The transfer settled, and Fintoc reversed the transfer later. | Chilean outbound transfers can report `partially_succeeded`. All Chilean transfers can report `reverse_pending` and `reversed`. Mexican transfers do not report any of these statuses. ### Final statuses `failed`, `rejected`, `partially_succeeded`, `returned`, and `reversed` are final. A `succeeded` transfer can still move to `return_pending` and `returned`, or in Chile to `reverse_pending` and `reversed`. A transfer reaches `rejected` or `reject_failed` only from `pending`, so a `succeeded` transfer never becomes `rejected`. When a Chilean outbound transfer fails, Fintoc credits the full `amount` back to your available balance, and the recipient does not receive the funds. See [Chilean transfer failure reasons](/guides/business-accounts/outbound-transfers/failure-reasons). Outbound transfers never report `rejected`, in Chile or in Mexico. A recipient institution or Banco de México rejection moves an outbound transfer to `failed`, and Fintoc sends `transfer.outbound.failed`. For Mexican rejections, see the [SPEI rejection causes](/api/business-accounts-api/transfers/spei-codes). If a transfer reports `reject_failed`, contact Fintoc support with the transfer `id` before you take any other action on it. ## Transfer limits The `Transfer` API does not set a maximum amount in Mexico or Chile. In Chile, some banks cap incoming transfers at \$7,000,000 CLP. Fintoc splits an outbound transfer over \$7,000,000 CLP into parts of up to \$7,000,000 CLP and reports the result on the single `Transfer` you created. Fintoc sends the parts one after another, so a split transfer stays `pending` longer than a single transfer. Transfers between Fintoc accounts are not split. See [Large transfers in Chile](/guides/business-accounts/outbound-transfers#large-transfers-in-chile). ## Rate limits The Business Accounts API accepts up to 10 `Transfer` requests per second per organization by default. Contact Fintoc support to request a higher limit. ## Transfer returns ### 🇲🇽 Mexico In Mexico, you can request the return of an inbound `Transfer` that you don't recognize or that doesn't meet your business's acceptance criteria. When Fintoc returns the `Transfer`, the status changes to `returned`. Fintoc deducts the transfer amount from your account balance. ### 🇨🇱 Chile In Chile, you can request the return of an inbound `Transfer` in the `succeeded` status. If the `Transfer` comes from another bank, wait 90 seconds after it reaches `succeeded` before you request the return. When Fintoc returns the `Transfer`, the status changes to `returned`. Fintoc deducts the transfer amount from your account balance. See [Return a transfer](/guides/business-accounts/inbound-transfers/returning-an-inbound-transfer). ## Authorizing a transfer Manual transfers in the dashboard use transfer permissions and approval percentages. This approval flow does not apply to transfers created through the API. For API transfers, follow [Send transfers](/guides/business-accounts/outbound-transfers). ### Authorize manual transfers in the dashboard When you create a manual transfer, your permission and approval percentage determine what happens: * **Authorize with 100%:** Your authorization is enough to create the transfer immediately. You do not need another person's approval. * **Authorize with less than 100%:** Your approval contributes your assigned percentage. The request stays pending authorization until another person approves and the combined approvals reach 100%. * **Manage only:** You create a request without contributing an approval percentage. One or more people with Authorize permission must approve until the combined approvals reach 100%. For example, two approvals of 50% satisfy the requirement. One approval of 100% also satisfies it. Reaching 100% creates the `Transfer`; it does not mean the funds have settled. Track the result through the [transfer statuses](#transfer-statuses-and-webhook-notifications). ### If you cannot authorize a transfer The Admin role and one-time password authentication are not enough to authorize transfers. You also need Authorize permission and an assigned approval percentage for the account the transfer debits. If you can see a request in **Business Accounts → Transfers → Authorizations**, but cannot approve it, check your transfer permissions. Manage permission alone does not let you approve, even if another person created the request. If your permissions do not match your responsibilities, contact Fintoc support to review your authorization setup. See [Permission roles](/guides/home/dashboard/permission-roles) for access levels. # Send your first transfer Source: https://docs.fintoc.com/guides/business-accounts/quickstart Send your first Fintoc test transfer end to end, from generating API keys to subscribing to webhook events, using the Business Accounts API sandbox environment. By the end, you will have signed your requests with a JSON Web Signature (JWS), funded a test `Account`, and sent your first `Transfer`. The examples cover Mexico and Chile. Pick the tab for the country your organization operates in. ## Step 1: Get your test API keys In the [dashboard](https://dashboard.fintoc.com/), go to **Developers → API Keys**. You'll see keys for `test` (`sk_test_...`) and `live` (`sk_live_...`) modes. Copy the `test` secret key. ## Step 2: Register JWS keys Money-moving endpoints require signed requests. These endpoints create transfers, return transfers, or verify a standardized Mexican bank account number. Follow [Generate JWS keys](/guides/business-accounts/setup/setting-up-jws-keys) to create a key pair and upload the public key. Return to this page when you're done. ## Step 3: List your accounts Every organization starts with a root `Account`. In Mexico, a root `Account` is also known as Centro de Costos. Fetch the root account with a `GET` request to `/v2/accounts`: ```bash cURL theme={null} curl --request GET \ --url https://api.fintoc.com/v2/accounts \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' ``` The response looks like this. The `currency` and the shape of `root_account_number` depend on the country of your organization: ```json Mexico theme={null} [ { "id": "acc_23JlasHas241", "object": "account", "mode": "test", "description": "My root account", "root_account_number": "000000000000000000", "root_account_number_id": "acno_Kasf91034gj1AD", "available_balance": 0, "currency": "MXN", "entity": { "id": "ent_4324qwkalsds", "holder_name": "Test Entity 1", "holder_id": "ND" } } ] ``` ```json Chile theme={null} [ { "id": "acc_23JlasHas241", "object": "account", "mode": "test", "description": "My root account", "root_account_number": "000000001", "root_account_number_id": "acno_Kasf91034gj1AD", "available_balance": 0, "currency": "CLP", "entity": { "id": "ent_4324qwkalsds", "holder_name": "Test Entity 1", "holder_id": "11.111.111-1" } } ] ``` ### Use an SDK If you're using Node or Python, install the [Node SDK](https://github.com/fintoc-com/fintoc-node) or [Python SDK](https://github.com/fintoc-com/fintoc-python) to call the API. The SDK signs each request with [JWS](/guides/business-accounts/setup/setting-up-jws-keys) and handles pagination. Install an SDK: ```bash Install Node SDK theme={null} npm install fintoc ``` ```bash Install Python SDK theme={null} pip install fintoc ``` List your accounts: ```javascript Node theme={null} const { Fintoc } = require('fintoc'); // You can provide a path to your PEM file or pass the PEM key directly as a string. // const privateKey = process.env.JWS_PRIVATE_KEY; const privateKey = './private_key.pem'; const fintoc = new Fintoc('YOUR_TEST_SECRET_KEY', privateKey); const accounts = await fintoc.v2.accounts.list(); for await (const account of accounts) { console.log(account.id, account.description, account.root_account_number, account.available_balance); } ``` ```python Python theme={null} from fintoc import Fintoc # You can provide a path to your PEM file or pass the PEM key directly as a string. # jws_private_key = os.environ.get('JWS_PRIVATE_KEY') jws_private_key = "./private_key.pem" client = Fintoc("YOUR_TEST_SECRET_KEY", jws_private_key=jws_private_key) for account in client.v2.accounts.list(): print(account.id, account.description, account.root_account_number, account.available_balance) ``` Keep the `id` (`acc_...`) and `root_account_number_id` (`acno_...`) from the response. Use `root_account_number_id` to fund the test `Account`. Use `id` to create the outbound `Transfer`. ## Step 4: Fund your test account Your test `Account` starts empty. Simulate an inbound transfer so you have money to send: ```bash Mexico theme={null} curl --request POST \ --url https://api.fintoc.com/v2/simulate/receive_transfer \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_number_id": "acno_Kasf91034gj1AD", "amount": 59013, "currency": "MXN" } ' ``` ```bash Chile theme={null} curl --request POST \ --url https://api.fintoc.com/v2/simulate/receive_transfer \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_number_id": "acno_Kasf91034gj1AD", "amount": 59013, "currency": "CLP" } ' ``` The response is the simulated inbound `Transfer` that funds your `Account`: ```json Mexico theme={null} { "id": "tr_7HbN2kPq9wZ4xR1s", "object": "transfer", "amount": 59013, "currency": "MXN", "status": "succeeded", "direction": "inbound", "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number" }, "comment": "Simulated inbound transfer" } ``` ```json Chile theme={null} { "id": "tr_7HbN2kPq9wZ4xR1s", "object": "transfer", "amount": 59013, "currency": "CLP", "status": "succeeded", "direction": "inbound", "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number" }, "comment": "Simulated inbound transfer" } ``` > [!WARNING] > > **Currencies are represented as integers** > > The Fintoc API represents money in the smallest currency unit as an integer with no decimals. An amount of \$590.13 MXN is `59013`. CLP has no minor unit, so an amount of \$59,013 CLP is also `59013`. > > See [Currencies](/guides/home/currencies). See [Test your integration](/guides/business-accounts/setup/test-your-integration) for simulations of failures, returns, and rejected payouts. ## Step 5: Send your first transfer Create an outbound `Transfer` from the test `Account` you funded. In Mexico, the `counterparty` needs only the recipient's standardized Mexican bank account number (CLABE). In Chile, the `counterparty` also needs the recipient's Chilean tax ID (RUT), name, account type, and institution: ```bash Mexico theme={null} curl --request POST \ --url https://api.fintoc.com/v2/transfers \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'Fintoc-JWS-Signature: YOUR_JWS_SIGNATURE' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 59013, "currency": "MXN", "account_id": "acc_23JlasHas241", "comment": "Pago de credito 10451", "reference_id": "150195", "counterparty": { "account_number": "012000000000000001" } }' ``` ```bash Chile theme={null} curl --request POST \ --url https://api.fintoc.com/v2/transfers \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'Fintoc-JWS-Signature: YOUR_JWS_SIGNATURE' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 59013, "currency": "CLP", "account_id": "acc_23JlasHas241", "comment": "Pago de credito 10451", "counterparty": { "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "11111111", "account_type": "checking_account", "institution_id": "cl_banco_de_chile" } }' ``` The response is the outbound `Transfer` you created: ```json Mexico theme={null} { "id": "tr_5pQ8rXcViBnM3kL2", "object": "transfer", "amount": 59013, "currency": "MXN", "status": "succeeded", "direction": "outbound", "comment": "Pago de credito 10451", "reference_id": "150195", "counterparty": { "account_number": "012000000000000001" } } ``` ```json Chile theme={null} { "id": "tr_5pQ8rXcViBnM3kL2", "object": "transfer", "amount": 59013, "currency": "CLP", "status": "succeeded", "direction": "outbound", "comment": "Pago de credito 10451", "reference_id": null, "counterparty": { "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "11111111", "account_type": "checking_account", "institution": { "id": "cl_banco_de_chile", "name": "Banco de Chile", "country": "cl" } } } ``` ## Step 6: Create a webhook endpoint Webhooks notify your server when a transfer settles, so you don't need to poll for status. Go to **Developers → Webhooks** in the dashboard. Add your URL, then subscribe to `transfer.inbound.succeeded` and `transfer.outbound.succeeded`. ## Test the integration Confirm the full flow worked end to end: 1. After Step 4, list your accounts again and confirm `available_balance` increased by `59013`. 2. Confirm the Step 5 transfer returns `"status": "succeeded"`. 3. After Step 6, repeat Steps 4 and 5. Confirm your endpoint receives a `transfer.outbound.succeeded` webhook for the new outbound transfer. # Setup Source: https://docs.fintoc.com/guides/business-accounts/setup/index Set up JSON Web Signature signing keys, test your Business Accounts integration in `test` mode, and review the security controls that protect your transfers. Complete these setup tasks before you move money in production. Configure your signing keys and test your integration end to end in `test` mode. Then review your security controls. Each task links to a detailed guide: * [Set up JSON Web Signature signing keys](/guides/business-accounts/setup/setting-up-jws-keys): generate and register the key pair that signs your transfer requests. * [Test your integration](/guides/business-accounts/setup/test-your-integration): simulate inbound and outbound transfers and verify webhook delivery. * [Review security controls](/guides/resources/security-controls): learn how Fintoc uses authentication, signing, and audit controls to protect transfers. # Generate JWS keys Source: https://docs.fintoc.com/guides/business-accounts/setup/setting-up-jws-keys Generate a public-private key pair, register the public key, and sign Business Accounts API requests that move money with a JSON Web Signature (JWS). Set up a public-private key pair to sign protected Business Accounts API requests. Business Accounts API requests that move money must include a JSON Web Signature (JWS). A JWS digitally signs data to ensure its integrity and authenticity. Protected actions include [creating outbound transfers](/api/business-accounts-api/transfers/transfers-create) and returning inbound transfers. ## Generate a public and private JWS key pair Run these commands in your terminal: ```bash theme={null} openssl genrsa -out private_key.pem 2048 openssl rsa -in private_key.pem -outform PEM -pubout -out public_key.pem ``` These commands generate two files: * `private_key.pem`, containing your private key. * `public_key.pem`, containing your public key. The files use the following formats: ```text public_key.pem theme={null} -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoPPSwkMAHrLy6ZY+cOIP jl6PxkrKJBicwMBMgFPf0Vtqe6QWepeOWXQuLgW+cSDI0KBjk8eZQEVB7GY3OwOl DcknxUkaVueEvsDiY74xeC1iN2Gfb6HXd2JqgDWdWy/HNv2eUe9kmsSPSSgruA8Y DvR6lpjPvAEJHP4Sg/B+9c0gBTDmqadL8UD291D7JbHmG4lIBT5NbhpOVnSBN0aC R6ioxWz+VJoz68qsxHQ69TYhl8/jG79ocvZsZEWCWc/Kv7SP6/cPJHu0oGWVZwa4 5BtPLeMQ9ZleHdV6RCUbxFXKzbZF5fKQ+z5NWk+hMz5TCs4jwmg1nodWyW+bL7K9 YQIDAQAB -----END PUBLIC KEY----- ``` ```text private_key.pem theme={null} -----BEGIN PRIVATE KEY----- -----END PRIVATE KEY----- ``` > [!WARNING] > > **Never share your JWS private key** > > Your JWS private key is sensitive and must remain confidential. Fintoc never asks for this key. Anyone with your private key can sign malicious transfer requests on your behalf. ## Upload your public key to the dashboard 1. Go to [dashboard.fintoc.com](https://dashboard.fintoc.com). 2. Open **API Keys** in the sidebar. 3. If your organization has products that require JWS, open **JWS Public Keys**, select **Add JWS Key**, and upload your JWS public key. ## Generate a signature After you upload your public key to the Fintoc dashboard, generate signatures with your private key. Each signature protects the integrity and authenticity of a Business Accounts API call that moves money. ## Generate signatures with an SDK The [Node SDK](https://github.com/fintoc-com/fintoc-node) and [Python SDK](https://github.com/fintoc-com/fintoc-python) generate signatures for you. Pass the private key when you initialize the Fintoc client. The SDK then signs each protected request: ```javascript Node theme={null} const { Fintoc } = require('fintoc'); // Provide a path to your PEM file const fintoc = new Fintoc('YOUR_API_KEY', 'private_key.pem'); // Or pass the PEM key directly as a string // const fintoc = new Fintoc('YOUR_API_KEY', process.env.JWS_PRIVATE_KEY); // The client now signs protected transfer requests ``` ```python Python theme={null} import os from fintoc import Fintoc # Provide a path to your PEM file client = Fintoc("YOUR_API_KEY", jws_private_key="private_key.pem") # Or pass the PEM key directly as a string # client = Fintoc("YOUR_API_KEY", jws_private_key=os.environ.get('JWS_PRIVATE_KEY')) # The client now signs protected transfer requests ``` ## Generate a signature manually If you want to write your own implementation or use a different programming language, follow these steps: ### Prepare the payload JWS signature generation operates on the exact JSON string sent in the HTTP request. Create that string by serializing your outbound transfer request body with your language's JSON serializer. ```javascript Node theme={null} const body = { amount: 100000, currency: 'MXN', account_id: 'YOUR_ACCOUNT_ID', counterparty: { account_number: '000000000000000000' } }; const rawBody = JSON.stringify(body); ``` ```python Python theme={null} import json body = { "amount": 100000, "currency": "MXN", "account_id": "YOUR_ACCOUNT_ID", "counterparty": { "account_number": "000000000000000000" } } raw_body = json.dumps(body) ``` > [!NOTE] > > **JSON string must be consistent** > > When serializing your request body to JSON, you must use the exact same string for two purposes: > > 1. Creating the JWS signature > 2. Sending as the payload in your HTTP request > > Any difference between the JSON used to create the JWS signature and the HTTP request payload may invalidate the signature. ### Load the private key and configure headers Load your private key from the PEM file and configure the protected JWS header. The header includes the `RS256` signing algorithm, a unique `nonce`, and the current Unix timestamp in `ts`. The `crit` field identifies `ts` and `nonce` as critical fields. ```javascript Node theme={null} // Load the private key const privateKey = readFileSync('./private_key.pem', 'utf8'); // Define the JWS headers const headers = { alg: 'RS256', // Signing algorithm. Must be "RS256" nonce: crypto.randomBytes(16).toString('hex'), // Unique string for each request ts: Math.floor(Date.now() / 1000), // Unix timestamp in seconds crit: ['ts', 'nonce'] // Critical headers }; ``` ```python Python theme={null} # Load the private key with open('./private_key.pem', 'rb') as f: private_key = serialization.load_pem_private_key( f.read(), password=None ) # Define the JWS headers headers = { "alg": "RS256", # Signing algorithm. Must be "RS256" "nonce": secrets.token_hex(16), # Unique string for each request "ts": int(time.time()), # Unix timestamp in seconds "crit": ["ts", "nonce"] # Critical headers } ``` #### Prevent replay attacks Fintoc uses the `nonce` and `ts` headers during JWS authentication to protect against [replay attacks](https://en.wikipedia.org/wiki/Replay_attack) and ensure request integrity. Include a unique, random `nonce` in every request. The `nonce` makes each signature distinct, even when you send the same data multiple times. Fintoc accepts each `nonce` only once and rejects requests that reuse a `nonce`. The Unix timestamp in `ts` records when you created the request. Fintoc validates that the timestamp falls within a 2-minute window and rejects outdated requests. Together, `nonce` and `ts` prevent replays: Fintoc rejects any intercepted request that reuses a `nonce` or falls outside the timestamp window. ### Generate the signing input Create the JWS signing input by joining the base64url-encoded `headers` and `raw_body` with a period (`.`). Encode both values without padding: ```javascript Node theme={null} // Base64url-encode the protected JWS header without padding const protectedBase64 = Buffer.from(JSON.stringify(headers)) .toString('base64url'); // Base64url-encode rawBody without padding const payloadBase64 = Buffer.from(rawBody) .toString('base64url'); // Join the encoded protected header and payload const signingInput = `${protectedBase64}.${payloadBase64}`; ``` ```python Python theme={null} # Base64url-encode the protected JWS header without padding protected_base64 = base64.urlsafe_b64encode( json.dumps(headers).encode() ).rstrip(b'=').decode() # Base64url-encode raw_body without padding payload_base64 = base64.urlsafe_b64encode( raw_body.encode() ).rstrip(b'=').decode() # Join the encoded protected header and payload signing_input = f"{protected_base64}.{payload_base64}" ``` ### Generate the JWS token signature Create the cryptographic signature from the signing input and your private key: 1. Sign the signing input with your private key using RSA and PKCS #1 v1.5 padding. 2. Base64url-encode the resulting signature without padding. ```javascript Node theme={null} // Sign the signing input const signatureRaw = crypto.createSign('sha256') .update(signingInput) .sign({ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }); // Base64url-encode the raw signature without padding const signatureBase64 = Buffer.from(signatureRaw) .toString('base64url'); ``` ```python Python theme={null} # Sign the signing input signature_raw = private_key.sign( signing_input.encode(), padding.PKCS1v15(), hashes.SHA256() ) # Base64url-encode the raw signature without padding signature_base64 = base64.urlsafe_b64encode(signature_raw).rstrip(b'=').decode() ``` ### Verify the JWS token (optional) Some libraries re-encode JSON payloads with different spacing, key ordering, or character encoding. To debug a signature, decode the payload locally and confirm that it matches the `raw_body` sent in the HTTP request. Do not share a token that contains sensitive transfer data. ```javascript Node theme={null} const token = `${protectedBase64}.${payloadBase64}.${signatureBase64}`; console.log(token); const payload = Buffer.from(payloadBase64, 'base64url').toString(); console.log(payload); // Should equal rawBody sent in the HTTP request ``` ```python Python theme={null} token = f"{protected_base64}.{payload_base64}.{signature_base64}" print(token) payload = base64.urlsafe_b64decode( payload_base64 + '=' * (-len(payload_base64) % 4) ) print(payload.decode()) # Should equal raw_body sent in the HTTP request ``` ### Construct the `Fintoc-JWS-Signature` header Construct the `Fintoc-JWS-Signature` header by concatenating the protected header and signature: ```javascript Node theme={null} const jwsSignatureHeader = `${protectedBase64}.${signatureBase64}`; ``` ```python Python theme={null} jws_signature_header = f"{protected_base64}.{signature_base64}" ``` ## Use the complete example The following functions combine the manual signature steps. Install the Python `cryptography` package before running the Python example. ```javascript Node theme={null} const crypto = require('crypto'); const { readFileSync } = require('fs'); function generateJwsSignatureHeader(rawBody) { // Read private key const privateKey = readFileSync('./private_key.pem', 'utf8'); const headers = { alg: 'RS256', nonce: crypto.randomBytes(16).toString('hex'), ts: Math.floor(Date.now() / 1000), crit: ['ts', 'nonce'] }; const protectedBase64 = Buffer.from(JSON.stringify(headers)) .toString('base64url'); const payloadBase64 = Buffer.from(rawBody) .toString('base64url'); const signingInput = `${protectedBase64}.${payloadBase64}`; const signatureRaw = crypto.createSign('sha256') .update(signingInput) .sign({ key: privateKey, padding: crypto.constants.RSA_PKCS1_PADDING }); const signatureBase64 = Buffer.from(signatureRaw) .toString('base64url'); return `${protectedBase64}.${signatureBase64}`; } const payload = { amount: 100000, currency: 'MXN', account_id: 'YOUR_ACCOUNT_ID', counterparty: { account_number: '000000000000000000' } }; const rawBody = JSON.stringify(payload); // Exact payload to send in the HTTP request // Signature to include in the 'Fintoc-JWS-Signature' request header const jwsSignatureHeader = generateJwsSignatureHeader(rawBody); ``` ```python Python theme={null} import base64 import json import secrets import time from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import serialization def generate_jws_signature_header(raw_body): # Read private key with open('./private_key.pem', 'rb') as f: private_key = serialization.load_pem_private_key( f.read(), password=None ) # Create headers headers = { 'alg': 'RS256', 'nonce': secrets.token_hex(16), 'ts': int(time.time()), 'crit': ['ts', 'nonce'] } # Base64url-encode without padding protected_base64 = base64.urlsafe_b64encode( json.dumps(headers).encode() ).rstrip(b'=').decode() payload_base64 = base64.urlsafe_b64encode( raw_body.encode() ).rstrip(b'=').decode() signing_input = f"{protected_base64}.{payload_base64}" # Sign the signing input signature_raw = private_key.sign( signing_input.encode(), padding.PKCS1v15(), hashes.SHA256() ) signature_base64 = base64.urlsafe_b64encode(signature_raw).rstrip(b'=').decode() return f"{protected_base64}.{signature_base64}" body = { "amount": 100000, "currency": "MXN", "account_id": "YOUR_ACCOUNT_ID", "counterparty": { "account_number": "000000000000000000" } } raw_body = json.dumps(body) # Exact payload to send in the HTTP request # Signature to include in the 'Fintoc-JWS-Signature' request header jws_signature_header = generate_jws_signature_header(raw_body) ``` ## Test the integration Confirm your signature works before you go live. Using a `test` mode API key, sign a [create outbound transfer](/api/business-accounts-api/transfers/transfers-create) request and send the signature in the `Fintoc-JWS-Signature` header. 1. Build the request body and serialize it with your JSON serializer. 2. Generate the signature from the serialized body with the function above. 3. Send the request with the `Fintoc-JWS-Signature` header set to the generated signature. Fintoc returns `201 Created` and the created transfer when the signature is valid. A signature error or `401 Unauthorized` response can indicate a mismatched request body, a reused `nonce`, or a `ts` value outside the 2-minute window. # Test transfers Source: https://docs.fintoc.com/guides/business-accounts/setup/test-your-integration Simulate inbound and outbound transfers on Fintoc's test environment to validate your integration end to end before switching to live API keys. To confirm that your integration works correctly, simulate transfers without moving any money using test amounts and counterparty account numbers in `test` mode. Use test API keys for every API call in `test` mode. ## Simulate an inbound transfer Fintoc lets you simulate an inbound transfer through the API or the dashboard. You can only use account numbers created in `test` mode. To create an account number, see [Create an account number](/guides/business-accounts/inbound-transfers#step-1-create-an-account-number). Simulate an inbound transfer with the API or an SDK. The following example simulates a transfer of \$1,020.00 MXN. Replace `YOUR_ACCOUNT_NUMBER_ID` with an account number created in `test` mode: ```bash curl theme={null} curl --request POST \ --url 'https://api.fintoc.com/v2/simulate/receive_transfer' \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ -d account_number_id=YOUR_ACCOUNT_NUMBER_ID \ -d amount=102000 \ -d currency='MXN' ``` ```javascript Node theme={null} const simTransfer = await fintoc.v2.simulate.receiveTransfer({ account_number_id: 'YOUR_ACCOUNT_NUMBER_ID', amount: 102000, currency: 'MXN' }); ``` ```python Python theme={null} transfer = client.v2.simulate.receive_transfer( amount=102000, currency="MXN", account_number_id="YOUR_ACCOUNT_NUMBER_ID", ) ``` ```json Response theme={null} { "id": "tr_2vF18OHZdXXxPJTLJ5qghpo1pdU", "object": "transfer", "account_number": { "id": "acno_2vF18OHZdXXxPJTLJ5qghpo1pdU", "object": "account_number", "account_id": "acc_000000000000000000", "created_at": "2026-06-23T12:00:00.000Z", "description": "Payins", "metadata": {}, "mode": "test", "number": "000000000000000000" }, "amount": 102000, "comment": "Test inbound transfer", "counterparty": { "account_number": "000000000000000001", "account_type": "clabe", "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "institution": { "id": "mx_banco_bbva", "country": "mx", "name": "BBVA Mexico" } }, "currency": "MXN", "direction": "inbound", "metadata": {}, "mode": "test", "post_date": "2026-06-23T00:00:00.000Z", "receipt_url": "https://www.banxico.org.mx/cep/example", "reference_id": "000000", "return_reason": null, "status": "succeeded", "tracking_key": "TEST0000000000000001", "transaction_date": "2026-06-23T12:00:00.000Z" } ``` > [!NOTE] > > **Simulate endpoint** > > The `/simulate/*` endpoints simulate production behavior and are available only in `test` mode. ### Test returning an inbound transfer A simulated inbound transfer always succeeds, regardless of its `amount`. The `amount` only determines what happens when you [return the transfer](/guides/business-accounts/inbound-transfers/returning-an-inbound-transfer) in `test` mode: | Return outcome | Inbound transfer `amount` (smallest currency unit) | | :- | :- | | Transfer returned successfully | Any value except `9999` | | Failed return | `9999` (99.99 MXN) | ## Test outbound transfers Fintoc provides counterparty test values for Mexico and Chile to simulate transfer outcomes. When you create a test outbound transfer, you receive the same webhooks you receive in `live` mode. ### Mexico 🇲🇽 To simulate different outbound transfer outcomes, use one of the following counterparties: | Scenario | Counterparty test values | | - | - | | Regular `Transfer` flow. If you have enough funds, the transfer succeeds. Otherwise, the API returns an insufficient funds error. | `account_number`: Any account number at a non-Fintoc institution. You can use these standardized Mexican bank account numbers (CLABEs): 012969100000000110 646969100000000214 | | External errors cause the `Transfer` to fail. | `account_number`: 012969100000000013 | | The recipient institution returns the `Transfer`. | `account_number`: 012969100000000026 | ### Chile 🇨🇱 Use one of the following counterparties to simulate transfers in Chile. The two Chilean tax IDs (RUTs) below are Fintoc sandbox values that force a specific outcome in `test` mode. They identify no real person, and they carry no meaning in `live` mode: | Scenario | Counterparty test values | | - | - | | Regular `Transfer` flow. If you have enough funds, the transfer succeeds. Otherwise, the API returns an insufficient funds error. | `holder_id`: Any valid Chilean tax ID (RUT) `holder_name`: Any name `account_number`: Any account number `account_type`: `checking_account` or `sight_account` `institution_id`: Any institution ID | | Insufficient funds cause the `Transfer` to fail. | `holder_id`: 41579263-8 `holder_name`: Any name `account_number`: Any account number `account_type`: `checking_account` or `sight_account` `institution_id`: Any institution ID | | The Centro de Compensación Automatizado returns the `Transfer`. | `holder_id`: 40427672-7 `holder_name`: Any name `account_number`: Any account number `account_type`: `checking_account` or `sight_account` `institution_id`: Any institution ID | # Collect payments with dedicated Account Numbers Source: https://docs.fintoc.com/guides/business-accounts/use-cases/collect-payments-with-dedicated-account-numbers Assign each customer or order its own Fintoc Account Number to identify inbound transfers automatically through metadata, without matching amounts or names. ## What you'll build Give each customer or order a dedicated Account Number to identify incoming payments. In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). In Chile, an Account Number is a bank account number on your Cuenta con Provisión de Fondos (CPF). This pattern works in both countries. When money reaches the Account Number, Fintoc sends you a webhook with the `metadata` you attached when you created the Account Number. Use the `metadata` to identify the customer or order without parsing bank statements or matching amounts. ## When to use it Use dedicated Account Numbers for these flows: * Lending installments, insurance premiums, and software-as-a-service subscriptions. * Flows with identifiable customers who pay you repeatedly. * Marketplaces where each buyer deposits funds to a stable Account Number. ## How it works ```text theme={null} 1. Your backend creates an Account Number with metadata.customer_id. 2. Fintoc returns an Account Number. 3. Your customer sends a Transfer to that Account Number. 4. Fintoc fires transfer.inbound.succeeded with your metadata attached. 5. Your backend marks the invoice paid. ``` The sequence includes Mexico's Sistema de Pagos Electrónicos Interbancarios (SPEI) and Chile's Transferencia Electrónica de Fondos (TEF). ```mermaid theme={null} sequenceDiagram autonumber participant You as Your backend participant Fintoc participant Customer You->>Fintoc: Create Account Number (with metadata.customer_id) Fintoc-->>You: Account Number 738969… You-->>Customer: Show this Account Number on the invoice Customer->>Fintoc: SPEI/TEF to that Account Number Fintoc->>You: transfer.inbound.succeeded (includes your metadata) You->>You: Mark invoice paid ``` ## One Account Number per customer, or one per order? Both patterns work; the right choice depends on how you reconcile payments: | Consideration | One per customer | One per order | | - | - | - | | Account Numbers needed | Number of customers | Number of open orders | | Reconciliation | Match by customer, then amount | Match directly to order | | Cleanup | Delete when the customer leaves | Delete when the order is paid | One Account Number per order lets you match each transfer directly to an order. Disable or delete the Account Number after you receive payment for the order to prevent additional payments. ## Implementation checklist Follow these steps to implement dedicated Account Numbers: 1. **Create the Account Number** with `metadata`. See [Receive transfers → Create an Account Number](/guides/business-accounts/inbound-transfers). 2. **Handle the webhook.** Subscribe to `transfer.inbound.succeeded`; read `data.account_number.metadata`. See [Receive transfers → Webhook payload](/guides/business-accounts/inbound-transfers) for the payload reference. 3. **Enforce business rules.** Disable the Account Number after receiving payment. In Mexico, also set `options.min_amount` and `options.max_amount` to reject incorrect amounts automatically. See [Add logic to Account Numbers](/guides/business-accounts/inbound-transfers/add-logic-to-clabes). 4. **Clean up unused Account Numbers** when customers leave or orders close. Disable them in either country, and delete them in Mexico to free quota. See [Manage your Account Numbers](/guides/business-accounts/inbound-transfers/manage-your-clabes). You can have up to 1,000,000 Account Numbers. Unused Account Numbers continue accepting transfers. These transfers can add unrelated entries to your reconciliation and statements. # Choose your use case Source: https://docs.fintoc.com/guides/business-accounts/use-cases/index Choose among five Business Accounts patterns: dedicated Account Numbers for payins, payouts, wallets, payroll or bulk payouts, and account verification. These guides help you choose among five transfer patterns. Each guide explains when to use a pattern, how it works, and which reference pages to read. In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). For API payloads, see [Receive transfers](/guides/business-accounts/inbound-transfers) and [Send transfers](/guides/business-accounts/outbound-transfers). Choose the pattern that matches your goal: | Goal | Pattern | Best for | | - | - | - | | Receive transfers and automatically identify who paid | [Payins on dedicated Account Numbers](/guides/business-accounts/use-cases/collect-payments-with-dedicated-account-numbers) | Lending, insurance, software as a service, marketplaces | | Send money from your Fintoc balance | [Payouts to users or suppliers](/guides/business-accounts/use-cases/send-payouts-to-users-or-suppliers) | Loan disbursements, refunds, vendor payments | | Give every end user their own balance | [Wallet for end users](/guides/business-accounts/use-cases/run-a-wallet-for-end-users) | Neobanks, gig platforms, business-to-business marketplaces | | Pay 10 to 5,000 people at once | [Payroll or bulk payouts](/guides/business-accounts/use-cases/run-payroll-or-bulk-payouts) | Monthly payroll, supplier runs | | Check Account Number ownership before sending a payout | [Verify an Account Number before sending a payout](/guides/business-accounts/use-cases/verify-a-clabe-before-paying-out) | User-entered destinations, peer-to-peer payments, onboarding | ## Availability in Chile Dedicated Account Numbers, the `metadata` you attach to them, and disabling an Account Number work in Chile and Mexico. The following features are available only in Mexico: `options.min_amount`, `options.max_amount`, deleting an Account Number, CLABE verification, and inbound transfer returns. Batch transfers are available in Mexico and Chile from the Dashboard. Each use case page identifies the steps that apply in each country. # Wallet for end users Source: https://docs.fintoc.com/guides/business-accounts/use-cases/run-a-wallet-for-end-users Three patterns to build a per-user wallet with Fintoc: virtual Account Numbers, one Account per user under your Entity, or one Entity per user. ## What you'll build Build a system where each of your end users has a balance, Account Numbers to receive money, and a movement history. ## When to use it Reach for this pattern when your product holds a balance per end user: * Neobanks and fintech apps. * B2B platforms holding client funds. * Marketplaces or gig platforms where sellers accumulate earnings before cashing out. ## Three patterns: pick one You can model a user wallet on Fintoc in three ways. The patterns differ in what Fintoc tracks and whether each user needs Know Your Customer (KYC). Start with the pattern that requires the fewest per-user resources and still fits your requirements. ### Pattern A: one Account Number per user (virtual Account Numbers) * Structure: **one** Fintoc `Account` (yours) with **many** Account Numbers, one per user. * Per-user balance: you track it in your own database. Fintoc holds the aggregate balance. * KYC: none per user. You only onboard your root `Entity`. ```mermaid theme={null} flowchart LR S1[Sender for user 1] -->|Incoming transfer| C1[Account Number 1] S2[Sender for user 2] -->|Incoming transfer| C2[Account Number 2] C1 --> A[Your Account
single total balance] C2 --> A A -.webhook.-> DB[(Your DB
balance_user1 += amount)] ``` Set up: 1. Use your root `Account`. 2. Create one Account Number per user with `metadata.user_id`. 3. On `transfer.inbound.succeeded`, credit the user's balance in your database. 4. For withdrawals, create an outbound `Transfer` from your root `Account` and debit the user's balance in your database. Use this pattern when you track each user's wallet balance in your database. This pattern works in Chile and Mexico. ### Pattern B: one Account per user under your Entity (sub-accounts) * Structure: **many** `Account` objects, all under your `Entity`. Each `Account` has its own balance and root Account Number. * Per-user balance: Fintoc tracks each user's balance at the `Account` level. You can view the balance in the dashboard and statements. * KYC: none per user. ```mermaid theme={null} flowchart LR S1[Sender for user 1] -->|Incoming transfer| C1[Account Number 1] S2[Sender for user 2] -->|Incoming transfer| C2[Account Number 2] C1 --> A1[Account: user 1
own balance] C2 --> A2[Account: user 2
own balance] A1 -.webhook.-> You[(Your backend)] A2 -.webhook.-> You ``` Set up: 1. Create an `Account` by sending `POST /v2/accounts` with your `Entity`'s ID. The new `Account` includes a root Account Number. 2. On `transfer.inbound.succeeded`, use `data.account_id` to identify the user. 3. Use `data.account_id` as the source of funds for withdrawals. Use this pattern when you want Fintoc to track wallet balances per user. This pattern works in Mexico and Chile. ### Pattern C: one Account per user under their own Entity * Structure: **many** `Entity` objects (one per client). Each `Entity` has one or more `Account` objects and root Account Numbers. * Per-user balance: Fintoc tracks each user's balance at the `Account` level. * KYC: required per `Entity`. You run KYC through the API without using the dashboard. ```mermaid theme={null} flowchart LR P[Your platform] -->|Create + onboard by API| E1[Client A Entity] P -->|Create + onboard by API| E2[Client B Entity] E1 -->|on entity.onboarding.approved| A1[One or more Accounts
under Client A] E2 -->|on entity.onboarding.approved| A2[One or more Accounts
under Client B] A1 -->|"Mexican payment receipt: Client A name"| O1[Client A bank] A2 -->|"Mexican payment receipt: Client B name"| O2[Client B bank] ``` Set up: 1. Create the client's `Entity` and run its KYC review through the API. Follow [Onboard an Entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api) to create the `Entity`, upload company, legal representative, and shareholder documents, and submit the onboarding. 2. Wait for the `entity.onboarding.approved` webhook or poll the onboarding status to confirm approval. 3. On approval, Fintoc creates the `Entity`'s main `Account` and root Account Number. When the client needs separate balances, as in Pattern B, create more `Account` objects by sending `POST /v2/accounts` with the `Entity`'s `entity_id`. Each `Account` has its own balance and root Account Number. Outbound transfers show the client's legal name on the Comprobante Electrónico de Pago, the Mexican payment receipt. Use this pattern when receipts must show the client's legal name. For example, a food delivery platform can pay each restaurant under the restaurant's Chilean tax ID (RUT) or Mexican tax ID (RFC). `Entity` objects for your clients are available in Chile and Mexico. ## Choosing between them This table compares the three wallet patterns: | Capability | Pattern A | Pattern B | Pattern C | | - | - | - | - | | Per-user balance ledgered by Fintoc | ❌ | ✅ | ✅ | | Unique Account Number per user | ✅ | ✅ | ✅ | | KYC per user | ❌ | ❌ | ✅ | | Receipts show user's name | ❌ | ❌ | ✅ | # Payroll or bulk payouts Source: https://docs.fintoc.com/guides/business-accounts/use-cases/run-payroll-or-bulk-payouts Create Batch Transfers from the Dashboard or the API. Review and authorize batches in the Dashboard to execute up to 5,000 payouts in Mexico or Chile per cycle. > [!NOTE] > > **Available in Mexico and Chile** > > Create batches from the Fintoc Dashboard or with the API. You always authorize batches from the Dashboard. If you pay the same recipients every cycle, use Batch Transfers. Upload one file in the Dashboard or send one API request. Then review and authorize one payout run instead of creating a transfer for each employee, supplier, or seller. ## Why batch Batch Transfers includes these safeguards: * Fintoc validates up to 5,000 transfers, from one CSV or one API request, before moving funds. * You review the total before approving the run. * You authorize the run through multi-factor authentication (MFA). * Each transfer triggers the same `transfer.outbound.*` webhooks as an API-created transfer, so your reconciliation code stays the same. ```mermaid theme={null} flowchart LR CSV[Dashboard: CSV up to 5,000 rows] --> Validate[Validate] API[API: one request up to 5,000 transfers] --> Validate Validate --> Auth[pending_authorization] Auth -->|MFA| Run[in_progress] Run --> Done[succeeded · partially_succeeded · failed] ``` ## When to use it Reach for Batch Transfers in these cases: * Monthly payroll. * Supplier runs and commission payouts. * Any batch of 10 to 5,000 transfers you should review before releasing. ## Where to go For step-by-step instructions, including the template download, column reference, authorization flow, and statuses, see [Batch Transfers](/guides/business-accounts/outbound-transfers/batch-transfers). To create the batch from your system, see [Create a batch with the API](/guides/business-accounts/outbound-transfers/batch-transfers#create-a-batch-with-the-api). # Send payouts to users or suppliers Source: https://docs.fintoc.com/guides/business-accounts/use-cases/send-payouts-to-users-or-suppliers Send payouts from your Fintoc Account to third-party bank accounts, over SPEI in Mexico or the Centro de Compensación Automatizado in Chile. ## What you'll build Send money from your Fintoc `Account` to a third-party bank account, then track every status change through webhooks. In Mexico, payouts use the Sistema de Pagos Electrónicos Interbancarios (SPEI) rail. In Chile, payouts travel as a Transferencia Electrónica de Fondos and clear over the Centro de Compensación Automatizado (CCA) rail. Settlement timing depends on the rail. ## When to use it Use payouts for these money movement flows: * Loan disbursements and refunds. * Marketplace payouts to sellers. * Wallet withdrawals. * Vendor and supplier payments. ## How it works ```text theme={null} 1. Your backend POSTs /v2/transfers. 2. Fintoc submits to SPEI (MX) or the CCA (CL). 3. Webhook fires: transfer.outbound.succeeded / .failed. 4. Your backend updates the user or order. ``` ```mermaid theme={null} sequenceDiagram autonumber participant You as Your backend participant Fintoc participant Rail as SPEI / CCA You->>Fintoc: POST /v2/transfers Fintoc-->>You: Transfer pending Fintoc->>Rail: Submit Rail-->>Fintoc: Settled / rejected Fintoc->>You: transfer.outbound.succeeded · .failed ``` ## Implementation checklist Complete these steps to send a payout: 1. **Fund the source `Account`.** Send money from your company's external bank account to the `root_account_number` of your Fintoc `Account`. 2. **Create the transfer.** See [Send transfers → Create a transfer](/guides/business-accounts/outbound-transfers) for the full request format, examples for Mexico and Chile, and `counterparty` fields. 3. **Handle the webhooks.** See [Send transfers → Monitor status](/guides/business-accounts/outbound-transfers) for the event catalog and status semantics. 4. **Verify the destination first (optional).** If your customer entered the standardized Mexican bank account number (CLABE), see [Verify a CLABE before payout](/guides/business-accounts/use-cases/verify-a-clabe-before-paying-out). ## A common pitfall Webhooks can arrive out of order. Always branch on `data.status` instead of the event arrival order. See [Send transfers → Monitor status](/guides/business-accounts/outbound-transfers) for status semantics. # Verify a CLABE before sending a payout Source: https://docs.fintoc.com/guides/business-accounts/use-cases/verify-a-clabe-before-paying-out Before a Mexican payout, send a 0.01 MXN micro-deposit to confirm the standardized bank account number (CLABE) and retrieve the holder's Mexican tax ID (RFC). > [!NOTE] > > Mexico only. ## What you'll build Before you send a payout, Fintoc sends a 0.01 MXN micro-deposit to the target standardized Mexican bank account number (CLABE). The receipt returns the holder's name and Mexican tax ID (RFC). You can compare these values with the information your user entered. This check helps you catch typos and evaluate the destination holder against your compliance rules. You can also verify a debit card or mobile phone number before sending a payout to that destination. See [Verify Mexican accounts](/guides/business-accounts/outbound-transfers/verify-clabes). ## When to use it Use this verification in these flows: * Withdrawals to a user-entered CLABE. * Peer-to-peer transfers to a user-entered CLABE. * Vendor onboarding and marketplace seller setup. * Any payout where a misdirected transfer is hard to reverse, such as a vendor settlement or a one-time withdrawal. ## How it works The verification runs in five steps and uses a JSON Web Signature (JWS): ```mermaid theme={null} sequenceDiagram autonumber participant You as Your backend participant Fintoc participant Dest as Destination bank You->>Fintoc: POST /v2/account_verifications (JWS) Fintoc->>Dest: 0.01 MXN micro-deposit Dest-->>Fintoc: Receipt with holder info Fintoc->>You: account_verification.succeeded (holder_id, holder_name) You->>You: Compare against what your user typed ``` ## Implementation checklist 1. **Create the verification.** See [Verify Mexican accounts](/guides/business-accounts/outbound-transfers/verify-clabes) for the API details and request body. 2. **Compare holder fields.** Use fuzzy matching on `holder_name` to account for name variants. Use `holder_id` (RFC) as a stricter signal. 3. **Cache the result.** Holder information is stable for each CLABE. You can verify the CLABE during onboarding and reuse the result for subsequent payouts to the same account. ## Test the integration In `test` mode, verify a published test CLABE and confirm that the webhook includes the holder fields: * Use your test secret key (`sk_test_...`) and the test CLABE `000000000000000000`. * Expect an `account_verification` object in `pending` status on the initial response, with `holder_name` and `holder_id` still `null`. * Expect an `account_verification.succeeded` webhook with populated `holder_name` and `holder_id` fields in `counterparty`. See [Verify Mexican accounts](/guides/business-accounts/outbound-transfers/verify-clabes) for the full payload. See [Test your integration](/guides/business-accounts/setup/test-your-integration) for the available test CLABEs. # API keys Source: https://docs.fintoc.com/guides/home/api-keys Understand Fintoc public and secret API keys for `test` and `live` modes, rotate and revoke `live` secret keys, and configure IP restrictions. Fintoc uses API keys to authenticate your API requests. Fintoc returns an error if a request has no key or an incorrect key. This page explains key types and environments, key management and rotation, and IP address restrictions. Every Fintoc account has two key pairs: one for [`test` mode](/guides/resources/test-mode) and one for `live` mode. Each resource belongs to one environment. A key cannot access resources in the other environment. Each pair contains two types of API key: * Use the **public key** to identify your account in Fintoc and integrate the [Widget](/guides/resources/widget). The public key is not secret. * Use the **secret key** to query the Fintoc API. Keep your secret key private and use it only from your application's backend. When you create an account, Fintoc provides four keys: a public key and a secret key for [`test` mode](/guides/resources/test-mode), and a public key and a secret key for `live` mode. ## Get your API keys > [!WARNING] > > **You can access your secret API key for `live` mode only once** > > You can view and copy a secret API key only when you activate or rotate the key. Store secret keys securely in your backend. You can activate and manage your API keys from the [Dashboard](https://dashboard.fintoc.com). ## Rotate and revoke your `live` secret keys We recommend rotating your `live` secret keys at least once a year. You can manage them from the [API keys page](https://dashboard.fintoc.com/api-keys) in the Dashboard. To rotate a `live` secret key without downtime: 1. Click **Create secret key** to create a new `live` secret key. 2. Update your backend to use the new key. 3. Open the three-dot menu next to the old key and click **Revoke**. Revoking a key takes effect immediately and cannot be undone. Any application that still uses the revoked key stops working. > [!NOTE] > > **Only `live` secret keys can be rotated or revoked** > > You cannot rotate or revoke `test` mode keys or public keys. The Dashboard shows the three-dot menu only for `live` secret keys. ## If your secret key is exposed If your `live` secret key is exposed, for example in a public repository, client-side code, or logs, replace the key right away: 1. Go to the [API keys page](https://dashboard.fintoc.com/api-keys) in `live` mode. 2. Click **Create secret key** to create a new `live` secret key. 3. Update your backend to use the new key. 4. Open the three-dot menu next to the exposed key and click **Revoke**. If you cannot update your backend right away, revoke the exposed key first. Requests that use the revoked key fail until you deploy the new key. If your `test` mode secret key is exposed, it does not affect your `live` operations. A `test` key can only access `test` mode resources, which do not move real money. You cannot rotate or revoke a `test` key, so remove it from the place where it was exposed. ## Configure IP restrictions You can restrict API requests to specific IP addresses. Fintoc rejects requests from all other addresses. To configure these restrictions: 1. Go to [dashboard.fintoc.com](https://dashboard.fintoc.com). 2. Select **API Keys** in the sidebar. 3. If your organization has products with IP restrictions enabled, turn on **IP Restrictions**. 4. Click **IP Restrictions** and enter the IP addresses or Classless Inter-Domain Routing (CIDR) blocks from which you make requests to the Fintoc API. Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. ### CIDR blocks CIDR blocks define a range of IP addresses. A CIDR block lets you specify a group of addresses instead of listing each address. For example: `192.168.1.0/24` represents all IP addresses from `192.168.1.0` to `192.168.1.255`. If you do not know your CIDR block, ask your network administrator or technical team to identify the correct range. > [!WARNING] > > **Add at least one IP address before you turn on IP restrictions** > > If you turn on IP restrictions without adding an IP address, Fintoc rejects every request. # API rate limits Source: https://docs.fintoc.com/guides/home/api-rate-limits How Fintoc applies rate limits to API requests and Business Accounts transfers, and how to handle `429 Too Many Requests` responses. Fintoc applies separate rate limits to API requests and Business Accounts transfers. This page explains these limits and how to handle `429 Too Many Requests` responses. The following limits apply: 1. **Organization rate limit:** Up to 100 requests per second for each organization across the Fintoc API. 2. **Business Accounts transfer rate limit:** Up to 10 `Transfer` requests per second for each organization. See [Business Accounts rate limits](/guides/business-accounts/overview/transfer-data-model#rate-limits). Treat these limits as maximums. Keep your request volume below them, and handle rate-limited responses. Fintoc lowers limits to prevent abuse and raises limits for integrations that require request volumes above the defaults. Contact support at least one month before you need a higher limit. ## Handle rate limiting Watch for `429 Too Many Requests` responses. Retry each rate-limited request with exponential backoff. Start with a 1-second delay, then double the delay after each attempt: 1, 2, 4, 8, and 16 seconds. Retry up to 5 times. Add a random delay of up to 1 second to each retry to prevent clients from synchronizing their requests. # API reference 📖 Source: https://docs.fintoc.com/guides/home/api-reference # Changes to the API Source: https://docs.fintoc.com/guides/home/changes Learn which API changes Fintoc treats as backwards compatible and how Fintoc releases a new dated API version for changes that are not backwards compatible. This page explains which API changes Fintoc treats as backwards compatible and how Fintoc versions changes that are not backwards compatible. For a change that is not backwards compatible, Fintoc releases a new dated API version so your existing integration keeps working. ## Backwards-compatible changes Fintoc considers the following changes backwards compatible: * Add objects to the API. * Add optional parameters to existing API endpoints. * Add new fields to existing objects. * Change the order of the keys in an object. * Change the length or format of IDs and tokens, including adding or removing prefixes such as the `acc_` prefix on the [`Account` object](/api/movements-api/accounts/accounts-object) ID. * Change header field names to uppercase or lowercase. Per [RFC 7230](https://www.rfc-editor.org/rfc/rfc7230#section-3.2), header field names are case-insensitive. > [!NOTE] > > **Do not assume the format of IDs or tokens** > > Do not parse an ID or token to extract information from it. Fintoc treats format changes as backwards compatible, so the format can change without a new API version. For example, objects created before `2021-05-05` do not have a prefix on their IDs. # Currencies Source: https://docs.fintoc.com/guides/home/currencies ## Currency representation as an integer The Fintoc API represents each monetary amount as an integer in the currency's smallest unit. The Chilean peso's smallest unit is the peso, so Fintoc represents `1000 CLP` as `1000`. The US dollar's smallest unit is the cent, so Fintoc represents `10.50 USD` as `1050`. The following examples show `CLP` and `USD` accounts. The `CLP` account has an available balance of `150980 CLP`. The `USD` account has an available balance of `159.50 USD`. ```json A CLP account example theme={null} { "id": "acc_nMNejK7BT8oGbvO4", "name": "Cuenta Corriente CLP", "official_name": "Cuenta Corriente Moneda Peso Chileno", "number": "0000000001", "holder_id": "111111111", "holder_name": "Test Company 1", "type": "checking_account", "currency": "CLP", "balance": { "available": 150980, "current": 150980, "limit": 150980 } } ``` ```json A USD account example theme={null} { "id": "acc_8s7Hk2Lp9QwErTy3", "name": "Cuenta Corriente USD", "official_name": "Cuenta Corriente Moneda Dolar", "number": "0000000002", "holder_id": "111111111", "holder_name": "Test Company 1", "type": "checking_account", "currency": "USD", "balance": { "available": 15950, "current": 15950, "limit": 15950 } } ``` Fintoc supports accounts denominated in `CLP`, `MXN`, `USD`, and `EUR`. The following table compares an amount in each currency with the integer Fintoc returns: | Currency | Amount | Fintoc representation of the amount | | :- | :- | :- | | CLP | 1000 CLP | 1000 | | MXN | 10.29 MXN | 1029 | | USD | 10.50 USD | 1050 | | EUR | 10.00 EUR | 1000 | # Disputes Source: https://docs.fintoc.com/guides/home/dashboard/disputes Find a dispute in the Fintoc Dashboard, check its documentation deadline, and submit evidence for review. A dispute (chargeback) happens when your customer contests a card payment with their issuer. Each dispute has an ID prefixed with `cb_`. While a dispute is open, the payment amount stays on hold until the issuer resolves the dispute. You can answer a dispute from the Dashboard by uploading evidence and submitting it for review before the deadline. To answer disputes through the API instead, see the [Disputes API reference](/api/payments-api/disputes). ## Before you begin * Your organization must have card payments enabled. The **Disputes** tab appears only for organizations with card payments. * To view disputes, your user needs **Read** access to **Payments**. * To upload evidence and submit it for review, your user needs **Manage** access to **Disputes**. If your user doesn't have this access, ask an administrator of your organization to grant access or to upload the evidence for you. To learn more, see [Permission roles](/guides/home/dashboard/permission-roles). ## Find a dispute 1. In the Dashboard, go to **Payment history**. 2. Open the **Disputes** tab. The badge next to the tab shows how many disputes are waiting for documentation. 3. To find a specific dispute, filter by **Dispute ID** with the exact `cb_` ID or by **Status**. 4. Click the dispute to open its detail page. The detail page shows the payment details, the **Activity** timeline with the documentation deadline, and the **Supporting documents** section. ## Dispute statuses The Dashboard shows each dispute status with its matching API value: | Dashboard status | API status | Description | | :- | :- | :- | | Documentation required | `waiting_documentation` | Your customer opened the dispute. Upload evidence and submit it before the deadline. | | In review | `in_review` | You submitted your evidence and the dispute is under review. You can't add or remove documents. | | Dispute won | `won` | The issuer resolved the dispute in your favor. You receive the funds back. | | Dispute lost | `lost` | The issuer resolved the dispute in your customer's favor. You don't receive the funds back. | | Expired | `expired` | The deadline passed without submitted evidence. You lose the dispute and don't receive the funds. | | Canceled | `canceled` | Fintoc voided the dispute. | ## Documentation deadline Each dispute has a documentation deadline, shown next to **Deadline:** in the dispute detail page. The API returns the deadline as `documentation_upload_deadline`. You can upload and submit documents only while the dispute is in **Documentation required** and before the deadline. If the deadline passes without submitted evidence, the dispute moves to **Expired**. ## Upload evidence and submit for review Attach evidence related to the sale or service you provided, such as receipts, communications with your customer, or proof of delivery. 1. Open the dispute detail page. 2. In **Supporting documents**, upload one or more files. Each file must be a PDF, JPEG, or PNG and smaller than 10 MB. 3. Click **Submit documentation**. 4. In the confirmation dialog, click **Submit documentation** again. After you submit the evidence, the dispute moves to **In review**. You can no longer add or remove documents for that dispute. ## Get notified about disputes To track disputes from your systems, subscribe to the `dispute.*` webhook events. To learn more, see [Types of events](/api/main-resources/events-reference/types-of-events). # Get your secret and public API keys Source: https://docs.fintoc.com/guides/home/dashboard/guides-api-keys Locate and copy your secret key and public key from the Fintoc dashboard for `test` and `live` modes. > [!WARNING] > > Never send your secret key to the frontend. Make requests that use your secret key only from your backend so the key never reaches the client. To use the Fintoc API, you need your secret key. To instantiate the Fintoc widget, you need your public key. To manage your API keys, open [the dashboard](https://dashboard.fintoc.com/). In the dashboard, open the API keys page: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/bb8cb122b9033147bb57750b4e99a0c26eb91ea6252793e376ea190186d8f42d-Captura_de_pantalla_2025-04-15_a_las_12.24.09.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=f1c84d257536268108c715aeeaf9ef63) By default, you see `live` mode. To switch, use the mode toggle to select `test` mode: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/f597f13ca0a9f47ea3e76ae1bbc7002f8e141c11e8e76aeb1ec576f4e9d63d2b-Captura_de_pantalla_2025-04-15_a_las_12.24.47.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=0e2653333957e302d6d6ed72ca6cf350) If you are using the [test environment](/guides/resources/test-mode), use the API keys shown in `test` mode. Otherwise, use the API keys shown in `live` mode. When an API key is available, select the *eye* button beside it to reveal the key: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/497058b89e7155b9170897e98d618172c8cb77d6adb7f55fd04cbbefb270bfb1-Captura_de_pantalla_2025-04-15_a_las_12.26.18.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=a0dd211d223ddade30e8e487781f6b86) The *eye* button beside an API key reveals it Secret keys start with `sk_`. Public keys start with `pk_`. > [!WARNING] > > **The dashboard shows your `live` secret key only during activation or rotation** > > You can copy and view your secret key only when you activate or rotate it, so store it securely in your backend. You can access both your public key and secret key for `test` mode at any time with the *eye* or *copy* buttons. For `live` mode, you can always access the public key. The dashboard displays the secret key only when you activate or rotate it, so store it securely in your backend when the key appears. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/090b18e36138fe291e0015e108f6cb3f778ebb1b8940412da0fcce8fe91f599d-Captura_de_pantalla_2025-04-15_a_las_12.30.04.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=fce0410dc1ae75ecdc44d4f3709b3375) ## Rotate or revoke a `live` secret key We recommend that you rotate your secret key for `live` mode at least once per year. To rotate the key, click **Create secret key** to create a new key. Update your backend to use the new key, then revoke the old key. To revoke a key, open the three-dot menu on the right side of the table and click **Revoke**. Revoking a key takes effect immediately and cannot be undone. You can only rotate or revoke `live` secret keys. The three-dot menu does not appear for `test` mode keys or public keys. ## If your secret key is exposed If your `live` secret key is exposed, create a new secret key, update your backend to use the new key, and revoke the exposed key right away. For the full steps, see [If your secret key is exposed](/guides/home/api-keys#if-your-secret-key-is-exposed). If your `test` mode secret key is exposed, it does not affect your `live` operations. You cannot rotate or revoke `test` keys. # Manage your team Source: https://docs.fintoc.com/guides/home/dashboard/manage-team Invite users to your organization's dashboard, edit or remove them, and recover accounts that are blocked after failed login attempts. You manage your organization's users from the **Team** section of the dashboard settings. This page explains how to find that section, invite and remove users, and unblock users who are locked out. To invite, edit, or remove users, you need the **Manage** access level on the Team resource. Among the predefined roles, only Admin includes the **Manage** access level. To learn more about roles and access levels, see [Permission roles](/guides/home/dashboard/permission-roles). ## Open the Team section 1. In the dashboard, click your organization's name at the top of the left sidebar. 2. Select **Settings**. 3. Open the **Team** section. The Team section lists every user in your organization, along with their role, two-factor authentication (2FA) status, and last login. To learn how users set up 2FA when they first sign in, see [Set up two-factor authentication](/guides/home/dashboard/set-up-2fa). ## Invite a user Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. 1. In the **Team** section, click **Invite**. 2. Enter the user's email and click **Continue**. 3. Choose a role for the user. You can also select **Custom role** or **Copy permissions from an existing user**. Only Admins can assign the Admin role. 4. If you chose Admin, click **Send invitation**. Otherwise, click **Continue to permissions**, review each access level, and click **Confirm**. Fintoc sends the user an email with a link to create an account. If the user does not receive the email, open the options menu on the user's row and select **Resend invitation**. ## Edit or remove a user To edit a user's permissions: 1. In the **Team** section, click the user's row. 2. Change the user's role or access levels. 3. Click **Save changes**. To remove a user, open the options menu on the user's row and select **Remove**. You cannot change the role of, or remove, a user who has the Admin role and has already accepted their invitation. An Admin can still grant another Admin permissions per account, such as transfer approval. See [Treasury](/guides/home/dashboard/permission-roles#treasury). ### Make a user an Admin Only Admins can make another user an Admin. Open the user's row, select **Admin** as the role, click **Save changes**, and then click **Promote to Admin**. You cannot undo this promotion from the dashboard. ## Unblock a locked account Fintoc blocks a dashboard account in two situations: too many failed password attempts, or too many failed 2FA code attempts. ### Failed password attempts After too many failed login attempts, the dashboard shows **Account blocked**. Fintoc sends the user an email with instructions to unlock the account. If the user does not receive the email, contact support through the chat. ### Failed 2FA code attempts The first time a user exceeds the limit of 2FA code attempts, Fintoc blocks the account temporarily. The user can try again after 10 minutes. A 2FA block applies only to the organization where the user exceeded the limit. If the user keeps failing, Fintoc keeps the account blocked until an Admin resets the user's 2FA from the **Team** section. Fintoc then emails the user a link to set up 2FA again. See [Unlock a teammate's 2FA](/guides/home/dashboard/unlock-teammate-mfa). If the blocked user is the only Admin in your organization, click **Contact Support** on the blocked screen, or contact support through the chat. # Permission roles Source: https://docs.fintoc.com/guides/home/dashboard/permission-roles How Fintoc's dashboard permission system works: permissions, access levels, and predefined roles, plus the access levels for each resource by category. Fintoc's dashboard holds sensitive information and lets your organization move money. To control who can do what, Fintoc provides a granular permission system built on three concepts: permissions, access levels, and roles. This page explains each concept and lists the available access levels for every resource. ## Permissions A permission controls a single action on a single resource. A resource is an area or feature of the dashboard, such as API keys, payments, or transfers. Fintoc groups permissions into five categories: Payment initiation, Treasury, Reconciliation, Developers, and Administration. ## Access levels You can grant one of four access levels for each resource. Manage includes everything in Read. * **None:** No access to the resource. * **Read:** See the resource's information without making changes. * **Manage:** Create, edit, and delete, in addition to everything in Read. * **Authorize:** Approve or reject transfers. Each authorizer has an assigned approval percentage. ## Roles A role is a predefined bundle of permissions that matches a common job function. Assign a role to a user as a starting point. You can then adjust the user's permissions when the role does not fit. Fintoc provides five predefined roles: * **Admin:** Access to all products and features, including team management, billing, organization settings, and Internet Protocol (IP) restrictions. The Admin role does not include transfer approval. Another Admin can grant transfer approval separately through account rules. See [Treasury](#treasury). * **Developer:** Full access to API keys, webhooks, and JSON Web Signature (JWS) public keys, plus read-only access to payments and reconciliation. * **Operations:** Manage links and refunds, plus read-only access to payments, payouts, and subscriptions. * **Finance and Accounting:** Read-only access to payments, payouts, subscriptions, and reconciliation. * **Support:** Read-only access to payments and subscriptions, plus the ability to refund payments. Only Admins can grant the Admin role, either when inviting a user or by editing an existing user's role. To learn how, see [Manage your team](/guides/home/dashboard/manage-team#make-a-user-an-admin). Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. ## Permissions by category The tables below list the resources in each category and the access levels you can grant for each one. ### Payment initiation These resources cover collecting and paying out money: | Resource | Available access levels | | :- | :- | | Payments | Read | | Refunds | Manage | | Payouts | Read | | Subscriptions | Read | | Charges | Read | | Customers | Read | | Disputes | Manage | Viewing disputes requires Read access to Payments. Manage access to Disputes lets a user upload evidence and submit a dispute for review. To learn more, see [Disputes](/guides/home/dashboard/disputes). ### Treasury No predefined role includes Treasury permissions; assign them to individual users. Manage lets you create a transfer request, but does not let you authorize it. Authorize lets you approve transfers with your assigned approval percentage. Fintoc creates the transfer once approvals total 100%. The Admin role and one-time password authentication do not grant transfer authorization permission. Check your transfer access level and approval percentage separately. For the creation flow and missing authorization options, see [Authorize manual transfers in the dashboard](/guides/business-accounts/overview/transfer-data-model#authorize-manual-transfers-in-the-dashboard). | Resource | Available access levels | | :- | :- | | Transfers | Read, Manage, Authorize | | Accounts | Read, Manage | | Standardized Mexican bank account numbers (CLABEs) | Read, Manage | | Entities | Read, Manage | Transfer approval (the Authorize level and its approval percentage) and account creation are assigned per user through account rules, including for Admins. An Admin who can change user roles can grant these permissions to another Admin who has accepted their invitation. Open the other Admin's detail page in the dashboard's **Team** section, then add account rules or raise existing levels. Admin-to-Admin edits can only grant permissions: * You cannot lower an access level or an approval percentage. * You cannot remove an existing account rule. * You cannot turn off account creation once it is on. * You cannot edit your own permissions. * The Admin role itself stays locked. Fintoc rejects any change that removes a permission and saves no changes. ### Reconciliation These resources cover reconciliation: | Resource | Available access levels | | :- | :- | | Links | Read, Manage | | Movements | Read | ### Developers These resources cover your integration and security tooling: | Resource | Available access levels | | :- | :- | | API keys | Read, Manage | | Webhooks | Read, Manage | | JWS public keys | Read, Manage | | IP restrictions | Read, Manage | ### Administration These resources cover your organization and its team: | Resource | Available access levels | | :- | :- | | Team | Read, Manage | | Organization settings | Read, Manage | | Billing | Read, Manage | # Set up two-factor authentication Source: https://docs.fintoc.com/guides/home/dashboard/set-up-2fa Set up two-factor authentication (2FA) for the Fintoc dashboard with an authenticator app such as Google Authenticator or Authy, and sign in with a 6-digit code. The Fintoc dashboard requires two-factor authentication (2FA). After you enter your email and password, you also enter a 6-digit code from an authenticator app on your phone. This page explains how to set up 2FA the first time you sign in and how to sign in afterward. ## Choose an authenticator app You can use any authenticator app that generates 6-digit time-based one-time passwords (TOTP). For example: * Google Authenticator * Authy Install the app on your phone before you sign in to the dashboard for the first time. ## Set up 2FA the first time you sign in The first time you sign in, the dashboard shows **Configure your authenticator app** with a QR code. 1. Open your authenticator app on your phone. 2. In the app, add a new account and scan the QR code shown in the dashboard. 3. Enter the 6-digit code that the app shows for Fintoc. 4. Click **Confirm**. Fintoc activates 2FA on your account, and the dashboard opens. In the **Team** section, your 2FA status changes to **OTP active**. ## Sign in with 2FA Each time you sign in after setup, the dashboard shows **Enter the code from your authenticator app**. 1. Open your authenticator app and find the Fintoc code. 2. Enter the 6-digit code in the dashboard. 3. Click **Confirm**. Each code is valid until your app shows the next code. If the dashboard rejects a code, wait for the app to show the next code and enter it. After three wrong codes in a row, Fintoc blocks your 2FA for 10 minutes. See [Unblock a locked account](/guides/home/dashboard/manage-team#failed-2fa-code-attempts). ### Remember this device Before you click **Confirm**, you can select **Remember this device for 30 days**. Fintoc then doesn't ask for a 2FA code when you sign in from the same device for the next 30 days. The option is off by default. To make Fintoc ask for a code again on every device, open the [Team section](/guides/home/dashboard/manage-team#open-the-team-section), open the options menu (**...**) on your own row, and select **Forget trusted devices**. ## Change your 2FA device If you move your authenticator app to a new phone and can still sign in, change your 2FA device from the **Team** section: 1. Open the options menu (**...**) on your own row and select **Change 2FA device**. 2. Click **Change**. Your old device stops generating valid codes for Fintoc. 3. Scan the new QR code with the authenticator app on your new phone. 4. Enter the 6-digit code that the app shows and click **Confirm**. If you lost the phone with your authenticator app, you can't change the device yourself. Ask an Admin in your organization to reset your 2FA. Fintoc then emails you a link to set up 2FA again. See [Unlock a teammate's 2FA](/guides/home/dashboard/unlock-teammate-mfa#reset-the-2fa-of-a-teammate-who-lost-their-device). # Unlock a teammate's 2FA Source: https://docs.fintoc.com/guides/home/dashboard/unlock-teammate-mfa Reset a teammate's blocked 2FA from the Team section so Fintoc emails the teammate a link to set up 2FA again, including after device loss. When a teammate enters too many wrong two-factor authentication (2FA) codes, Fintoc blocks their 2FA and they can't sign in to the dashboard. From the **Team** section, you approve a reset with your own 2FA code, and Fintoc emails your teammate a link to set up 2FA again. ## Before you begin To reset a teammate's 2FA, you need the following: * **The Manage access level on the Team resource.** Among the predefined roles, only Admin includes this access level. See [Permission roles](/guides/home/dashboard/permission-roles). * **Active 2FA on your own account.** You confirm every reset with a code from your authenticator app. You can't reset your own 2FA. If your 2FA is blocked, ask another Admin in your organization to reset it. If no other Admin can, contact support through the chat. ## Check your teammate's 2FA status The **2 Factor Authentication** column in the **Team** section shows the 2FA status of each user. To open the Team section, see [Manage your team](/guides/home/dashboard/manage-team#open-the-team-section). Fintoc locks 2FA in two stages: 1. **OTP temporarily blocked:** After three wrong codes in a row, Fintoc blocks 2FA for 10 minutes. You can't reset 2FA in this status. Your teammate waits 10 minutes and tries again. 2. **OTP blocked:** If the first code after those 10 minutes is also wrong, Fintoc blocks 2FA until an Admin resets the teammate's 2FA. The dashboard grays out the teammate's row. A 2FA lock applies only to the organization where your teammate entered the wrong codes. ## Allow the 2FA reset Approve the reset from the teammate's row in the **Team** section: 1. Find the teammate whose status is **OTP blocked**. 2. Open the options menu (**...**) at the end of the row and select **Allow MFA reset**. ![Team section with the options menu of a blocked user open and the Allow MFA reset option highlighted](https://mintcdn.com/fintoc-49b8bee8/e6ENZyQg5A9dQJxK/images/unlock-teammate-mfa-menu-en.png?fit=max\&auto=format\&n=e6ENZyQg5A9dQJxK\&q=85\&s=e54b8d77e3f3fb8013a846ec6d09867e) 3. Enter the 6-digit code from your own authenticator app. ![Dialog titled Allow Test User 1 to restore their access, with a 6-digit code field and an Authorize button](https://mintcdn.com/fintoc-49b8bee8/e6ENZyQg5A9dQJxK/images/unlock-teammate-mfa-modal-en.png?fit=max\&auto=format\&n=e6ENZyQg5A9dQJxK\&q=85\&s=716f1e3bcbd69d29a0ccfb9f59a53804) 4. Click **Authorize**. The dashboard confirms with **MFA reset link sent** and shows the email address that received the link. You can also start the reset from the teammate's detail page: click their row, and then click **Allow** on the **Blocked user** banner. > [!WARNING] > > Codes you enter in this dialog count toward your own 2FA attempt limit. If you enter three wrong codes in a row, Fintoc temporarily blocks your 2FA too. ## Set up 2FA again Your teammate receives an email with the subject **Reset your two-factor authentication**. To restore access, your teammate follows these steps: 1. Your teammate opens the link in the email. If the dashboard asks them to sign in, they sign in with the email address that received the link. 2. Your teammate scans the QR code with an authenticator app, such as Google Authenticator. 3. Your teammate enters the 6-digit code that the app shows and clicks **Confirm**. The 2FA status changes to **OTP active**, and your teammate can use the dashboard again. The link expires 24 hours after you send it and works only once. If the link expires, the dashboard shows **Invalid reset link**. Allow the reset again to send a new link. ## Reset the 2FA of a teammate who lost their device If a teammate loses or replaces the phone that has their authenticator app, you can reset the teammate's 2FA without waiting for a block. Open the options menu on the row of a teammate whose status is **OTP active** and select **Start MFA reset**. The rest of the flow matches [Allow the 2FA reset](#allow-the-2fa-reset). When you authorize the reset, Fintoc blocks the teammate's current 2FA immediately. Your teammate can sign in and approve transfers again after [setting up 2FA again](#set-up-2fa-again). # Upgrade your API version Source: https://docs.fintoc.com/guides/home/upgrade-api-version Move your account to the latest API version without breaking your existing integration. Move your account to API version `2026-02-01` without breaking your existing integration. Fintoc pins your account to an API version and applies that version to every request that does not send the `Fintoc-Version` header. The header always takes precedence over the pinned version. For more details, see [API version](/api/fintoc-api/authentication#api-version). The upgrade changes the shape of request bodies, response bodies, and webhook events, but does not change your API keys, webhook endpoints, or webhook signature verification. > [!NOTE] > > Use this guide to upgrade your account's API version. The guide does not cover moving from v1 endpoints to v2 endpoints. Some v1 and v2 endpoints work differently, such as `/v1/payment_intents` and `/v2/payment_intents`. To use a v2 endpoint, see its API reference. ## 1. Find your current API version Go to the [Fintoc Dashboard](https://dashboard.fintoc.com) and open **your organization name** (top left) > **Settings** > **Company profile** > **API Version**. If your version is `2026-02-01`, your account already uses the latest version and you can skip this guide. ## 2. Review the changes Version `2026-02-01` introduces the following changes. They affect your v1 requests, your v2 requests, and your webhook events: | Object | Before `2026-02-01` | Starting in `2026-02-01` | | - | - | - | | `CheckoutSession` | The payment methods field is `payment_methods`. | The payment methods field is `payment_method_types`. | | `CheckoutSession` | Payment method values are `payment_intent`, `installments_payment`, `card`, and `cash`. | Payment method values are `bank_transfer`, `installments`, `card`, and `cash`. | | `CheckoutSession` | `payment_method_options` keys are `payment_intent`, `installments_payment`, `card`, and `cash`. | `payment_method_options` keys are `bank_transfer`, `installments`, `card`, and `cash`. | | `PaymentIntent` | `sender_account` is `null` when Fintoc only knows the sender's bank. | `sender_account` contains the `institution_id` of the sender's bank, with `holder_id`, `number`, and `type` set to `null`. | The renames apply to request bodies, response bodies, and error messages. If your account is pinned to `2023-11-15`, the changes in version `2025-08-13` also apply to you: | Object | Before `2025-08-13` | Starting in `2025-08-13` | | - | - | - | | `Movement` | The object has no `status` field. | The object includes a `status` field. | | `Movement` | `GET /v1/accounts/{id}/movements` returns only confirmed movements, regardless of the `confirmed_only` value you send. | `GET /v1/accounts/{id}/movements` returns only confirmed movements unless you send `confirmed_only=false`. | ## 3. Prepare your webhook handler Webhook events do not carry the `Fintoc-Version` header. Fintoc serializes every event with your account's pinned version, so `checkout_session.*` and `payment_intent.*` events change shape when your account moves to `2026-02-01`. Update your webhook handler to accept both shapes described in [step 2](#2-review-the-changes), and deploy the handler before you request the upgrade. For example, read the payment methods of a checkout session in either shape: ```javascript Webhook handler (Node.js) theme={null} const LEGACY_TO_NEW = { payment_intent: 'bank_transfer', installments_payment: 'installments', }; function paymentMethodTypes(checkoutSession) { if (checkoutSession.payment_method_types) { return checkoutSession.payment_method_types; } return checkoutSession.payment_methods.map((pm) => LEGACY_TO_NEW[pm] ?? pm); } ``` ```python Webhook handler (Python) theme={null} LEGACY_TO_NEW = { "payment_intent": "bank_transfer", "installments_payment": "installments", } def payment_method_types(checkout_session): if "payment_method_types" in checkout_session: return checkout_session["payment_method_types"] return [LEGACY_TO_NEW.get(pm, pm) for pm in checkout_session["payment_methods"]] ``` Apply the same mapping to the keys of `payment_method_options`. For `payment_intent.*` events, accept a `sender_account` that contains the `institution_id` of the sender's bank, with `holder_id`, `number`, and `type` set to `null`. ## 4. Adapt your requests Update your code to the changes in [step 2](#2-review-the-changes) and send `Fintoc-Version: 2026-02-01` on every request, to both v1 and v2 endpoints: ```text Requests theme={null} Fintoc-Version: 2026-02-01 ``` You can adapt your requests one endpoint at a time. Requests without the header keep using your current version until the upgrade. > [!NOTE] > > While your account is pinned to an earlier version, the v2 Checkout Session, Payment Intent, and Setup Intent endpoints return a `404 Not Found` error with code `unrecognized_request` unless you send the header. If you use `fintoc-python`, set the version on the client. The client sends the header with each request, so use one client per version while you adapt your integration: ```python Server (Python) theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_KEY', api_version='2026-02-01') ``` `fintoc-node` does not send the `Fintoc-Version` header. If you use `fintoc-node`, send the requests you adapt with an HTTP client, such as `fetch`, and include your secret key in the `Authorization` header and `Fintoc-Version: 2026-02-01`. Keep the rest of your requests in `fintoc-node` until the upgrade, and update your code to accept both shapes from [step 2](#2-review-the-changes). ## 5. Test your changes Test your changes with your `test` API keys: 1. Send your v1 and v2 requests with `Fintoc-Version: 2026-02-01` and confirm your code handles the new response shapes. 2. Test your webhook handler with sample payloads in both shapes from [step 2](#2-review-the-changes). Your `test` webhook events keep your current version until the upgrade, so you cannot receive events in the new shape before you request it. ## 6. Request the upgrade > [!WARNING] > > After the upgrade, a v1 request that sends `payment_methods` without the `Fintoc-Version` header does not fail. Fintoc ignores `payment_methods` and the checkout session defaults to `bank_transfer`. Adapt every request before you upgrade, or send `Fintoc-Version` with your previous version on requests you have not adapted yet. Ask your Fintoc account representative or Fintoc support to upgrade your account to `2026-02-01`. The upgrade applies to `test` and `live` modes at once. After the upgrade, requests without the `Fintoc-Version` header use `2026-02-01`, and Fintoc sends webhook events in the new shape. ## 7. Clean up your integration Remove any `Fintoc-Version: 2026-02-01` headers from your requests. Your account already uses `2026-02-01`, so those headers no longer change the version. If some requests still send `Fintoc-Version` with your previous version, adapt those requests and then remove the header too. Fintoc keeps the previous shape for `checkout_session.*` events created before the upgrade. This behavior applies to [retries](/guides/resources/webhooks-walkthrough/webhooks-creating-guide#handle-retries-and-failed-deliveries) and to events you [list](/api/main-resources/events-reference/events-list) or [get](/api/main-resources/events-reference/events-get). Remove support for the previous shape from your webhook handler once those retries end. Keep support for the previous shape in code that reads events created before the upgrade. # Welcome 👋 Source: https://docs.fintoc.com/guides/home/welcome Start integrating Fintoc: browse guides for Smart Checkout, recurring payments, transfers, and bank account connections across Chile and Mexico. Browse the guides and examples to integrate Fintoc into your product. ## Explore our products > [card] [Smart Checkout](/guides/payments/accept-a-payment) > > Accept and optimize online payments without writing code. > [card] [Recurring Payments](/guides/payments/accept-recurring-payments) > > Automate subscriptions and billing with automatic retries for failed charges. > [card] [Business Accounts](/guides/business-accounts/overview) > > Initiate, receive, and reconcile money programmatically. > [card] [Connections](/guides/movements/overview-data-aggregation) > > Connect bank accounts to pull balances and movements. ## Start with a use case > [card] [Accept a one-time payment](/guides/payments/accept-a-payment) > > Embed the checkout widget and confirm payments via a webhook. > [card] [Set up a subscription](/guides/payments/accept-recurring-payments) > > Create a plan, save a payment method, and automate monthly billing. > [card] [Send or receive transfers](/guides/business-accounts/use-cases) > > Move money through local rails in Mexico and Chile. > [card] [Recover failed payments](/guides/payments/fintoc-collect-payments/dealing-with-payment-exceptions) > > Build retry flows with custom rules and notification logic. > [card] [Reconcile your revenue](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation) > > Pull transaction reports, match movements, and export to your accounting system. ## Building with AI? Fintoc exposes a Model Context Protocol (MCP) server for AI agents. Use the server with Claude, Cursor, and other agents to call the API directly. You don't need to copy content from the documentation. > [card] [MCP Server](/guides/resources/building-with-ai/model-context-protocol-mcp) > [card] [llms.txt](https://docs.fintoc.com/llms.txt) > [card] [Fintoc CLI](/guides/resources/cli) > [card] [Agent Skills](/guides/resources/building-with-ai/agent-skills) ## Get help 💬 [Talk to support](https://ayuda.fintoc.cl/es) · 📞 [Talk to sales](https://fintoc.com/cl/contacto) · 💡 [Send product feedback](mailto:producto@fintoc.com) # Accept a one-click payment with Apple Pay Source: https://docs.fintoc.com/guides/payments/accept-a-payment/accept-a-one-click-payment-with-apple-pay Use Fintoc Express Checkout to accept one-click Apple Pay payments on the web, with server-side confirmation and support for saved payment methods. Use a single integration to accept payments through one-click payment buttons. The Express Checkout component is a Fintoc SDK feature that lets your customers pay with wallet buttons, without opening the full widget. The currently supported payment method is **Apple Pay**. Customers see the Apple Pay button depending on their device and browser. If Apple Pay is not available on the device, the button is hidden. > [!WARNING] > > **Before you begin: your domain must be enabled for Apple Pay.** Apple Pay won't load until Fintoc registers your domain with Apple, so the button stays hidden on an unregistered domain. See [Enabling Apple Pay](#enabling-apple-pay) to start the process before you integrate. Accepting Apple Pay payments with Express Checkout takes six steps: 1. Set up your server to create a `Checkout Session` 2. Set up the Fintoc SDK on your frontend 3. Create and mount the Express Checkout component 4. Handle the `onPaymentRequest` callback 5. Submit the payment to Fintoc 6. Test the integration *** ## Step 1: Set up your server > **Server-side** Express Checkout calls the `onPaymentRequest` callback after the customer authorizes the Apple Pay sheet. In that callback you must create a **Checkout Session** from your backend and return its `session_token` to the browser. Expose an endpoint on your server that creates a Checkout Session with Fintoc's API: **Node** ```javascript theme={null} // server.js (Node example) const { Fintoc } = require("fintoc"); const fintoc = new Fintoc(process.env.FINTOC_SECRET_KEY); app.post("/api/create-checkout", async (req, res) => { const session = await fintoc.v2.checkoutSessions.create({ amount: 1000, currency: "CLP", payment_method_types: ["card"], // ...any other fields your flow requires }); res.json({ session_token: session.session_token }); }); ``` > [!WARNING] > > Never expose your secret key in the browser. Always keep the Checkout Session creation call on your server. *** ## Step 2: Set up the Fintoc SDK > **Client-side** Express Checkout is automatically available as a feature of the Fintoc SDK. Include the Fintoc script on your checkout page by adding it to the `` of your HTML file. Always load the SDK directly from `js.fintoc.com` to receive security updates. Don't include the script in a bundle or host a copy of it yourself. ```html theme={null} Checkout ``` *** ## Step 3: Create and mount the Express Checkout > **Client-side** The Express Checkout component renders the wallet button inside an iframe that securely sends the payment information to Fintoc over an HTTPS connection. The checkout page address must also start with `https://`, rather than `http://`, for your integration to work. First, create an empty DOM node (container) with a unique ID in your payment form: ```html theme={null}
``` When the form has loaded, create an instance of the widget and mount Express Checkout to the container DOM node: ```javascript theme={null} const widget = window.Fintoc.create({ product: "payments", publicKey: "pk_test_...", country: "cl", expressCheckout: { container: "apple-pay-container", amount: 1000, currency: "CLP", }, onPaymentRequest: async ({ payment_method_type, wallet }) => { const res = await fetch("/api/create-checkout", { method: "POST" }); const { session_token } = await res.json(); return { sessionToken: session_token }; }, onSuccess: (data) => console.log("Payment succeeded", data), onExit: (reason) => console.log("Widget closed", reason), onEvent: (eventName, metadata) => console.log(eventName, metadata), }); ``` The Apple Pay buttons can have the following styles: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/561c75e5fcefe7d9d425ebf84aeef3319c52f1faf85c723cf386406727337137-apple-pay_buttons.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=2cb710e2686837190232688296dbe678) Button styles: black, white, and white with outline *** ## Step 4: Handle the onPaymentRequest callback > **Client-side** `onPaymentRequest` runs when the SDK needs a `sessionToken` to continue the flow. For Apple Pay, the SDK calls it after the customer authorizes the Apple Pay sheet. When you call `widget.open()` for bank transfer, the SDK calls the same callback before it opens the widget. In that callback you must call your server, obtain a `session_token`, and return it to the SDK. The callback receives a single argument with information about the requested method: | Field | Type | Description | | - | - | - | | `payment_method_type` | `string` | `"card"` for wallet payments. `"bank_transfer"` when `widget.open()` is called. | | `wallet` | `string` (optional) | The specific wallet selected, e.g. `"apple_pay"`. `undefined` for bank transfer. | Your callback **must** resolve to `{ sessionToken: string }` within **30 seconds**, or the SDK emits `payment_error`. > [!NOTE] > > You can use the `payment_method_type` and `wallet` fields to reuse a single endpoint for wallets and bank transfer, or to route to different endpoints if your backend logic differs. *** ## Step 5: Submit the payment to Fintoc > **Client-side** Once the customer authorizes the wallet payment, the SDK automatically completes the flow. You don't need to call a `confirmPayment` method yourself. The sequence is: 1. The SDK opens the Apple Pay sheet and requests a payment token from Apple Pay. 2. Once the customer authorizes, the SDK emits `processing_express_checkout_payment`. 3. The SDK calls your `onPaymentRequest` callback to get a fresh `sessionToken`. 4. The SDK submits both tokens to the Fintoc backend, which creates the Payment Resource and charges the wallet. 5. When the payment reaches `status === 'succeeded'`, the SDK calls `onSuccess(data)` with the resulting resource. > [!NOTE] > > If the payment status is anything other than `succeeded`, or any step in the flow fails, the SDK emits `payment_error` instead of calling `onSuccess`. ### Handling the loading state during payment processing While Express Checkout is processing a payment, you should display a loading state to give clear feedback to your customer and prevent duplicate interactions. Manage it from the `onEvent` and `onSuccess` callbacks you already pass to `Fintoc.create`: * `processing_express_checkout_payment` fires once the customer authorizes the payment. Use it to show your loading indicator while the SDK gets a fresh `sessionToken` from your server and submits the payment. * The payment then resolves through `onSuccess` when it succeeds, or through a `payment_error` event when it fails. Use both to clear the loading indicator. A typical implementation looks like this: ```javascript theme={null} window.Fintoc.create({ // ... onEvent: (eventName) => { if (eventName === "processing_express_checkout_payment") { // Show loading state (e.g. spinner, disable buttons) setLoading(true); } if (eventName === "payment_error") { // Hide loading state after a failed attempt setLoading(false); } }, onSuccess: () => { // Hide loading state after a successful payment setLoading(false); }, }); ``` Always clear the loading state on both `onSuccess` and `payment_error` so the UI never gets stuck after a payment attempt. *** ## Step 6: Test the integration Before you go live, test the integration on a device that supports Apple Pay. **Requirements for testing:** * Use your test public key and a test recipient account. * Open your checkout on iOS or macOS. * Make sure your staging domain is enabled for Apple Pay. If you haven't done this yet, follow [Enabling Apple Pay](#enabling-apple-pay) first. **Integration checklist:** * [ ] The Apple Pay button renders on page load on a supported device. * [ ] `express_checkout_ready` fires with `wallets.applePay === true`. * [ ] Authorizing the Apple Pay sheet triggers `onPaymentRequest` with `payment_method_type: 'card'`, `wallet: 'apple_pay'`. * [ ] `processing_express_checkout_payment` fires while the payment is in progress. * [ ] `onSuccess` fires with the payment resource after a successful authorization. * [ ] Cancelling the Apple Pay sheet does **not** emit `payment_error`. * [ ] Calling `widget.open()` (bank transfer fallback) invokes `onPaymentRequest` with `payment_method_type: 'bank_transfer'` and opens the widget. *** ## Optional configurations ## Listen to the express\_checkout\_ready event After mounting, Express Checkout won't show buttons until the SDK initializes and checks wallet availability. To animate the element when the button appears, listen to the `express_checkout_ready` event. Inspect the `wallets` value to determine which buttons, if any, to display: ```javascript theme={null} // Optional: hide the element until we know if a button will show const container = document.getElementById("apple-pay-container"); container.style.visibility = "hidden"; window.Fintoc.create({ // ... onEvent: (eventName, metadata) => { if (eventName === "express_checkout_ready") { if (metadata.wallets.applePay) { container.style.visibility = "initial"; } else { // No buttons will show; fall back to bank transfer only } } }, }); ``` ## Style the button You can tune the look of the Apple Pay button through the optional fields of `expressCheckout`. ```javascript theme={null} expressCheckout: { container: "apple-pay-container", amount: 1000, currency: "CLP", // Height in pixels. Defaults to 44. Range [40, 100]. buttonHeight: 52, // Border radius in pixels. Defaults to 4. Range [0, 100]. buttonBorderRadius: 12, // Specify the label shown inside the button. // Defaults to "plain" for Apple Pay. buttonType: { applePay: "buy" }, // Specify the color scheme of the button. // Defaults to "black". buttonStyle: { applePay: "white" }, // Specify the language for the Apple Pay label. // Defaults to "es-ES". locale: { applePay: "es-MX" }, } ``` | Option | Type | Default | Description | | - | - | - | - | | `buttonHeight` | `number` (px) | `44` | Height of the button. Clamped to `[40, 100]`. | | `buttonBorderRadius` | `number` (px) | `4` | Border radius of the button. Clamped to `[0, 100]`. | | `buttonType.applePay` | `"buy"`, `"pay"`, or `"plain"` | `"plain"` | Label shown inside the Apple Pay button. | | `buttonStyle.applePay` | `"black"` or `"white"` | `"black"` | Color scheme of the Apple Pay button. | | `locale.applePay` | `"es-ES"` or `"es-MX"` | `"es-ES"` | Language for the Apple Pay button label. | > [!NOTE] > > Values outside the allowed range are clamped rather than rejected. For example, `buttonHeight: 200` is treated as `100`. The same `widget` object returned by `Fintoc.create` exposes the usual widget methods. When `expressCheckout` is configured, calling `widget.open()` automatically invokes `onPaymentRequest` with `payment_method_type: 'bank_transfer'` before opening the widget, so you don't need a second initialization. ```javascript theme={null} document .getElementById("bank-transfer-button") .addEventListener("click", () => widget.open()); ``` *** ## Event reference Express Checkout uses the same `onEvent` callback as the rest of the widget ([widget events reference](/guides/resources/widget/widget-events)), plus the events specific to this component: | Event | Payload | When it fires | | - | - | - | | `express_checkout_ready` | `{ wallets: { applePay?: boolean } }` | Once the SDK finishes initializing. The `wallets` object lists the wallets that were successfully rendered. If empty, none are available, for example on an unsupported browser or an unverified domain. | | `processing_express_checkout_payment` | None | After the customer confirms the wallet payment and the SDK is exchanging tokens with your server and the Fintoc backend. | | `payment_error` | None | The wallet payment failed at any step: `onPaymentRequest` rejected or timed out, the wallet provider returned an error, or the resulting payment status is not `succeeded`. | | `express_checkout_error` | None | An internal error prevented the button from rendering, for example when the SDK fails to load or the container is not found. | *** ## Full option reference ## Fintoc.create(options) | Parameter | Type | Required | Description | | - | - | - | - | | `product` | `"payments"` | Yes | Literal value `"payments"` for Express Checkout. | | `publicKey` | `string` | Yes | Your publishable key. | | `country` | `"cl"` or `"mx"` | No | Destination country. Defaults to `"cl"`. | | `expressCheckout` | `ExpressCheckoutConfig` | Yes | Configuration for the wallet button. | | `onPaymentRequest` | `(data) => Promise<{ sessionToken }>` | Yes | Callback that returns a `sessionToken` when the SDK needs one to continue the flow. | | `onSuccess` | `(data) => void` | No | Callback that receives the payment resource once the payment reaches `succeeded`. | | `onExit` | `(reason?: string) => void` | No | Callback that runs when the widget closes. | | `onEvent` | `(eventName, metadata?) => void` | No | Callback that receives every widget event. | ## ExpressCheckoutConfig | Parameter | Type | Required | Description | | - | - | - | - | | `container` | `string` | Yes | `id` of the DOM element where the SDK renders the wallet button. | | `amount` | `number` | Yes | Amount to charge, in the currency's minor unit. For example, CLP has no decimals and MXN uses cents. | | `currency` | `string` | Yes | Three-letter ISO 4217 currency code, for example `"CLP"` or `"MXN"`. | | `buttonHeight` | `number` | No | Button height in px. Range `[40, 100]`. Default `44`. | | `buttonBorderRadius` | `number` | No | Button border radius in px. Range `[0, 100]`. Default `4`. | | `buttonType.applePay` | `"buy"`, `"pay"`, or `"plain"` | No | Apple Pay button label. Default `"plain"`. | | `buttonStyle.applePay` | `"black"` or `"white"` | No | Apple Pay color scheme. Default `"black"`. | | `locale.applePay` | `"es-ES"` or `"es-MX"` | No | Apple Pay button language. Default `"es-ES"`. | *** ## Enabling Apple Pay Apple Pay won't load on a domain until Fintoc has registered it with Apple. Registration is a prerequisite for both testing and going live. Complete the registration for every domain that will show the button, in both staging and production. Each registered domain must use HTTPS. The process works like this: 1. **Tell Fintoc you want to use Apple Pay.** Contact your account manager, customer success contact, or sales contact, and share the domains you plan to integrate. 2. **Host the verification file Fintoc sends you.** Fintoc sends you a domain association file. Host it on each domain under the path `/.well-known/apple-developer-merchantid-domain-association`, so it's reachable at `https://your-domain.com/.well-known/apple-developer-merchantid-domain-association`. The file must return `200 OK` and be downloadable. 3. **Confirm the file is live.** Let Fintoc know once the file is hosted on every domain. Fintoc then registers each domain with Apple. 4. **Test your integration.** Once your domains are registered, the Apple Pay button can load, and you can follow the [testing steps](#step-6-test-the-integration) on a supported device. > [!WARNING] > > If a domain isn't registered, the Apple Pay button stays hidden and `express_checkout_ready` reports no available Apple Pay wallet (`wallets.applePay` is not `true`). Confirm the domain is enabled before debugging your integration. *** ## See also * [Accept a payment](/guides/payments/accept-a-payment): standard Checkout Session integration guide. * [Web Integration](/guides/resources/widget/web-integration): full widget integration guide. * [Listen to Widget events](/guides/resources/widget/widget-events): complete event catalog. * [WebView Integration](/guides/resources/widget/webview): integrating the widget inside a native app. # Accept split payments Source: https://docs.fintoc.com/guides/payments/accept-a-payment/accept-split-payments Split one Fintoc `CheckoutSession` payment across recipient `Entity` objects, sending each share to its own bank account without manual reconciliation. Split Payments lets platforms and marketplaces distribute the funds of a single payment across multiple recipients. When a customer pays through a Checkout Session, Fintoc splits the payout according to your rules and transfers each share to the recipient's own bank account. You do not need manual transfers or reconciliation on your side. Each recipient is an **Entity**: the legal holder that receives a share of the payment. An Entity declares the account where it gets paid as part of its onboarding, so there is no separate account resource to manage. There are three steps to accept split payments: 1. **Create an Entity** for each recipient 2. **Onboard the Entity**, including the account where it will be paid 3. **Create a Checkout Session with a `split` array**, then send the customer to its `redirect_url` ## Before you begin Before you start, make sure you have: * A Fintoc account with **Collects** enabled * Your [Secret Key and Public Key](/api/fintoc-api/authentication) * Recipient business and bank account information for each Entity you need to onboard *** ## Step 1: Create an Entity An Entity represents the legal holder that receives a share of a payment, such as a seller, a partner, a professional, or a business unit. ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/entities" \ --header 'Authorization: YOUR_TEST_SECRET_KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "country_code": "CL", "holder_name": "Test Merchant 1 SpA", "holder_id": "111111111" }' ``` | Param | Type | Required | Description | | - | - | - | - | | `country_code` | string | Yes | ISO 3166-1 alpha-2 country code. One of `CL` (Chile) or `MX` (Mexico). | | `holder_name` | string | Yes | Legal name of the entity holder. | | `holder_id` | string | Yes | Tax ID without formatting. Chilean tax ID (RUT) in Chile, Mexican tax ID (RFC) in Mexico. Must be unique within your organization. | ```json theme={null} { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "object": "entity", "country_code": "cl", "holder_id": "111111111", "holder_name": "Test Merchant 1 SpA", "is_root": false, "mode": "live", "status": "waiting_initialization", "capabilities": { "settlement_recipient": { "status": "waiting_initialization" }, "account_holder": { "status": "waiting_initialization" } } } ``` A new Entity's `settlement_recipient` capability starts in `waiting_initialization`. It cannot receive a split until `capabilities.settlement_recipient.status` reaches `operational`. Fintoc sets this status after it approves the onboarding. The top-level `status` reflects the Entity's most advanced capability. Use the capability status to determine whether the Entity is available for Split Payments. > [!NOTE] > > If the recipient already exists as an Entity in your organization, reuse its `id`. Creating a second Entity with the same `holder_id` returns `409 entity_holder_id_already_exists_for_organization`. List and retrieve entities with `GET /v2/entities`, which accepts `holder_id`, `status`, and `is_root` filters, and `GET /v2/entities/{id}`. *** ## Step 2: Onboard the Entity During onboarding, the Entity declares who it is and the bank account where Fintoc pays split funds. Fintoc reviews the onboarding. After approval, the Entity's `settlement_recipient` capability becomes `operational`. You complete onboarding through the API in **Chile and Mexico**. ### Create the onboarding ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings" \ --header 'Authorization: YOUR_SECRET_KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "type": "settlement_recipient", "data": { "company_information": { "business_activity": "Servicios de arquitectura", "business_address": "Av. Apoquindo 100, Santiago, Region Metropolitana, 7550000, Chile", "phone": "+56 9 1111 1111", "settlement_account": { "institution_id": "cl_banco_de_chile", "account_number": "123456789", "account_type": "checking_account" } }, "legal_representatives": [ { "first_name": "Test", "last_name": "Customer 1", "email": "test@mail.com", "nationality": "CL", "identification_number": "111111111", "position": "Representante legal" } ] } }' ``` ### Onboarding type **`type` is required when you create the onboarding.** It declares what the Entity will do with Fintoc and determines how much information the onboarding asks for. You cannot change it after creation. **`settlement_recipient`**: The `Entity` only *receives* money. Fintoc transfers its share of each split to the bank account in `settlement_account`. The `Entity` does not hold a balance at Fintoc, receive transfers from third parties, or send money out. Because the `Entity` only gets paid, the onboarding asks for the minimum needed to identify who is being paid. **This is the value to use for Split Payments.** **`account_holder`**: the `Entity` *operates* an account at Fintoc. It can receive incoming transfers, send outgoing ones, and hold a balance. That capability carries a higher risk profile, so the onboarding requires the full set of information: transactional profile, ownership structure, and supporting documents. ### The settlement account Fintoc transfers each recipient's share of every split to `data.company_information.settlement_account`. The `settlement_account` field is the only Split Payments addition to the onboarding. Required `settlement_account` fields depend on the recipient's `country_code`. #### Chile | Param | Type | Required | Description | | - | - | - | - | | `institution_id` | string | Yes | Bank identifier. See [Chile institution codes](/api/fintoc-api/chile-institution-codes). | | `account_number` | string | Yes | Account number. | | `account_type` | string | Yes | One of `checking_account` or `sight_account`. | #### Mexico | Param | Type | Required | Description | | - | - | - | - | | `account_number` | string | Yes | Standardized Mexican bank account number (CLABE), 18 digits. Fintoc derives the bank identifier from the CLABE. Do not send `institution_id` or `account_type`. | The `settlement_account` field carries no holder fields. The account holder is the Entity being onboarded, so the tax ID is already known. > [!WARNING] > > An Entity has exactly one settlement account. To change it, create a new onboarding. See [Changing the settlement account](#changing-the-settlement-account). ### Onboarding fields | Block | Required | What it declares | | - | - | - | | `type` | Yes | Onboarding type. One of `settlement_recipient` (receives split payments) or `account_holder` (operates a Fintoc account). Use `settlement_recipient` for Split Payments. | | `data` | Yes | Container for `company_information` and any optional onboarding blocks. | | `data.company_information` | Yes | Business information for the Entity. | | `data.company_information.settlement_account` | Yes | Account that receives the Entity's split funds. Required for natural-person and company Entities. | | `data.company_information.business_activity` | Required for Mexican companies. Optional for Chilean companies. | Business activity of the Entity. | | `data.company_information.business_address` | Required for Mexican companies. Optional for Chilean companies. | Business address of the Entity. | | `data.company_information.phone` | Required for Mexican companies. Optional for Chilean companies. | Contact phone number of the Entity. | | `data.legal_representatives[]` | No | Name, email, nationality, identification number, and position of each legal representative. Only processed for company Entities. | | `data.transactional_profile` | No | Expected monthly volume, number of operations, and origin of funds. Only processed for company Entities. | | `data.shareholders[]` | No | Ownership structure, with each shareholder's tax ID and participation percentage. Only processed for company Entities. | | Documents | No | Supporting files, uploaded per slot with `PUT`. Up to 20 MB each; re-uploading a slot replaces the file. | For Chilean company Entities, `business_activity`, `business_address`, and `phone` are optional. You can omit them from the example above. Mexican company Entities must still send all three. ### Submit the onboarding Once the information is complete, submit it for review: ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/entities/ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN/onboardings/onbprc_9kQ2mZpLtR4vXn/submit" \ --header 'Authorization: YOUR_SECRET_KEY' ``` > [!NOTE] > > **Automatic settlement account validation.** When you submit the onboarding, Fintoc validates `settlement_account` by sending a micro-deposit (`1 CLP` for Chilean Entities or `0.01 MXN` for Mexican Entities). The micro-deposit confirms that the account is active and that its holder matches the Entity's `holder_id`. Fintoc runs this validation automatically for every `settlement_recipient` onboarding submission; you do not need to trigger it separately. The onboarding moves through these statuses: | Status | Meaning | | - | - | | `pending` | Created, nothing submitted yet. | | `in_progress` | Being completed. Fields and documents can still be edited. | | `submitted` | Under review by Fintoc. No further edits. | | `approved` | Review passed. **The Entity's `settlement_recipient` capability is now `operational` and can receive splits.** | | `rejected` | Review failed. Create a new onboarding with the corrected data to retry. See [Retry after a rejection](/api/main-resources/events-reference/types-of-events#retry-after-a-rejection). | Two webhooks tell you the outcome: * `entity.onboarding.approved`: the Entity is ready to receive splits. * `entity.onboarding.rejected`: the review failed. Each event carries the full onboarding, including the `settlement_account` you declared, so you can read the reviewed data without calling the API. See the [settlement recipient payload](/api/main-resources/events-reference/types-of-events#settlement-recipient). > [!NOTE] > > Compliance review typically takes one to two business days. Design your flow so the recipient can be created and shown as pending while the review runs. ### Changing the settlement account Create a **new onboarding** for the same Entity with the new account. While the new onboarding is under review, the previous account stays in effect and the Entity keeps receiving splits. When Fintoc approves the new onboarding, the new account replaces the previous one. If Fintoc rejects the new onboarding, nothing changes. *** ## Step 3: Create a Checkout Session with `split` Add a `split` array to the Checkout Session. Each entry names an Entity and its share. ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header 'Authorization: YOUR_SECRET_KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": 150000, "currency": "CLP", "customer_email": "buyer@example.com", "success_url": "https://merchant.example/success", "cancel_url": "https://merchant.example/cancel", "metadata": { "order_id": "ORD-1234" }, "split": [ { "entity_id": "ent_3fXq9tLbnKmWzR4dHs2VcJ7yP5N", "type": "flat", "amount": 50000 }, { "entity_id": "ent_5jMw7rTkqZbNxH3cLs9YdV2pF8Q", "type": "flat", "amount": 45000 }, { "entity_id": "ent_9hPz4mVtkXbLwN6cRs1YdJ5qG3T", "type": "flat", "amount": 30000 }, { "entity_id": "ent_1cKp8sWnvYbMtQ5hLr7XdF3jZ2R", "type": "flat", "amount": 25000, "charge_processing_fee": true } ] }' ``` | Field | Type | Required | Description | | - | - | - | - | | `split` | array | No | Rules used to divide the payment. Omit it and 100% of the payout goes to you. When present, it must contain between 1 and 10 entries. | | `split[].entity_id` | string | Yes | ID of an Entity whose `settlement_recipient` capability is `operational`. | | `split[].type` | string | Yes | `flat` or `percentage`. Every entry must use the same type. | | `split[].amount` | integer | Yes | For `flat`, the amount in the smallest currency unit (for example, `150000` for CLP 150,000; CLP has no minor unit). For `percentage`, basis points where `10000` = 100%. | | `split[].charge_processing_fee` | boolean | Yes, on exactly one entry | The recipient that absorbs the payment's processing fee. | | `split[].metadata` | object | No | Key-value data attached to this rule. Returned in webhooks. | > [!WARNING] > > **Split rules must add up to the payment amount exactly.** No residual remains. If you keep part of the payment, declare your own root Entity as another entry, as in the example above. Retrieve your root Entity with `GET /v2/entities?is_root=true`. > [!NOTE] > > **Percentages are expressed in basis points.** `10000` = 100%, `1000` = 10%, `1` = 0.01%. To assign 90%, send `9000`. The response echoes the `split` array as you sent it, along with the `redirect_url` of the payment page. Send the customer there to complete the payment. In webhook payloads (see [Step 4](#step-4-handle-post-payment-events)), each `split` entry includes `metadata` (even when empty) and an explicit `charge_processing_fee`. Entries that do not absorb the fee return `charge_processing_fee: false`. At creation time, `metadata` remains optional and `charge_processing_fee` only needs to be sent on the entry that absorbs the fee. *** ## Step 4: Handle post-payment events `checkout_session.finished` and `payment_intent.succeeded` include a `split_applied` array with the amount resolved for each recipient. ```json theme={null} { "id": "evt_a4xK32BanKWYn", "object": "event", "type": "checkout_session.finished", "data": { "id": "cs_li5531onlFDi235", "object": "checkout_session", "amount": 150000, "currency": "CLP", "status": "finished", "metadata": { "order_id": "ORD-1234" }, "split": [ { "entity_id": "ent_3fXq9tLbnKmWzR4dHs2VcJ7yP5N", "type": "flat", "amount": 50000, "charge_processing_fee": false, "metadata": {} }, { "entity_id": "ent_5jMw7rTkqZbNxH3cLs9YdV2pF8Q", "type": "flat", "amount": 45000, "charge_processing_fee": false, "metadata": {} }, { "entity_id": "ent_9hPz4mVtkXbLwN6cRs1YdJ5qG3T", "type": "flat", "amount": 30000, "charge_processing_fee": false, "metadata": {} }, { "entity_id": "ent_1cKp8sWnvYbMtQ5hLr7XdF3jZ2R", "type": "flat", "amount": 25000, "charge_processing_fee": true, "metadata": {} } ], "split_applied": [ { "entity_id": "ent_3fXq9tLbnKmWzR4dHs2VcJ7yP5N", "calculated_amount": 50000, "charge_processing_fee": false }, { "entity_id": "ent_5jMw7rTkqZbNxH3cLs9YdV2pF8Q", "calculated_amount": 45000, "charge_processing_fee": false }, { "entity_id": "ent_9hPz4mVtkXbLwN6cRs1YdJ5qG3T", "calculated_amount": 30000, "charge_processing_fee": false }, { "entity_id": "ent_1cKp8sWnvYbMtQ5hLr7XdF3jZ2R", "calculated_amount": 25000, "charge_processing_fee": true } ], "payment_resource": { "payment_intent": { "id": "pi_38DNJo3rbvGUzKFvCGZ6dxR1Kxx", "object": "payment_intent", "status": "succeeded", "split_applied": [ { "entity_id": "ent_3fXq9tLbnKmWzR4dHs2VcJ7yP5N", "calculated_amount": 50000, "charge_processing_fee": false }, { "entity_id": "ent_5jMw7rTkqZbNxH3cLs9YdV2pF8Q", "calculated_amount": 45000, "charge_processing_fee": false }, { "entity_id": "ent_9hPz4mVtkXbLwN6cRs1YdJ5qG3T", "calculated_amount": 30000, "charge_processing_fee": false }, { "entity_id": "ent_1cKp8sWnvYbMtQ5hLr7XdF3jZ2R", "calculated_amount": 25000, "charge_processing_fee": true } ] } } } } ``` `split_applied` appears twice on `checkout_session.finished`: once on the `checkout_session` itself and once inside `data.payment_resource.payment_intent`. Both arrays carry the exact same content, so you can read either one. The nested copy is the same array delivered by `payment_intent.succeeded`, which fires alongside `checkout_session.finished`. > [!WARNING] > > `checkout_session.finished` can arrive before the payment has reached a final state. Mark the order as paid only when `data.payment_resource.payment_intent.status` is `succeeded`. Events to handle: | Event | When | | - | - | | `checkout_session.finished` | The session reached a final state. Includes `split` and `split_applied`. | | `checkout_session.expired` | The session expired before payment. | | `payment_intent.succeeded` | The payment succeeded. | | `payment_intent.failed` | The payment failed. | | `payout.created` | A payout to a recipient was created for the settlement cycle. | | `payout.succeeded` | The payout reached the recipient's account. | | `payout.canceled` | The payout was canceled and will not be sent. | | `payout.returned` | The bank returned a successful payout. Mexico only. | | `entity.onboarding.approved` | The Entity passed review and can receive splits. | | `entity.onboarding.rejected` | The review failed. | ### How and when recipients are paid Payouts follow your organization's settlement schedule. In each cycle, Fintoc groups every share owed to the same Entity into **one transfer** to its settlement account. For example, a recipient that appears in 200 payments during a cycle receives a single transfer. Retrieve a payout with `GET /v1/payouts/{id}`, list them with `GET /v1/payouts`, and get the payments it covers with `GET /v1/payouts/{id}/resources`. > [!WARNING] > > `payout.*` events fire only in `live` mode. Payouts settle against real balances, so `test` mode does not emit `payout.created`, `payout.succeeded`, `payout.canceled`, or `payout.returned`. ### Refund a split payment You can refund a payment with a split only in full. [Create a refund](/api/payments-api/refunds/refunds-create) without an `amount`, or set `amount` to the full payment amount. Fintoc rejects partial refunds for payments with a split. Each recipient funds its original share of the payment. The recipient with `charge_processing_fee: true` also pays the refund fee. If any recipient lacks the balance to fund its share, the refund stays pending while Fintoc retries it for up to 5 business days. For refund statuses and webhook events, see [Refund payments](/guides/payments/fintoc-collect-payments/payment-initiation-refunds). *** ## Rules and validations Fintoc validates the `split` array when you create a Checkout Session. The request fails with `400 Bad Request` and `invalid_request_error` if the `split` array violates any rule. **Per entry** * `entity_id` must reference an `Entity` whose `capabilities.settlement_recipient.status` is `operational`. * The `Entity` object's `country_code` must match the payment currency. * For `flat`, `amount` must be greater than `0` and less than or equal to the Checkout Session `amount`. * For `percentage`: `0 < amount <= 10000`. **Global** * Between 1 and 10 entries. * No duplicate `entity_id` values. * Every entry must use the same `type`. * The sum of all `split[].amount` values, after converting percentages, must equal the Checkout Session `amount` exactly. * For `percentage`, the values must add up to exactly `10000` bps. **Rounding.** Fintoc calculates percentage amounts as `floor(amount_total * amount / 10000)`. Fintoc assigns the accumulated rounding difference to the entry with `charge_processing_fee: true`. ### Errors | Code | Meaning | | - | - | | `ENTITY_NOT_FOUND` | The `entity_id` does not exist in your organization. | | `ENTITY_NOT_OPERATIONAL` | The Entity has not completed its onboarding. | | `DUPLICATE_ENTITY_IN_SPLIT` | The same `entity_id` appears more than once. | | `MIXED_SPLIT_TYPES` | The array mixes `flat` and `percentage`. | | `SPLIT_SUM_MISMATCH` | The amounts do not add up to `amount` exactly. | | `MISSING_CHARGE_PROCESSING_FEE` | No entry sets `charge_processing_fee` to `true`. Exactly one entry must set it. | | `MULTIPLE_CHARGE_PROCESSING_FEE` | More than one entry sets `charge_processing_fee` to `true`. | ```json theme={null} { "error": { "type": "invalid_request_error", "message": "Split rules must add up to the total amount", "code": "SPLIT_SUM_MISMATCH", "param": "split" } } ``` # Accept a payment Source: https://docs.fintoc.com/guides/payments/accept-a-payment/index Accept one-time payments in CLP or MXN through a Fintoc-hosted Checkout Session, from creating the session on your backend to redirecting the customer. Build a payment flow that collects one-time payments in CLP or MXN through a Fintoc-hosted checkout page. To accept payments with Fintoc, you complete three steps: 1. On your backend, create a `Checkout Session` using your [Secret Key](/guides/home/api-keys) 2. Redirect your customer to complete the payment on the Fintoc-hosted checkout page 3. Handle post-payment events The following diagram shows how Fintoc interacts with both your backend and your frontend: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/40e0b1888c86590031351e94422f1d5e23207fcb2f795a93eb76cbb6c780a9eb-accept-payment-diagram.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=653e7ae98608d0462ec14d67546c6ca5) ## Optional: install the backend SDK > [tab] Python > > If you’re using Python, you can install our [Python SDK](https://github.com/fintoc-com/fintoc-python) to make it easier to interact with our API. The SDK automatically handles pagination, lets you easily verify Fintoc's webhooks, and offers many other helpful features. > > ```bash theme={null} > pip install fintoc > ``` > [tab] Node > > If you’re using Node, you can install our [Node SDK](https://github.com/fintoc-com/fintoc-node) to make it easier to interact with our API. The SDK automatically handles pagination, lets you easily verify Fintoc's webhooks, and offers many other helpful features. > > ```bash theme={null} > npm install fintoc > ``` ## Create a session The [Checkout Session](/api/payments-api/checkout-sessions/checkout-session-object) object represents your intent to collect a payment from a customer and tracks state changes throughout the payment process. Using your [Secret Key](/guides/home/api-keys), create a `Checkout Session` from your backend with the required parameters: `amount`, `currency`, `success_url`, and `cancel_url`, like the example below: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 350000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "customer_data": { "tax_id": { "type": "cl_rut", "value": "41.579.263-8" }, "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {} }, "metadata": { "order": "987654321" } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 350000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', customer_data: { tax_id: { type: 'cl_rut', value: '41.579.263-8' }, name: 'Felipe Castro', email: 'jon@snow.com', metadata: {} }, metadata: { order: '987654321' } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=350000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', customer_data={ 'tax_id': { 'type': 'cl_rut', 'value': '41.579.263-8' }, 'name': 'Felipe Castro', 'email': 'jon@snow.com', 'metadata': {} }, metadata={ 'order': '987654321' } ) ``` Fintoc responds with the created `Checkout Session` object, including the `redirect_url` you use to send the customer to the payment: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 350000, "currency": "CLP", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": { "order": "987654321" }, "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } } } ``` | Parameter | Example | Description | | - | - | - | | `amount` | 350000 | **Required.** A positive integer representing the amount to charge, in the smallest currency unit. CLP has no minor unit, so `350000` means CLP 350000. MXN uses centavos, so `350000` means MXN 3500.00. [Read more about currencies](/guides/home/currencies). | | `currency` | `CLP` or `MXN` | **Required.** Three-letter ISO 4217 currency code. One of `CLP` or `MXN`. See the [supported currencies](/guides/home/currencies) for the full list. | | `success_url` | `https://merchant.com/success` | **Required.** URL Fintoc redirects the customer to after a successful payment. | | `cancel_url` | `https://merchant.com/cancel` | **Required.** URL Fintoc redirects the customer to if they cancel the payment and return to your website. | | `metadata` | `{"order": "987654321"}` | Set of key-value pairs you can attach to an object, useful for storing additional information in a structured format. | ### Business profile (optional) > [!NOTE] > > **Send the Business Profile object if you are processing payments for a submerchant** > > You can also add the `business_profile` object when creating a session to customize the name displayed as the "Recipient" on the payment flow. > > [Read here to learn more](/api/payments-api/checkout-sessions/checkout-sessions-create). ### Include customer data (optional) When creating a `Checkout Session`, you can include customer information by sending a `customer_data` object (or `customer` with the `id` of an existing `Customer`). This information allows Fintoc to display only the payment methods available for that specific customer. For example, Fintoc hides a bank when the amount exceeds its [transaction limit](/guides/payments/overview-payment-initiation/transaction-limits). | Attribute | Type | Description | | - | - | - | | `tax_id` | `object` | **Required if no `email`.** Object that identifies the customer at a fiscal or regulatory level. It includes a `type` field indicating the format or country-specific identifier, for example, `cl_rut` for a Chilean tax ID (RUT), `mx_rfc` for a Mexican tax ID (RFC), or `custom` for any other identifier. It also includes a `value` field that contains the tax identifier as a string. For `custom`, send any non-empty value. Fintoc removes leading and trailing spaces and does not validate its format. If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `name` | `string` | Full name of the customer. | | `email` | `string` | **Required if no `tax_id`.** Email address of the customer. | | `metadata` | `object` | Custom data that stores additional information about the customer, such as internal IDs, CRM references, or tags. | > [!NOTE] > > **Bank specific payment flows for business accounts and high amounts** > > In Chile, some `bank_transfer` payments require banks with special payment flows: Banco Estado, Banco de Chile, and Banco Santander. Fintoc limits the session to these banks when the payment exceeds the [transaction limits](/guides/payments/overview-payment-initiation/transaction-limits) or the `customer` has a `tax_id.value` of a business instead of a natural person. You can test this flow with the [alternative payment method test guide](/guides/payments/alternative-payment-methods/alternative-payment-method-test-your-integration). ### Include a list of items (optional) When creating a `Checkout Session`, you can also send the `line_items`, including information about the items of the session. This enables Fintoc to display this information on the checkout page and show only the payment methods available for specific products. Each item should have: | Attribute | Type | Description | | :- | :- | :- | | `quantity` | `integer` | **Required.** Number of units of this item being purchased. | | `price_data` | `object` | **Required.** Object with the price of the item and its product details. | #### The `price_data` object | Attribute | Type | Description | | :- | :- | :- | | `product_data` | `object` | **Required.** Object with information about the product, such as its name and image. | | `currency` | `string` | **Required.** Three-letter ISO 4217 currency code (for example, `CLP`, `MXN`). | | `unit_amount` | `integer` | **Required.** Price per unit of the item, in the smallest currency unit. CLP has no minor unit, so `350000` means CLP 350000. | #### The `product_data` object The `price_data` object contains a `product_data` object with product information: | Attribute | Type | Description | | :- | :- | :- | | `name` | `string` | **Required.** Name of the product or service being purchased. | | `image_url` | `string` | Image URL for the product. Must be an HTTPS URL. Recommended aspect ratio: 9:4. | The example below creates a `Checkout Session` with a single line item: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 350000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "line_items": [ { "quantity": 1, "price_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "Annual subscription", "image_url": "https://merchant.com/images/annual-subscription.png" } } } ] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 350000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', line_items: [ { quantity: 1, price_data: { currency: 'CLP', unit_amount: 350000, product_data: { name: 'Annual subscription', image_url: 'https://merchant.com/images/annual-subscription.png' } } } ] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=350000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', line_items=[ { 'quantity': 1, 'price_data': { 'currency': 'CLP', 'unit_amount': 350000, 'product_data': { 'name': 'Annual subscription', 'image_url': 'https://merchant.com/images/annual-subscription.png' } } } ] ) ``` Fintoc responds with the created `Checkout Session` object. Each item in `line_items` includes a `price` with the `product` details you sent: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 350000, "currency": "CLP", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {}, "line_items": [ { "quantity": 1, "price": { "currency": "CLP", "unit_amount": 350000, "product": { "description": null, "image_url": "https://merchant.com/images/annual-subscription.png", "metadata": {}, "name": "Annual subscription" }, "recurring": null } } ] } ``` ### Pre-select a payment method (optional) You can create a `Checkout Session` without specifying payment methods. In this case, customers can select from all available options on the Fintoc-hosted checkout page, based on the session parameters (`amount`, `customer`, `currency`) and the payment methods you have enabled in Fintoc. Alternatively, you can explicitly define the payment method type(s) for the session. For example, the request below sets the `bank_transfer` method and uses `payment_method_options` to pre-select the institution `cl_banco_estado` for the customer. In this scenario, the payment flow presented to the customer is limited to this specific method and bank. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 350000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "payment_method_types": ["bank_transfer"], "payment_method_options": { "bank_transfer": { "sender_account": { "institution_id": { "value": "cl_banco_estado" } } } }, "customer_data": { "tax_id": { "type": "cl_rut", "value": "41.579.263-8" }, "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {} } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 350000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', payment_method_types: ['bank_transfer'], payment_method_options: { bank_transfer: { sender_account: { institution_id: { value: 'cl_banco_estado' } } } }, customer_data: { tax_id: { type: 'cl_rut', value: '41.579.263-8' }, name: 'Felipe Castro', email: 'jon@snow.com', metadata: {} } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=350000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', payment_method_types=['bank_transfer'], payment_method_options={ 'bank_transfer': { 'sender_account': { 'institution_id': { 'value': 'cl_banco_estado' } } } }, customer_data={ 'tax_id': { 'type': 'cl_rut', 'value': '41.579.263-8' }, 'name': 'Felipe Castro', 'email': 'jon@snow.com', 'metadata': {} } ) ``` | Attribute | Type | Description | | :- | :- | :- | | `payment_method_types` | `array of strings` | List of payment method types available for the session. One or more of `bank_transfer`, `card`, `cash`. `cash` is available only in `MXN` sessions. | | `payment_method_options` | `object` | Set of settings for each available payment method. | Fintoc responds with the created `Checkout Session` object, echoing the pre-selected method and institution: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 350000, "currency": "CLP", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {}, "payment_method_types": [ "bank_transfer" ], "payment_method_options": { "bank_transfer": { "sender_account": { "institution_id": { "value": "cl_banco_estado" } } } }, "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } } } ``` ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/14f9be8089f64e7247ce874ee2bdca674fa9ccc1f9b479c2e499b6e31f592b35-payment-methods-pre-selected.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=13740451d33acbeb815bccfd23fac655) **Left**: Default view showing all available methods in Chile (bank transfer and cards) when no `payment_method_types` parameter is set. **Center**: Pre-selected `bank_transfer` flow for Banco Estado, displaying the institution-specific payment form directly. **Right**: Pre-selected `card` flow. > [!NOTE] > > **Using your own Checkout Page** > > When you have your own checkout page, you should set the `payment_method_types` to redirect customers to the Fintoc-hosted checkout after they've already selected their preferred payment method. > > This skips Fintoc's payment method selection screen and directs customers straight to the specific payment flow, instead of letting Fintoc manage the full checkout experience. #### Offer cash in MXN sessions In `MXN` sessions, you can offer `cash` on its own or combine it with `card` and `bank_transfer`. Your customer picks how to pay on the Fintoc-hosted checkout page. You can't combine `cash` with `installments`. For example, the following request lets your customer pay with a card or in cash: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 250000, "currency": "MXN", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "payment_method_types": ["card", "cash"] }' ``` Fintoc responds with the session object, including `cash` in `payment_method_types`: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 250000, "currency": "MXN", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {}, "payment_method_types": [ "card", "cash" ] } ``` If a card or bank transfer payment fails and `cash` is available in the session, your customer can retry the payment in cash. See [Accept cash payments in Mexico](/guides/payments/cash-payment-direct-api) for how cash payments work. ### Response when creating a Checkout Session After you make the request to create the [Checkout Session](/api/payments-api/checkout-sessions/checkout-session-object), Fintoc responds with the session object: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 350000, "currency": "CLP", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {}, "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } } } ``` The response includes the `redirect_url` attribute. In the following step, you'll use this attribute to redirect the customer to complete the payment. ## Redirect the customer to complete the payment Next, redirect customers to the Fintoc-hosted checkout page. After they complete the payment, Fintoc automatically redirects them back to your site: to the `success_url` after a successful payment, or to the `cancel_url` if they cancel. The Fintoc-hosted checkout does not support iframe integrations. Do not load the `redirect_url` in an `iframe`; redirect the full browser page instead. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` To keep customers on your site instead, render the same Checkout Session with the embedded Widget. Pass the session's `session_token` as the Widget's `sessionToken` option. See [Integrate the Widget on the web](/guides/resources/widget/web-integration) or [WebView integration](/guides/resources/widget/webview) for mobile apps. You don't create a Payment Intent for a Checkout Session. Fintoc creates the Payment Intent automatically when your customer starts a payment attempt. The session's `payment_resource` field exposes the Payment Intent and stays `null` until then. ## Handle post-payment events Once a `Checkout Session` finishes, you handle the payment result in your frontend and complete the payment in your backend. On your backend, use the events that Fintoc sends through webhooks. ### Complete the payment on your backend Fintoc sends a `checkout_session.finished` and a `payment_intent.succeeded` event when the session completes and the payment is successful. Follow the [webhook guide](/guides/resources/webhooks-walkthrough) to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow. The `checkout_session.finished` event includes information about the session and the `payment_intent`: ```json theme={null} { "id": "evt_a4xK32BanKWYn", "object": "event", "type": "checkout_session.finished", "data": { "id": "cs_li5531onlFDi235", "mode": "test", "amount": 350000, "object": "checkout_session", "status": "finished", "flow": "payment", "currency": "CLP", "metadata": {}, "cancel_url": "https://merchant.com/cancel", "created_at": "2026-01-13T18:48:25Z", "expires_at": "2026-01-14T18:48:25Z", "success_url": "https://merchant.com/success", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "session_token": null, "customer_email": null, "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } }, "payment_method_types": [ "bank_transfer" ], "business_profile": {}, "payment_resource": { "payment_intent": { "id": "pi_38DNJo3rbvGUzKFvCGZ6dxR1Kxx", "mode": "test", "amount": 350000, "object": "payment_intent", "status": "succeeded", "currency": "CLP", "metadata": {}, "created_at": "2026-01-13T18:48:31Z", "expires_at": "2026-01-14T18:48:25Z", "error_reason": null, "payment_type": "bank_transfer", "reference_id": null, "widget_token": null, "customer_email": null, "sender_account": { "type": "checking_account", "number": "000000000", "holder_id": "111111111", "institution_id": "cl_banco_falabella" }, "business_profile": {}, "transaction_date": null, "recipient_account": null, "payment_type_options": {} } }, "payment_method_options": {} } } ``` Fintoc emits these events across the payment lifecycle, including the failure and pending paths. Handle each one: | Event | Description | Action | | - | - | - | | `checkout_session.finished` | Sent when a `Checkout Session` reaches a final state. The associated payment may still be pending, for example `requires_action`. | Complete the order based on `data.payment_resource.payment_intent.status`. If the status is `requires_action`, read `next_action` and tell your customer what they need to do. | | `checkout_session.expired` | Sent when a `Checkout Session` expires. | Offer the customer another attempt to pay. | | `payment_intent.succeeded` | Sent when the payment related to a `Checkout Session` succeeds. | Confirm the customer's order. | | `payment_intent.failed` | Sent when the payment related to a `Checkout Session` fails. | Offer the customer another attempt to pay. | > [!NOTE] > > **Handling async payments after the `Checkout Session` ends** > > In some cases, the `Checkout Session` may finish with a payment that does not yet have a final status, such as `requires_action`. This can happen, for example, when a bank transfer from a business account requires approval from more than one representative. > > Fintoc does not send a separate event for this status. You receive `checkout_session.finished` with `data.payment_resource.payment_intent.status` set to `requires_action`, so inform the customer that the payment is pending approval. When the payment reaches its final status, Fintoc sends `payment_intent.succeeded` or `payment_intent.failed`. Notify the customer of the final status when you receive it. ## Test your integration Using your [test mode API Secret Key](/guides/resources/test-mode), you can create payments that simulate successful and failed outcomes without moving any money. This lets you validate your full payment flow end-to-end: * Your backend API requests (creating sessions and handling responses) * The redirect flow from your frontend to the `redirect_url` and back to the `success_url` or `cancel_url` after the payment * The webhooks for post-payment events A successful test session reaches `status` `finished` and triggers the `checkout_session.finished` and `payment_intent.succeeded` webhooks; a failed one triggers `payment_intent.failed`. To trigger specific scenarios, use the **test credentials** and special test values described in our [testing guide](/guides/payments/payment-initiation-test-your-integration). # Save a customer's payment method for future payments Source: https://docs.fintoc.com/guides/payments/accept-a-payment/save-a-paymentmethod-of-a-customer-for-future-payments Use Fintoc's Checkout Session API to save a customer's card or bank account during a payment or in a standalone setup flow, then reuse it for future payments. Build a flow that saves a customer's payment method during a payment or through a standalone setup session. For payment flows where customers pay often, like ride sharing or delivery apps, you can let your customers save a payment method for future payments. A saved payment method can be a card or a bank account, so their next payments take fewer steps. You can save a customer's payment method in two ways: 1. **Save during a payment:** create a Checkout Session with `flow` set to `payment` and `save_payment_method` set to `enabled`. Your customer gets the option to save the payment method for future payments. 2. **Save without a current payment:** create a Checkout Session with `flow` set to `setup` to enroll a payment method without processing a payment. ## Option 1: Save during a payment (recommended) The customer pays and their payment method is saved in a single step. ### Create or choose a Customer Every saved payment method must belong to a `Customer`. If you already have one, reuse its `id`. Otherwise, you can either create it first with the Customers API or send `customer_data` in the Checkout Session to create the `Customer` inline. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/customers" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "name": "Felipe Castro", "email": "jon@snow.com" }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const customer = await fintoc.v2.customers.create({ name: 'Felipe Castro', email: 'jon@snow.com' }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') customer = client.v2.customers.create( name='Felipe Castro', email='jon@snow.com' ) ``` Fintoc responds with the created `Customer`: ```json theme={null} { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "address": null, "created_at": "2026-03-16T19:41:17Z", "email": "jon@snow.com", "metadata": {}, "mode": "live", "name": "Felipe Castro", "phone": null, "tax_id": null } ``` Save the returned `id` (e.g. `cus_3B2bODrQFje7ZVkT69xyaTSDwXQ`). If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. ### Create a Checkout Session with `save_payment_method` Create a Checkout Session with the `customer` ID, `flow` set to `payment`, and `save_payment_method` set to `enabled`. Fintoc processes the payment and, if your customer chooses to save the payment method during the flow, stores their credentials for future use. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "payment", "customer": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "amount": 5000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "save_payment_method": "enabled", "payment_method_types": ["bank_transfer"] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'payment', customer: 'cus_3B2bODrQFje7ZVkT69xyaTSDwXQ', amount: 5000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', save_payment_method: 'enabled', payment_method_types: ['bank_transfer'] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='payment', customer='cus_3B2bODrQFje7ZVkT69xyaTSDwXQ', amount=5000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', save_payment_method='enabled', payment_method_types=['bank_transfer'] ) ``` Fintoc responds with the created `CheckoutSession`, including its `redirect_url`: ```json theme={null} { "id": "cs_VvO7kpUMWlq2N10B", "object": "checkout_session", "flow": "payment", "status": "created", "amount": 5000, "currency": "CLP", "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "email": "jon@snow.com", "metadata": {}, "name": "Felipe Castro", "tax_id": null }, "save_payment_method": "enabled", "payment_method_types": ["bank_transfer"], "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_VvO7kpUMWlq2N10B", "metadata": {} } ``` | **Parameter** | **Example** | **Description** | | - | - | - | | `flow` | `payment` | **Required.** Flow the session runs. One of `payment`, `setup`, or `subscription`. | | `amount` | `5000` | **Required.** A positive integer representing the amount to charge in the smallest currency unit. CLP has no minor unit, so `5000` charges \$5000 CLP. | | `currency` | `CLP` | **Required.** Three-letter ISO 4217 currency code. Only `CLP` supports saving a payment method. | | `success_url` | `https://merchant.com/success` | **Required.** URL Fintoc redirects your customer to after a successful payment. | | `cancel_url` | `https://merchant.com/cancel` | **Required.** URL Fintoc redirects your customer to if they cancel the payment and return to your website. | | `customer` | `"cus_3B2bODrQFje7ZVkT69xyaTSDwXQ"` | **Required if no `customer_data`.** ID of an existing `Customer`. | | `customer_data` | `{"email": "jon@snow.com"}` | **Required if no `customer`.** Data for inline customer creation. Send at least one of `email` or `tax_id`. If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `metadata` | `{"order": "987654321"}` | Set of key-value pairs you can attach to an object. Useful for storing additional information about the object in a structured format. | | `payment_method_types` | `["bank_transfer"]` | **Required.** Payment method types available for the session. For the `payment` flow, one or more of `bank_transfer` or `card`. Only `bank_transfer` supports saving a payment method while collecting a payment. | | `payment_method_options` | `bank_transfer` object with `sender_account` information | Options for a specific payment method type, like preselecting a specific bank. See the [complete example](/api/payments-api/checkout-sessions/checkout-sessions-create) in the API Reference. | | `save_payment_method` | `enabled` | Whether your customer gets the option to save the payment method during the flow. One of `enabled` or `disabled`. Defaults to `disabled`. | ### Redirect the customer Use the `redirect_url` returned in the response to redirect your customer to the Fintoc-hosted page, where they complete the payment and can choose to save their credentials for future payments. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` ### Handle post-payment events Always use webhooks to determine the final outcome. Your customer may close the tab, lose connection, or never reach your `success_url`. #### Checkout Session events * `checkout_session.finished`: Sent when a Checkout Session reaches a final successful state. The event includes the payment outcome and, if your customer opted in, the saved `payment_method`. Example `data` object: ```json theme={null} { "id": "cs_VvO7kpUMWlq2N10B", "flow": "payment", "mode": "test", "amount": 5000, "object": "checkout_session", "status": "finished", "currency": "CLP", "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "mode": "test", "name": null, "email": "jon@snow.com", "phone": null, "object": "customer", "tax_id": { "type": "cl_rut", "value": "11.111.111-1" }, "address": null, "metadata": {}, "created_at": "2026-03-16T19:41:17Z" }, "metadata": {}, "cancel_url": "https://merchant.com/cancel", "created_at": "2026-03-30T20:47:41Z", "expires_at": "2026-03-31T20:47:41Z", "line_items": null, "success_url": "https://merchant.com/success", "redirect_url": "https://pay.fintoc.com/checkout/cs_VvO7kpUMWlq2N10B", "setup_intent": null, "subscription": null, "session_token": "cs_VvO7kpUMWlq2N10B_sec_UuSuPYRuEQTcWKXT6ba9LDTh", "customer_email": null, "payment_method": "pm_3BgHP7aSqsqLiEcotFQfyx7Of8u", "business_profile": null, "payment_resource": { "payment_intent": { "id": "pi_3BgHFvey4Qj4QZvTTZwyLL9OfSA", "mode": "test", "amount": 5000, "object": "payment_intent", "status": "succeeded", "currency": "CLP", "metadata": {}, "created_at": "2026-03-30T20:48:12Z", "expires_at": null, "next_action": null, "error_reason": null, "payment_type": "bank_transfer", "reference_id": "575930", "widget_token": null, "customer_email": null, "sender_account": { "type": "checking_account", "number": "00000000000", "holder_id": "11.111.111-1", "institution_id": "cl_banco_falabella" }, "business_profile": null, "transaction_date": "2026-03-30T20:49:00Z", "recipient_account": { "type": "checking_account", "number": "000000000", "holder_id": "11.111.111-1", "institution_id": "cl_banco_security" }, "payment_type_options": {} } }, "save_payment_method": "enabled", "payment_method_types": [ "bank_transfer" ], "payment_method_options": {} } ``` #### Payment Method events If your customer chose to save the method, Fintoc also sends a `payment_method.activated` event. The event's `data` field contains a `PaymentMethod` like this: ```json theme={null} { "id": "pm_3BgHP7aSqsqLiEcotFQfyx7Of8u", "object": "payment_method", "created_at": "2026-03-30T20:49:12Z", "customer": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "mode": "test", "bank_transfer": { "account_holder_id": "11.111.111-1", "account_number": "00000000000", "account_type": "checking_account", "institution_id": "cl_banco_falabella", "status": "active" }, "type": "bank_transfer" } ``` Subscribe to the following post-session events: | **Event** | **Description** | **Recommended action** | | - | - | - | | `checkout_session.finished` | Session successfully completed. | Store `customer` + `payment_method`. Update your records based on the final status. | | `checkout_session.expired` | Session expired before completion. | Allow your customer to retry. | | `payment_method.activated` | Method becomes available for future charges. | Enable "pay with saved method" experiences for that customer. | | `payment_intent.succeeded` | Payment succeeded. | Fulfill the order. | | `payment_intent.failed` | Payment failed. | Ask your customer to retry or use another payment method. | *** ## Option 2: Save a method without a current payment ### Create a setup session The [**Checkout Session**](/api/payments-api/checkout-sessions/checkout-session-object) object represents your intent to save a payment method without processing a payment. Using your [**Secret Key**](/guides/home/api-keys), create a Checkout Session from your backend with `flow` set to `setup`: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "setup", "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "customer_data": { "email": "jon@snow.com" }, "metadata": {} }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'setup', currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', customer_data: { email: 'jon@snow.com' }, metadata: {} }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='setup', currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', customer_data={ 'email': 'jon@snow.com' }, metadata={} ) ``` Fintoc responds with the created `CheckoutSession`, including its `redirect_url`: ```json theme={null} { "id": "cs_VvO7kpUMWlq2N10B", "object": "checkout_session", "flow": "setup", "status": "created", "currency": "CLP", "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "email": "jon@snow.com", "metadata": {}, "name": null, "tax_id": null }, "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_VvO7kpUMWlq2N10B", "metadata": {} } ``` | **Parameter** | **Example** | **Description** | | - | - | - | | `flow` | `setup` | **Required.** Flow the session runs. One of `payment`, `setup`, or `subscription`. | | `currency` | `CLP` | **Required.** Three-letter ISO 4217 currency code. Only `CLP` supports the `setup` flow. | | `success_url` | `https://merchant.com/success` | **Required.** URL Fintoc redirects your customer to after a successful setup. | | `cancel_url` | `https://merchant.com/cancel` | **Required.** URL Fintoc redirects your customer to if they cancel the setup and return to your website. | | `customer` | `"cus_3B2bODrQFje7ZVkT69xyaTSDwXQ"` | **Required if no `customer_data`.** ID of an existing `Customer`. | | `customer_data` | `{"email": "jon@snow.com"}` | **Required if no `customer`.** Data for inline customer creation. Send at least one of `email` or `tax_id`. If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `metadata` | `{"order": "987654321"}` | Set of key-value pairs you can attach to an object. Useful for storing additional information about the object in a structured format. | | `payment_method_types` | `["pac", "direct_debit", "card"]` | Payment method types available for the session. For the `setup` flow, one or more of `pac`, `direct_debit`, or `card`. Send this parameter if your customer already selected the method on your website. | | `payment_method_options` | `pac` object with `sender_account` information | Options for a specific payment method type, such as a preselected bank or enrollment restrictions. For `card`, restrict `kinds` (`credit`, `debit`); for `pac`, restrict `sender_account.types` (`checking_account`). See the [complete example](/api/payments-api/checkout-sessions/checkout-sessions-create) in the API Reference. | > [!NOTE] > > **Send `payment_method_options` to preselect a bank for your customer** > > You can create the Checkout Session with a specific bank by sending its `institution_id` inside the `sender_account` of `payment_method_options`. Your customer can then only save a bank account of that institution. You can also send the customer's Chilean tax ID (RUT) as the `holder_id`, so the flow pre-fills it. > > We recommend this option when your customer selects their bank in your flow before you create the session, so they do not have to select a bank twice. > > You can also restrict enrollment by card kind or account type. Send `kinds` (`credit`, `debit`) inside `payment_method_options.card` to limit card kinds. Send `types` (`checking_account`) inside `payment_method_options.pac.sender_account` to limit account types. To apply no restriction, omit the option instead of sending an empty array: an empty array allows nothing. ### Redirect the customer After creating a session, you receive a `redirect_url` that you use to redirect your customer so they can enroll their bank account as a saved payment method. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d511cfe7c0e86a1d7abadf52209a6f4037ba3c73ce2d6d80768fe031d3e7a24e-setup_1.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=d6b14d623a8cb97127be0bf7b1cdfd31) *** ### Handle post-session events Subscribe to `checkout_session.finished`, `checkout_session.expired`, and `payment_method.activated` for the standalone `setup` flow. *** ## Create a payment session with a saved payment method If your customer has a saved `bank_transfer` payment method, you can create a payment Checkout Session that uses the saved method. Fintoc redirects your customer directly to the bank approval step, without asking them to log in with their bank credentials. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 100000, "currency": "CLP", "flow": "payment", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "customer": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "payment_method": "pm_1NkL7QKs215JZ1LyW4c1m9Ut", "payment_method_types": [ "bank_transfer" ] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 100000, currency: 'CLP', flow: 'payment', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', customer: 'cus_3B2bODrQFje7ZVkT69xyaTSDwXQ', payment_method: 'pm_1NkL7QKs215JZ1LyW4c1m9Ut', payment_method_types: ['bank_transfer'] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=100000, currency='CLP', flow='payment', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', customer='cus_3B2bODrQFje7ZVkT69xyaTSDwXQ', payment_method='pm_1NkL7QKs215JZ1LyW4c1m9Ut', payment_method_types=['bank_transfer'] ) ``` Fintoc responds with the created `CheckoutSession`, including its `redirect_url`: ```json theme={null} { "id": "cs_VvO7kpUMWlq2N10B", "object": "checkout_session", "flow": "payment", "status": "created", "amount": 100000, "currency": "CLP", "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "email": "jon@snow.com", "metadata": {}, "name": "Felipe Castro", "tax_id": null }, "payment_method": "pm_1NkL7QKs215JZ1LyW4c1m9Ut", "payment_method_types": ["bank_transfer"], "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_VvO7kpUMWlq2N10B", "metadata": {} } ``` ### Redirect the customer Use the `redirect_url` to redirect your customer to the Fintoc-hosted page, where they go directly to the bank approval step without logging in with their bank credentials. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` ### Handle post-payment events After the payment, Fintoc sends `checkout_session.finished`, `checkout_session.expired`, `payment_intent.succeeded`, or `payment_intent.failed`, depending on the outcome: | **Event** | **Description** | **Recommended action** | | - | - | - | | `checkout_session.finished` | Session successfully completed. | Store `customer` + `payment_method`. Update your records based on the final status. | | `checkout_session.expired` | Session expired before completion. | Allow your customer to retry. | | `payment_intent.succeeded` | Payment succeeded. | Fulfill the order. | | `payment_intent.failed` | Payment failed. | Ask your customer to retry or use another payment method. | ## Test your integration Using your [**test mode API Secret Key**](/guides/resources/test-mode), you can create Checkout Sessions that simulate successful and failed outcomes without moving any money. This lets you validate your full setup and payment flow end-to-end: * Your backend API requests (creating sessions and handling responses) * The redirect flow from your frontend to the `redirect_url` and back to the `success_url` or `cancel_url` after the setup or payment * The webhooks for post-session events that save the `customer`, the `payment_method`, and the payment result * After a successful setup or payment that saves a `payment_method`, test creating a payment session with the customer's saved method To learn how to trigger specific scenarios, use the **test credentials** and special test values described in our [**testing guide**](/guides/payments/payment-initiation-test-your-integration). For a `bank_transfer` flow in test mode, open the `redirect_url`, select the test bank, and log in with the test credentials `user_good` and `pass_good`. This combination simulates a successful enrollment and payment. After a successful run, Fintoc sends a `checkout_session.finished` event with `status` set to `finished`: ```json theme={null} { "id": "cs_VvO7kpUMWlq2N10B", "object": "checkout_session", "flow": "payment", "mode": "test", "status": "finished", "customer": { "id": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "object": "customer", "email": "jon@snow.com", "metadata": {}, "name": "Felipe Castro", "tax_id": null }, "payment_method": "pm_3BgHP7aSqsqLiEcotFQfyx7Of8u" } ``` If your customer opted in, Fintoc also sends a `payment_method.activated` event with `status` set to `active`: ```json theme={null} { "id": "pm_3BgHP7aSqsqLiEcotFQfyx7Of8u", "object": "payment_method", "customer": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "mode": "test", "type": "bank_transfer", "bank_transfer": { "account_holder_id": "11.111.111-1", "account_number": "00000000000", "account_type": "checking_account", "institution_id": "cl_banco_falabella", "status": "active" } } ``` # Accept direct debit payments in Mexico Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/direct-debit-mexico Enroll a Mexican bank account or debit card by API or Checkout Session, and test mandate approval and charges in sandbox. Enroll your customer's Mexican bank account or debit card, then use the resulting payment method for subscriptions or on-demand charges. > [!WARNING] > > Mexican direct debit (`mx_direct_debit`) is available in `test` mode. Sandbox simulates identity verification, account verification, mandate approval, and charges. It does not verify real identity documents or move money. This guide describes the sandbox integration. Choose how your customer authorizes the payment method: | Responsibility | By API | By Checkout Session | | - | - | - | | Customer interaction | You collect the account details and consent documents in your own interface. | Your customer completes enrollment at Fintoc's checkout. | | Your backend | Sends `POST /v2/payment_methods` with the details and four files. | Sends `POST /v2/checkout_sessions` and returns `redirect_url` to your frontend. | | Identity and consent | You provide the account holder's details and evidence of consent. | Fintoc handles the identity steps and generates the mandate document. | | Result | A `PaymentMethod` with a `pending` mandate. | A `finished` Checkout Session with a payment method, and a subscription when `flow` is `subscription`. The mandate starts as `pending`. | | Consent source | Fintoc sets `mx_direct_debit.consent_source` to `api`. | Fintoc sets `mx_direct_debit.consent_source` to `checkout`. | Both paths require asynchronous mandate approval before you can charge the payment method. Completing checkout is different from receiving approval. ```mermaid theme={null} flowchart TD A["Your integration"] --> B["API: collect account details and consent documents"] A --> C["Checkout Session: redirect your customer"] B --> D["Payment Method: pending mandate"] C --> E["Customer verifies identity and authorizes the account"] E --> D D --> F["payment_method.activated: ready to charge"] D --> G["payment_method.canceled: cannot charge"] ``` ## 1. Prepare your integration Use a [test secret API key](/guides/home/api-keys) on your server and [configure webhooks](/guides/resources/webhooks-walkthrough/index) to receive enrollment and payment results. Checkout Sessions for this payment method require an organization configured for Mexico and currency `mxn`. Send `Fintoc-Version: 2026-02-01` on API requests. The Node examples use the official `fintoc` SDK, and the Python examples use the official `fintoc` package. The Node SDK uses your organization’s default API version, which must be `2026-02-01` or later for these examples. See [Authentication](/api/fintoc-api/authentication) for API version selection. Every payment method belongs to a [Customer](/api/payments-api/customers/customer-object). For the API path, [create a customer](/api/payments-api/customers/customers-create) first and use its `id`. For Checkout Sessions, send an existing `customer` ID or `customer_data` to create one during session creation. The examples below use `customer_data`. For later sessions with the same billing customer, send its `customer` ID instead of creating it again. Repeating a tax ID in `customer_data` returns a conflict. The account holder's identity is separate from the billing customer's details. The holder provides a Mexican tax ID (RFC). For a bank account, use its 18-digit standardized Mexican bank account number (CLABE). Debit cards use a 16-digit number. ## 2. Enroll a payment method by API Use this path when you collect the holder's details and consent in your own interface. If your customer will authorize in Fintoc's checkout, skip to [Create a Checkout Session](#3-create-a-checkout-session). Send one `multipart/form-data` request to [Create a payment method](/api/payments-api/payment-methods/payment-methods-create). Replace `cus_000000001` with your customer's ID and the four file paths with your local files. The account number in this example is a published sandbox fixture. **Server** ```bash curl theme={null} curl --request POST "https://api.fintoc.com/v2/payment_methods" \ --header "Authorization: YOUR_TEST_SECRET_KEY" \ --header "Fintoc-Version: 2026-02-01" \ --form "type=mx_direct_debit" \ --form "customer=cus_000000001" \ --form "mx_direct_debit[account_number]=012180000000000015" \ --form "mx_direct_debit[account_type]=clabe" \ --form "mx_direct_debit[interval]=month" \ --form "mx_direct_debit[max_amount]=35000" \ --form "mx_direct_debit[account_holder][name]=Test Customer 1" \ --form "mx_direct_debit[account_holder][email]=test.customer.1@example.com" \ --form "mx_direct_debit[account_holder][rfc]=AAAA010101AAA" \ --form "mx_direct_debit[consent_documents][contract]=@contract.pdf" \ --form "mx_direct_debit[consent_documents][selfie]=@selfie.jpg" \ --form "mx_direct_debit[consent_documents][id_front]=@id_front.jpg" \ --form "mx_direct_debit[consent_documents][id_back]=@id_back.jpg" ``` ```json Response theme={null} { "id": "pm_000000001", "object": "payment_method", "created_at": "2026-10-08T12:00:00Z", "customer": "cus_000000001", "mode": "test", "mx_direct_debit": { "account_holder_id": "AAAA010101AAA", "account_number_last4": "0015", "account_type": "clabe", "consent_source": "api", "error_reason": null, "institution": { "id": "mx_banco_bbva", "country": "mx", "name": "Banco BBVA" }, "interval": "month", "max_amount": 35000, "status": "pending" }, "type": "mx_direct_debit" } ``` The endpoint returns `201 Created` with a payment method whose mandate is `pending`. Save the payment method `id` and wait for the approval event before charging it. The enrollment request accepts these parameters: | Parameter | Requirement | Description | | - | - | - | | `customer` | Required | Customer ID in the same organization and API key mode. | | `mx_direct_debit.account_number` | Required | CLABE with 18 digits and a valid checksum, or debit card number with 16 digits and a valid Luhn checksum. | | `mx_direct_debit.account_type` | Required | `clabe` or `debit_card`. | | `mx_direct_debit.institution_id` | Required if `account_type` is `debit_card` | Supported issuing bank ID. Fintoc derives the bank from a CLABE and ignores this field for `clabe`. | | `mx_direct_debit.interval` | Required | Authorization period: `week`, `month`, or `year`. | | `mx_direct_debit.max_amount` | Required | Authorized limit in MXN cents, from `100` (\$1.00 MXN) to `5000000` (\$50,000.00 MXN), inclusive. Fintoc rejects values outside this range with an invalid parameter error for `mx_direct_debit.max_amount` in `test` and `live` modes. For example, `35000` means \$350.00 MXN. | | `mx_direct_debit.account_holder` | Optional | Holder's `name`, `email`, and `rfc`. Each omitted field uses the matching Customer field. The RFC defaults from the Customer only when its tax ID type is `mx_rfc`. | | `mx_direct_debit.consent_documents` | Required | Four files: `contract`, `selfie`, `id_front`, and `id_back`. | Provide the signed mandate as `contract`, a photo of the holder with their identity document as `selfie`, and the front and back of that document as `id_front` and `id_back`. Each file must be a PDF, JPEG, or PNG, at least 100 bytes and smaller than 10 MiB (10,485,760 bytes). Fintoc checks the file content instead of relying only on the extension. An invalid document returns `422` and creates neither a mandate nor a payment method. In `live` mode, Fintoc rejects the enrollment when the holder's RFC or the account is blocked for direct debit. The request returns `422` with the `account_blocked_for_direct_debit` error code and creates neither a mandate nor a payment method. Fintoc doesn't run this check in `test` mode. > [!NOTE] > > The official Node and Python SDKs do not expose payment method creation with file uploads. Use the HTTP endpoint for this step. You do not send `consent_source`; Fintoc assigns it from the enrollment path. ## 3. Create a Checkout Session Use this path when your customer will complete enrollment in Fintoc's checkout. Set `payment_method_types` explicitly to `['mx_direct_debit']`, or include `card` to offer both. Direct debit is available for `setup` and `subscription` sessions in `test` mode with `mxn` currency. It is not a payment method for `payment` flow sessions. ### Save the payment method for future charges Create a session with `flow: 'setup'`. This enrolls the payment method without creating a subscription or charging the customer. Set the mandate terms in `payment_method_options.mx_direct_debit`. If you omit them, `max_amount` defaults to `1000000` cents (\$10,000.00 MXN) and `interval` defaults to `month`. Supported intervals are `week`, `month`, and `year`. The example authorizes up to \$350.00 MXN per month. **Server** ```bash curl theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_KEY" \ --header "Fintoc-Version: 2026-02-01" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "setup", "currency": "mxn", "payment_method_types": [ "mx_direct_debit" ], "customer_data": { "name": "Test Customer 1", "email": "test.customer.1@example.com" }, "success_url": "https://example.com/success", "cancel_url": "https://example.com/cancel", "payment_method_options": { "mx_direct_debit": { "max_amount": 35000, "interval": "month" } } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'setup', currency: 'mxn', payment_method_types: ['mx_direct_debit'], customer_data: { name: 'Test Customer 1', email: 'test.customer.1@example.com', }, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', payment_method_options: { mx_direct_debit: { max_amount: 35000, interval: 'month', }, }, }); ``` ```python Python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_KEY', api_version='2026-02-01') checkout_session = client.v2.checkout_sessions.create( flow="setup", currency="mxn", payment_method_types=[ "mx_direct_debit" ], customer_data={ "name": "Test Customer 1", "email": "test.customer.1@example.com" }, success_url="https://example.com/success", cancel_url="https://example.com/cancel", payment_method_options={ "mx_direct_debit": { "max_amount": 35000, "interval": "month" } }, ) ``` ```json Response theme={null} { "id": "cs_000000001", "object": "checkout_session", "amount": null, "business_profile": null, "cancel_url": "https://example.com/cancel", "created_at": "2026-10-08T12:00:00Z", "currency": "MXN", "customer": { "id": "cus_000000001", "object": "customer", "address": null, "created_at": "2026-10-08T12:00:00Z", "email": "test.customer.1@example.com", "metadata": {}, "mode": "test", "name": "Test Customer 1", "phone": null, "tax_id": null }, "customer_email": null, "customer_phone": null, "expires_at": "2026-10-09T12:00:00Z", "flow": "setup", "line_items": null, "metadata": {}, "mode": "test", "payment_method": null, "payment_method_options": { "mx_direct_debit": { "max_amount": 35000, "interval": "month" } }, "payment_method_types": [ "mx_direct_debit" ], "payment_resource": null, "redirect_url": "https://checkout.fintoc.com/cs_000000001", "session_token": null, "setup_intent": null, "split": null, "split_applied": null, "status": "created", "subscription": null, "success_url": "https://example.com/success" } ``` The endpoint returns `201 Created`. `payment_method` is `null` until the customer completes enrollment. Use `redirect_url` to open checkout; the public response's `session_token` is `null` for this flow. ### Create a subscription with the payment method Create a session with `flow: 'subscription'`. Fintoc derives the mandate limit from the sum of each line item's `unit_amount × quantity`, and derives the mandate period from `recurring.interval`. The example authorizes \$350.00 MXN monthly. All line items must use the same interval, and `interval_count` must be `1` when direct debit is available, including sessions that also offer cards. Use `week`, `month`, or `year`. Do not send direct debit mandate terms in `payment_method_options` for a subscription. **Server** ```bash curl theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_KEY" \ --header "Fintoc-Version: 2026-02-01" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "subscription", "currency": "mxn", "payment_method_types": [ "mx_direct_debit" ], "customer_data": { "name": "Test Customer 1", "email": "test.customer.1@example.com" }, "success_url": "https://example.com/success", "cancel_url": "https://example.com/cancel", "line_items": [ { "price_data": { "currency": "mxn", "unit_amount": 35000, "product_data": { "name": "Test monthly plan" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'subscription', currency: 'mxn', payment_method_types: ['mx_direct_debit'], customer_data: { name: 'Test Customer 1', email: 'test.customer.1@example.com', }, success_url: 'https://example.com/success', cancel_url: 'https://example.com/cancel', line_items: [ { price_data: { currency: 'mxn', unit_amount: 35000, product_data: { name: 'Test monthly plan', }, recurring: { interval: 'month', interval_count: 1, }, }, quantity: 1, } ], }); ``` ```python Python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_KEY', api_version='2026-02-01') checkout_session = client.v2.checkout_sessions.create( flow="subscription", currency="mxn", payment_method_types=[ "mx_direct_debit" ], customer_data={ "name": "Test Customer 1", "email": "test.customer.1@example.com" }, success_url="https://example.com/success", cancel_url="https://example.com/cancel", line_items=[ { "price_data": { "currency": "mxn", "unit_amount": 35000, "product_data": { "name": "Test monthly plan" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ], ) ``` ```json Response theme={null} { "id": "cs_000000001", "object": "checkout_session", "amount": null, "business_profile": null, "cancel_url": "https://example.com/cancel", "created_at": "2026-10-08T12:00:00Z", "currency": "MXN", "customer": { "id": "cus_000000001", "object": "customer", "address": null, "created_at": "2026-10-08T12:00:00Z", "email": "test.customer.1@example.com", "metadata": {}, "mode": "test", "name": "Test Customer 1", "phone": null, "tax_id": null }, "customer_email": null, "customer_phone": null, "expires_at": "2026-10-09T12:00:00Z", "flow": "subscription", "line_items": [ { "quantity": 1, "price": { "currency": "MXN", "product": { "description": null, "image_url": null, "metadata": {}, "name": "Test monthly plan" }, "recurring": { "interval": "month", "interval_count": 1 }, "unit_amount": 35000 } } ], "metadata": {}, "mode": "test", "payment_method": null, "payment_method_options": { "mx_direct_debit": {} }, "payment_method_types": [ "mx_direct_debit" ], "payment_resource": null, "redirect_url": "https://checkout.fintoc.com/cs_000000001", "session_token": null, "setup_intent": null, "split": null, "split_applied": null, "status": "created", "subscription": null, "success_url": "https://example.com/success", "billing_cycle_anchor": null, "trial_end": null } ``` The endpoint returns `201 Created`. Both `payment_method` and `subscription` are `null` until enrollment completes. `customer_data` creates the billing customer; it does not replace the holder details your customer enters during checkout. ## 4. Redirect your customer to checkout Return `redirect_url` from your backend and redirect the customer's browser to it. Keep your secret key on the server. ```javascript Client theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` Your customer completes these steps on desktop or mobile: 1. Enters the holder's first name, last name, email, and RFC. 2. Continues through identity verification, with front and back images of an Instituto Nacional Electoral (INE) voter ID and a selfie. Sandbox uses simulated documents. 3. Enters a CLABE or debit card and, for a debit card, selects the bank. 4. Confirms the account and mandate terms, then authorizes the direct debit. 5. Sees the confirmation and can download the mandate document. Keep these enrollment rules in mind: * Correcting an account that fails verification keeps the identity approval. * A rejected identity does not create a mandate or payment method. * Enrollment expires one hour after the customer submits the holder details. Advancing through screens does not extend the deadline, and it is independent of the Checkout Session's public `expires_at`. * After enrollment expires, the customer cannot resume direct debit in that session. The customer can return to your site or choose another payment method if the session still allows it. * Starting identity verification again within the same session is not supported in this release. ## 5. Handle enrollment and mandate events Handle webhooks on your backend rather than treating the redirect to `success_url` as proof that you can charge the payment method. Events can arrive out of order, so use the resource IDs to reconcile your stored state. Follow the [webhook verification and delivery guide](/guides/resources/webhooks-walkthrough/index). | Event | Path | What it means | | - | - | - | | `checkout_session.finished` | Checkout Session | Enrollment completed. The session contains `payment_method` and, for `subscription`, `subscription`. It does not confirm mandate approval or a successful charge. | | `payment_method.activated` | Both | The mandate is `active` and the payment method can be charged. | | `payment_method.canceled` | Both | The mandate was rejected, expired without approval, or canceled. Inspect `mx_direct_debit.status` to distinguish the outcome. Stop using the payment method for new charges. | | `invoice.paid`, `invoice.payment_failed` | Subscription billing | An invoice was paid or its collection failed. Enrollment and mandate approval are separate from invoice payment. | Use [Get a payment method](/api/payments-api/payment-methods/payment-methods-get) to reconcile its current state. The `mx_direct_debit.status` values are `pending`, `active`, `rejected`, `expired`, and `canceled`. Only `active` permits charges. For subscriptions, follow [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices) for billing and collection. Mandate activation does not itself confirm payment of the first invoice or change the subscription's billing dates. ## 6. Charge the enrolled payment method After `payment_method.activated`, use the payment method ID to [create an on-demand charge](/api/payments-api/payment-intents/payment-intents-create) or [create a subscription by API](/api/payments-api/subscriptions/subscriptions-create). A subscription created through checkout already has its payment method attached. Charges must use `MXN`, be between `100` and `99999900` cents (\$1.00 to \$999,999.00 MXN), and stay within the remaining authorized limit for the mandate period. Creating a charge that exceeds the available limit returns `limit_exceeded`. A charge that fails the limit check during settlement reports `amount_limit_reached`. Charge creation and charge settlement are separate; handle the charge or invoice result webhooks before marking an order as paid. ## 7. Download the mandate document Call [Get a payment method mandate document](/api/payments-api/payment-methods/payment-methods-mandate-document) with your secret key to obtain a temporary download URL. This works for both enrollment paths once the contract is stored, including while the mandate is `pending`. **Server** ```bash curl theme={null} curl --request GET "https://api.fintoc.com/v2/payment_methods/pm_000000001/mandate_document" \ --header "Authorization: YOUR_TEST_SECRET_KEY" \ --header "Fintoc-Version: 2026-02-01" ``` ```json Response theme={null} { "download_url": "https://storage.example.com/mandates/contract.pdf?signature=EXAMPLE", "expires_at": "2026-10-08T12:05:00Z", "filename": "contract.pdf" } ``` `download_url` expires after five minutes. `expires_at` is an ISO 8601 datetime in UTC, and `filename` is the stored file's name. Request a fresh URL when needed; do not store the URL as a permanent document link. This endpoint is not exposed by the official Node or Python SDKs. A missing payment method, wrong organization, or wrong API key mode returns `404` with `missing_resource`. A payment method without a downloadable native direct debit contract returns `422` with `invalid_payment_method_state`, including legacy Belvo payment methods. For checkout enrollment, Fintoc sends a confirmation email to the Checkout Session's resolved customer email when enrollment completes, unless receipt emails are suppressed by your branding configuration. The holder email entered in the widget does not replace that recipient. The confirmation email is not proof that the mandate is `active`. The widget also offers document download; it does not offer a manual email-send action. ## 8. Test the integration Use your `test` secret key and the fixtures below. Run API enrollment with local sample files, or create a Checkout Session and complete it on desktop and mobile. Verify the returned resources and received webhooks as well as the confirmation screen. ### Simulate identity verification in checkout These RFCs apply to the Checkout Session path. API enrollment accepts the consent documents you supply and does not run the checkout identity simulator. | RFC | Expected result | | - | - | | `AAAA010101AAA` | Identity approved. Continue to account entry and authorization. | | `AAAA010101111` | Identity rejected with `identity_not_approved`. No mandate or payment method is created. | | `AAAA010101222` | The first identity validation in the session fails with `identity_simulation_failed`. No mandate or payment method is created. | The last three characters select the scenario. Use a structurally valid individual RFC with 13 characters. Retrying identity verification within the same Checkout Session is not part of this release. ### Simulate account verification in checkout Use CLABE `012180000000083333` to return `account_not_validated` before a mandate is created. Correct the account to `012180000000000015` and continue without repeating identity verification. Account numbers with invalid format or checksum, and unsupported banks, are rejected before enrollment. The `3333` suffix applies to account verification in checkout. It is not a mandate-rejection scenario for API enrollment. ### Simulate mandate outcomes in either path Use the following published sandbox account numbers. For a debit card, select or send `mx_banco_bbva` as the issuing bank. Mandates first return `pending`, then resolve asynchronously. The sandbox resolution delay defaults to five seconds; allow additional time for webhook delivery. | Account type | Test number | Expected mandate status | Expected event | | - | - | - | - | | `clabe` | `012180000000000015` | `active` | `payment_method.activated` | | `clabe` | `012180000000001111` | `rejected` | `payment_method.canceled` | | `clabe` | `012180000000088888` | `expired` | `payment_method.canceled` | | `debit_card` | `4111111111111111` | `active` | `payment_method.activated` | | `debit_card` | `4111111111050335` | `rejected` | `payment_method.canceled` | CLABEs ending in `1111` simulate rejection; CLABEs ending in `8888` simulate no bank response and expiry. Debit cards ending in `0335` simulate rejection. Other valid accounts approve, except for checkout account-verification failures. A debit card ending in `1111` approves; it does not use the CLABE rejection rule. ### Simulate charges After the payment method becomes `active`, create a charge within the mandate limit. Valid amounts of at least `500` MXN cents (\$5.00 MXN) succeed; amounts from `100` to `499` simulate `insufficient_funds`. Resolution is asynchronous and defaults to five seconds in sandbox. Verify the charge result instead of only the create response. Also verify that a charge exceeding the mandate's remaining authorized limit is rejected with `limit_exceeded`, and that a `pending`, `rejected`, `expired`, or `canceled` mandate cannot be charged. ## What's next * [Manage subscription invoices](/guides/payments/accept-recurring-payments/manage-invoices). * [Payment Method reference](/api/payments-api/payment-methods/payment-method-object). * [Checkout Session reference](/api/payments-api/checkout-sessions/checkout-session-object). # Create subscriptions for your customer Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/index Create a recurring subscription for your customer with a Fintoc Checkout Session or the Subscriptions API, and collect one invoice per billing cycle. Create a subscription that bills your customer on a fixed schedule. Charge it automatically, or issue an invoice for each period and collect it yourself. A subscription never charges on its own. On each billing cycle, Fintoc creates an `Invoice` for the amount your customer owes. Fintoc then collects that invoice, or leaves it open for you to collect. The subscription schedules the charge; the invoice is the charge. Attempts, retries, and payment links all live on the invoice. Handle `invoice.*` events as part of the integration, not as an add-on. See [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices). You can create a subscription in two ways: * **With a `Checkout Session`.** Your customer enrolls a payment method at the Fintoc-hosted checkout page, and Fintoc creates the subscription with that payment method attached. Use it when your customer has to authorize the payment method. * **With the Subscriptions API.** You create the subscription on your backend, with no checkout and no customer interaction. Use it when your customer already has an enrolled payment method, or when you plan to issue invoices without charging. See [Create a subscription with the API](#create-a-subscription-with-the-api). To create a subscription with a `Checkout Session`, you complete four steps: 1. On your backend, create a `Checkout Session` with `flow: subscription`. 2. Redirect the customer to complete the enrollment at the Fintoc-hosted checkout page. 3. Handle post-enrollment and recurring payment events (webhooks). 4. Handle the invoices the subscription issues on every billing cycle. This guide ends once you have tested the subscription. From there, [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices) covers the invoices the subscription issues on every billing cycle, and [Update the payment method on a subscription](/guides/payments/accept-recurring-payments/update-the-payment-method-on-a-subscription) covers changing the payment method it charges. > [!NOTE] > > The v2 `Checkout Session` endpoints require API version `2026-02-01` or later. Fintoc pins your account to the version current on your first API request. If your account is pinned to an earlier version, send the `Fintoc-Version: 2026-02-01` header on checkout session requests. This lets you test them without affecting the rest of your integration. See [Authentication](/api/fintoc-api/authentication) for details. The following diagram shows how Fintoc interacts with both your backend and your frontend: ![fintoc-recurring-payment-diagram](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/7c83e6d024806e4bb3f97b72e61e66f4256a045722cd1d0007dc700b9b0210aa-subscription-flow.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=a00e0ea28ea70b494d1943be86d94a7c) > [!WARNING] > > This diagram covers recurring billing through Fintoc, not legacy enrollment-only integrations under your own bank agreement. If your existing integration only enrolls bank accounts, follow [Enrollment under your own bank agreement](/api/direct-debit-legacy/direct-debit-subscriptions/direct-debit-subscription-object#enrollment-under-your-own-bank-agreement). That flow ends at `subscription_intent.succeeded`; your bank handles activation and collections. The v2 `CheckoutSession` flow does not support bank-account enrollment under your own agreement. ## Create a Checkout Session The [Checkout Session](/api/payments-api/checkout-sessions/checkout-session-object) object represents your intent to enroll a payment method for recurring charges, and to create a subscription with a fixed amount and periodicity. Using your [Secret Key](/guides/home/api-keys), create a `Checkout Session` on your backend with `flow` set to `subscription`. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "subscription", "amount": 350000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "payment_method_types": [ "pac" ], "customer_data": { "tax_id": { "type": "cl_rut", "value": "41.579.263-8" }, "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {} }, "line_items": [ { "price_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "Plan 1" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ], "metadata": { "subscription_external_id": "sub_987654321" } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'subscription', amount: 350000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', payment_method_types: ['pac'], customer_data: { tax_id: { type: 'cl_rut', value: '41.579.263-8' }, name: 'Felipe Castro', email: 'jon@snow.com', metadata: {} }, line_items: [ { price_data: { currency: 'CLP', unit_amount: 350000, product_data: { name: 'Plan 1' }, recurring: { interval: 'month', interval_count: 1 } }, quantity: 1 } ], metadata: { subscription_external_id: 'sub_987654321' } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='subscription', amount=350000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', payment_method_types=['pac'], customer_data={ 'tax_id': { 'type': 'cl_rut', 'value': '41.579.263-8', }, 'name': 'Felipe Castro', 'email': 'jon@snow.com', 'metadata': {}, }, line_items=[ { 'price_data': { 'currency': 'CLP', 'unit_amount': 350000, 'product_data': { 'name': 'Plan 1', }, 'recurring': { 'interval': 'month', 'interval_count': 1, }, }, 'quantity': 1, } ], metadata={ 'subscription_external_id': 'sub_987654321', }, ) ``` Fintoc responds with the [Checkout Session](/api/payments-api/checkout-sessions/checkout-session-object) object. Store its `id` and `redirect_url` to continue the flow: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "flow": "subscription", "status": "created", "amount": 350000, "currency": "CLP", "payment_method_types": ["pac"], "customer": { "id": "cus_NffrFeUfNV2Hib", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } }, "line_items": [ { "price": { "product": { "name": "Plan 1", "description": "Fixed-amount monthly plan" }, "currency": "CLP", "unit_amount": 350000, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ], "metadata": { "subscription_external_id": "sub_987654321" }, "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235" } ``` The response includes a `redirect_url` attribute. In the next step, you redirect the customer to this location to complete the subscription. The following table describes the parameters you send when creating a `Checkout Session`: | Parameter | Example | Description | | - | - | - | | `amount` | 350000 | **Required.** A positive integer representing the value to charge, in the smallest currency unit (for example, `1000` for `$1000 CLP`, since CLP has no minor unit, or `2476` for `$24.76 MXN`, since MXN has a minor unit). See the [currencies](/guides/home/currencies) page for details. | | `currency` | `CLP` | **Required.** Three-letter ISO 4217 currency code for the recurring payments. One of `CLP` or `MXN`. Fintoc charges in this currency, so a subscription priced in Unidad de Fomento (UF) keeps `CLP` here. | | `flow` | `subscription` | **Required.** Flow type for the session. One of `payment`, `setup`, or `subscription`. | | `success_url` | `https://merchant.com/success` | **Required.** URL to redirect the customer to after a successful enrollment. | | `cancel_url` | `https://merchant.com/cancel` | **Required.** URL to redirect the customer to if they cancel the enrollment and return to your website. | | `customer` | `cus_3B2bODrQFje7ZVkT69xyaTSDwXQ` | **Required if no `customer_data`.** ID of an existing `Customer`. | | `customer_data` | `(object)` | **Required if no `customer`.** Data for inline customer creation. If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `payment_method_types` | `["pac"]` | List of allowed payment methods during enrollment. One or more of `pac` (charges on bank accounts in Chile), `mx_direct_debit` (Mexican direct debit in `test` mode with `MXN`; see [the sandbox guide](/guides/payments/accept-recurring-payments/direct-debit-mexico)), and `card`. | | `line_items` | `(array)` | **Required.** Array of items the customer subscribes to. Each item contains `quantity` and either `price` or `price_data`. | | `metadata` | `{"subscription_external_id": "sub_987654321"}` | Set of key-value pairs you can attach to an object. Useful for storing additional information about the object in a structured format. | ### Include customer data (required for subscriptions) When creating a `Checkout Session` with `flow: subscription`, you must include customer information. You can do this either by referencing an existing customer ID (`customer`) or by sending `customer_data` to create one inline: | Attribute | Type | Description | | - | - | - | | `tax_id` | `object` | **Required if no `email`.** Object that identifies the customer at a fiscal or regulatory level. The `type` is `cl_rut` for a Chilean tax ID (RUT), `mx_rfc` for a Mexican tax ID (RFC), or `custom` for any other identifier, and `value` is the tax identifier as a string. For `custom`, send any non-empty value. Fintoc removes leading and trailing spaces and does not validate its format. See the [Customer object](/api/payments-api/checkout-sessions/checkout-session-object#customer-object). If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `name` | `string` | Full name of the customer. | | `email` | `string` | **Required if no `tax_id`.** Email address of the customer. | | `metadata` | `object` | Custom data that stores additional information about the customer, for example internal IDs, CRM references, or tags. | ### Include an items list (required for subscriptions) When creating a `Checkout Session` with `flow: subscription`, you must include the items the customer subscribes to. This information lets Fintoc display the items on the checkout page and show only the payment methods available for specific products. | Attribute | Type | Description | | :- | :- | :- | | `quantity` | `integer` | **Required.** Number of units of this item being purchased. | | `price_data` | `object` | **Required.** Data used to generate a new recurring price inline. | Each item in `line_items` must include `price_data`. #### `price_data` object | Attribute | Type | Description | | :- | :- | :- | | `product_data` | `object` | **Required.** Data used to generate a new `Product` object inline. | | `currency` | `string` | Three-letter ISO 4217 currency code for the item. One of `CLP`, `MXN`, or `CLF`. It must match the session's `currency`, except `CLF` (UF), which prices an item inside a `CLP` subscription. | | `unit_amount` | `integer` | **Required.** Price per unit in the smallest currency unit. For example, `1000` represents `$1000 CLP`, since CLP has no minor unit. `2476` represents `$24.76 MXN`, since MXN has a minor unit. `35000` represents 3.5 UF, since CLF has four decimals. | | `recurring` | `object` | **Required.** Recurring configuration. `interval` is one of `day`, `week`, `month`, or `year`, and `interval_count` is the number of intervals between charges (for example, `1` for monthly when `interval` is `month`). | #### `product_data` object | Attribute | Type | Description | | :- | :- | :- | | `name` | `string` | **Required.** Name of the product or service being purchased. | | `image_url` | `string` | Image URL for the product. Must be an HTTPS URL. Recommended aspect ratio: 9:4. | ### Price a subscription in UF To charge a plan indexed to UF, keep the session's `currency` as `CLP`. Set the item's `price_data.currency` to `CLF`, the ISO 4217 code for UF. Set `unit_amount` in the smallest UF unit, which has four decimals. The following partial payload shows the UF-specific fields; keep the other required fields from the full request above: ```json theme={null} { "flow": "subscription", "currency": "CLP", "line_items": [ { "price_data": { "currency": "CLF", "unit_amount": 35000, "product_data": { "name": "Plan UF" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ] } ``` Fintoc charges the subscription in `CLP`. When Fintoc generates an invoice, Fintoc converts every `CLF` item using the UF value at the start of the billing period. The amount adjusts on every cycle. Once Fintoc issues the invoice, the invoice amount no longer changes, no matter when your customer pays the invoice. A single subscription can combine `CLP` and `CLF` items, which lets you index only part of a plan to UF. Any other currency mix, such as an `MXN` item inside a `CLP` subscription, returns an error, and Fintoc does not create the subscription. ## Redirect the customer to complete the enrollment Next, redirect the customer to the Fintoc-hosted checkout page using the `redirect_url`. After the customer completes the enrollment, Fintoc redirects the customer back to your site: to the `success_url` on success, or to the `cancel_url` if they cancel. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` ## Handle post-session events Once a `Checkout Session` finishes, you handle the result in your frontend and complete the subscription in your backend. For your backend, you use the events that Fintoc sends through webhooks. ### Complete the subscription on your backend Fintoc sends a `checkout_session.finished` event when the session completes. In a subscription flow, this event includes information about the session and references to the `subscription` and `payment_method` created during enrollment. ```json theme={null} { "id": "evt_a4xK32BanKWYn", "object": "event", "type": "checkout_session.finished", "data": { "id": "cs_li5531onlFDi235", "flow": "subscription", "customer": { "id": "cus_NffrFeUfNV2Hib", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "111111111" } }, "payment_method_types": ["pac"], "status": "finished", "payment_status": "succeeded", "subscription": "sub_NffrFeUfNV2Hib", "payment_method": "pm_NffrFeUfNV2Hib" } } ``` You should handle the following post-session events: | Event | Description | Action | | :- | :- | :- | | `checkout_session.finished` | Sent when a subscription `Checkout Session` reaches a final state. | Store the created IDs (`subscription`, `payment_method`, `customer`). With `charge_automatically`, wait for `invoice.payment_succeeded` before you grant your customer access: the subscription is still `incomplete` at this point. | | `checkout_session.expired` | Sent when a session expires. | Offer the customer another attempt to subscribe. | | `payment_intent.succeeded` | Sent when a payment intent succeeds, like a charge on a bank account or card. | Confirm to your customer that the subscription charge succeeded. | | `payment_intent.failed` | Sent when a payment intent fails. | Offer the customer another attempt to pay the subscription. | > [!NOTE] > > In `live` mode, when the bank has not activated a Chilean automatic debit (PAC) mandate yet, Fintoc schedules the first charge for 2 Chilean business days later. The first invoice stays `open` and the subscription stays `incomplete` until Fintoc charges the invoice. Fintoc charges cards right away. See [First automatic debit (PAC) charge while the mandate activates](/guides/payments/accept-recurring-payments/manage-invoices#first-automatic-debit-pac-charge-while-the-mandate-activates). To link a payment intent to an invoice and subscription, read the payment intent's `invoices` field. See [Reconcile payments with invoices and subscriptions](/guides/payments/accept-recurring-payments/manage-invoices#reconcile-payments-with-invoices-and-subscriptions). ## Create a subscription with the API When your customer does not need to enroll a payment method in a checkout, create the subscription directly with [Create a subscription](/api/payments-api/subscriptions/subscriptions-create). You need an existing `customer` and the `items` the subscription bills on every cycle. The `collection_method` decides how Fintoc collects every invoice the subscription generates: * `charge_automatically`, the default, charges a `payment_method` on every billing cycle. The payment method is required. * `send_invoice` leaves every invoice `open` for you to collect. The payment method is optional. ### Charge automatically against a payment method Pass the `payment_method` Fintoc charges on every billing cycle. It must belong to the `customer`, be `active`, and be `pac`, `card`, or `mx_direct_debit` (in `test` mode with `MXN`). Subscriptions do not support `bank_transfer`. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/subscriptions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_NffrFeUfNV2Hib", "payment_method": "pm_NffrFeUfNV2Hib", "collection_method": "charge_automatically", "items": [ { "price_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "Plan 1" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ], "metadata": { "subscription_external_id": "sub_987654321" } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const subscription = await fintoc.v2.subscriptions.create({ customer: 'cus_NffrFeUfNV2Hib', payment_method: 'pm_NffrFeUfNV2Hib', collection_method: 'charge_automatically', items: [ { price_data: { currency: 'CLP', unit_amount: 350000, product_data: { name: 'Plan 1' }, recurring: { interval: 'month', interval_count: 1 } }, quantity: 1 } ], metadata: { subscription_external_id: 'sub_987654321' } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') subscription = client.v2.subscriptions.create( customer='cus_NffrFeUfNV2Hib', payment_method='pm_NffrFeUfNV2Hib', collection_method='charge_automatically', items=[ { 'price_data': { 'currency': 'CLP', 'unit_amount': 350000, 'product_data': { 'name': 'Plan 1', }, 'recurring': { 'interval': 'month', 'interval_count': 1, }, }, 'quantity': 1, } ], metadata={ 'subscription_external_id': 'sub_987654321' } ) ``` | Parameter | Example | Description | | - | - | - | | `customer` | `cus_NffrFeUfNV2Hib` | **Required.** ID of the `Customer` the subscription bills. | | `items` | See the example above | **Required.** Items the subscription bills for on every billing cycle. Each item takes the same `price_data` and `product_data` objects as a checkout session's `line_items`. Set each `unit_amount` in the smallest currency unit. Up to 10 items, all sharing the same `interval` and `interval_count`. | | `payment_method` | `pm_NffrFeUfNV2Hib` | Payment method Fintoc charges on every billing cycle. Required with `charge_automatically`, optional with `send_invoice`. Must belong to `customer`, be `active`, and be `pac`, `card`, or `mx_direct_debit` (in `test` mode with `MXN`). | | `collection_method` | `charge_automatically` | How Fintoc collects every invoice the subscription generates. One of `charge_automatically` or `send_invoice`. Defaults to `charge_automatically`. | | `trial_end` | `2026-10-01T00:00:00Z` | ISO 8601 timestamp in UTC at which a trial ends, at least one day in the future. During the trial the subscription is `trialing` and Fintoc issues no invoice. Fintoc anchors the billing cycle to `trial_end` and issues the first invoice then. Omit for no trial. | | `metadata` | `{ "subscription_external_id": "sub_987654321" }` | Set of key-value pairs for storing additional information. | Fintoc responds with the created subscription: ```json theme={null} { "id": "sub_NffrFeUfNV2Hib", "object": "subscription", "billing_cycle_anchor": "2026-08-28T15:00:00Z", "collection_method": "charge_automatically", "created_at": "2026-08-28T15:00:00Z", "customer": "cus_NffrFeUfNV2Hib", "items": [ { "id": "si_2c4mDfkPLLrLTCJ3wPCEHGYpkVf", "object": "subscription_item", "price": { "currency": "CLP", "unit_amount": 350000, "recurring": { "interval": "month", "interval_count": 1 }, "product": { "id": "prod_2c4mDgwQqkNwMHnXSc4DBjkbcWz", "object": "product", "name": "Plan 1", "description": null, "image_url": null, "metadata": {}, "mode": "live", "created_at": "2026-08-28T15:00:00Z" } }, "quantity": 1 } ], "metadata": { "subscription_external_id": "sub_987654321" }, "mode": "live", "payment_method": "pm_NffrFeUfNV2Hib", "status": "incomplete", "trial_end": null } ``` The subscription starts `incomplete`, not `active`. Fintoc finalizes the initial invoice during subscription creation and charges the payment method. The subscription becomes `active` once that first payment succeeds. Track the outcome with the `invoice.*` events described in [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices). ### Issue invoices without charging Set `collection_method` to `send_invoice` and leave out `payment_method`. Fintoc issues one invoice per billing cycle and leaves each one `open`, so the subscription never charges anyone on its own. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/subscriptions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_NffrFeUfNV2Hib", "collection_method": "send_invoice", "items": [ { "price_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "Plan 1" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ] }' ``` The subscription starts `active` when you create it, and the initial invoice stays `open`. `active` does not mean your customer paid. With `send_invoice` there is no charge to wait for, so Fintoc skips the `incomplete` status. Track the `status` of each invoice to know what your customer owes. You can attach a payment method later with [Update a subscription](/api/payments-api/subscriptions/subscriptions-update), which lets you charge open invoices on demand. For the ways to settle an open invoice, see [Collect the invoices yourself instead of charging automatically](/guides/payments/accept-recurring-payments/manage-invoices#collect-the-invoices-yourself-instead-of-charging-automatically). ## Test your integration To confirm that your integration works correctly, you can simulate subscriptions and scheduled recurring payments without moving any money. ### 1) Create a subscription Checkout Session using test user credentials Using your test mode Secret Key, create a `Checkout Session` with `flow: subscription` on your backend. Then complete the enrollment on the Fintoc-hosted checkout page with the following credentials: **Test credentials** * Username (RUT): `41.579.263-8` * Password: `jonsnow` ### 2) Handle simulated scheduled payments of the subscription In test mode, Fintoc simulates scheduled subscription payments so you can verify success and failure handling without moving money. You handle simulated payments through the same `invoice.*` and `payment_intent.*` events described in [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices). A successful charge emits `invoice.payment_succeeded`, `invoice.paid`, and `payment_intent.succeeded`. A failed charge emits `invoice.payment_failed` and `payment_intent.failed`. > [!NOTE] > > Mexican direct debit (`mx_direct_debit`) supports recurring payments in `test` mode with `MXN`. Follow [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico) for the sandbox enrollment and charge scenarios. ## Go live Before you create subscriptions in `live` mode, confirm that your organization has the required products enabled for each payment method you plan to offer: * **`pac`** requires the Subscriptions product. * **`card`** requires card payments with setup for future charges. Fintoc checks each type in `payment_method_types` separately. If any listed type is not enabled for your organization in `live` mode, `POST /v2/checkout_sessions` returns a `403 Forbidden` error. The error has `type` set to `authorization_error` and `code` set to `product_access_required`. If you omit `payment_method_types`, Fintoc offers only the enabled types. The endpoint returns this error only when no payment method types are enabled. ```json theme={null} { "error": { "type": "authorization_error", "code": "product_access_required", "param": null, "message": "Your organization does not have access to the 'Subscriptions' product. Send an email to sales@fintoc.com to hire this product.", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` To enable a product for `live` mode, email [sales@fintoc.com](mailto:sales@fintoc.com) or contact your Account Executive. Specify which payment methods you need for subscriptions. For the rest of the steps to go live, see the [Go-live checklist](/guides/payments/go-live-checklist). # Manage invoices Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/manage-invoices Handle the invoices a Fintoc subscription issues on every billing cycle, recover a failed charge, and create your own invoices for amounts outside the cycle. When you create a [subscription](/guides/payments/accept-recurring-payments), Fintoc generates an `Invoice` for each billing cycle. An invoice represents the amount your customer owes for a given period. With `charge_automatically`, Fintoc attempts to collect the invoice using the enrolled payment method. With `send_invoice`, the invoice stays `open` for you to collect. Fintoc creates the invoices of the subscription for you. You can also create your own invoices for amounts the subscription does not cover, and collect any open invoice on demand. For full details on invoices, see the [Invoice object](/api/payments-api/invoices/invoice-object). ## Invoices in the subscription flow After the `checkout_session.finished` event, Fintoc creates the first invoice and charges the enrolled payment method. With `charge_automatically`, the subscription stays `incomplete` until that first payment succeeds, and then becomes `active`. Handle the following invoice-related events alongside the post-session events in [Create subscriptions for your customer](/guides/payments/accept-recurring-payments#handle-post-session-events): | Event | Description | Action | | - | - | - | | `invoice.upcoming` | Sent before a subscription's next billing cycle, as a preview of the invoice Fintoc is about to create. The preview has no `id`. | Remind your customer of the upcoming charge. See [Upcoming invoice previews](/api/main-resources/events-reference/types-of-events#upcoming-invoice-previews). | | `invoice.created` | Sent when Fintoc generates a new invoice for a billing cycle. | Log the invoice and update your records. | | `invoice.finalized` | Sent when Fintoc finalizes the invoice and it becomes ready for payment. | Store the `hosted_invoice_url`, but send it to your customer only if the automatic charge later fails. | | `invoice.finalization_failed` | Sent when Fintoc can't finalize an invoice because its `split` doesn't add up to its `total`. The invoice stays in `draft`. | Fix the split and finalize the invoice. See [Split mismatches at finalization](/guides/payments/accept-recurring-payments/split-on-recurring-payments#split-mismatches-at-finalization). | | `invoice.payment_created` | Sent when a payment for the invoice starts, either from an automatic charge or from your customer using the `hosted_invoice_url`. | Treat the event as informational. Do not send the `hosted_invoice_url` while a payment is in progress. | | `invoice.payment_succeeded` | Sent when Fintoc collects the invoice payment. | Confirm the payment to your customer and extend access. | | `invoice.paid` | Sent on every transition to `paid`, whether Fintoc collected the invoice or you marked it as paid outside Fintoc. | Settle the debt in your records. Read `external_payment` to tell whether the money went through Fintoc. | | `invoice.payment_failed` | Sent when a payment attempt for the invoice fails. | Send the `hosted_invoice_url` so your customer can pay the invoice. | | `invoice.voided` | Sent when an invoice becomes void and Fintoc disables its `hosted_invoice_url`. | Update your records. | | `invoice.marked_uncollectible` | Sent when you mark an `open` invoice as `uncollectible`. | Record the debt as uncollectible in your records. | **Month 1:** When the subscription is created, Fintoc generates the first invoice and finalizes it without the one-hour draft window. Fintoc then charges the enrolled payment method. On success, you receive `invoice.created`, followed by `invoice.finalized`, `invoice.payment_succeeded`, `invoice.paid`, and `payment_intent.succeeded`. **Month 2 onwards:** At each billing cycle renewal, based on the subscription's `billing_cycle_anchor`, Fintoc creates a new invoice in `draft` status. After 1 hour, Fintoc finalizes the invoice, moves it to `open`, and charges the enrolled payment method. Use that hour to adjust the invoice before Fintoc charges it. On success, you receive `invoice.finalized`, `invoice.payment_succeeded`, and `invoice.paid`. On failure, you receive `invoice.payment_failed`. ### First automatic debit (PAC) charge while the mandate activates In `live` mode, a new Chilean automatic debit (PAC) mandate may still be pending when Fintoc finalizes the invoice. Fintoc defers the first charge when both conditions apply: * The PAC payment method is not `active` yet. * Fintoc has never charged that payment method. In that case, Fintoc schedules the charge for 2 Chilean business days later, at the same time of day, instead of charging right away. The invoice's `next_payment_attempt_at` field shows when Fintoc will charge it. While the charge is scheduled, the first invoice stays `open` and the subscription stays `incomplete`. This state is expected and does not mean the payment failed. Do not send the `hosted_invoice_url` to your customer during this window. When Fintoc runs the charge, you receive `invoice.payment_created`. If the charge succeeds, you then receive `invoice.payment_succeeded` and `invoice.paid`, and the subscription becomes `active`. If it fails, you receive `invoice.payment_failed`. Fintoc does not defer charges on cards or on PAC payment methods that are already `active`. Fintoc charges them right after it finalizes the invoice. In `test` mode, Fintoc never defers the first charge. Fintoc finalizes the invoices of a subscription for you. An invoice you create yourself stays `draft` until you finalize it, as described in [Charge an amount outside the billing cycle](#charge-an-amount-outside-the-billing-cycle). ## Recovering a failed payment When an automatic charge fails, Fintoc emits `invoice.payment_failed`. To recover the payment, send the invoice's `hosted_invoice_url` to your customer through your own channel, such as email or WhatsApp. The hosted page lets your customer pay using the payment methods enabled on your organization's account. A successful payment creates a `payment_intent` on the invoice and settles the debt. The subscription's enrolled payment method stays valid, and Fintoc charges the next cycle automatically. The `hosted_invoice_url` becomes available on the `Invoice` object once the invoice reaches `open` status. For details, see the [Invoice object](/api/payments-api/invoices/invoice-object). > [!NOTE] > > An invoice accepts only one payment at a time. If you open the `hosted_invoice_url` while an automatic charge is in progress, the page shows that an invoice payment is in progress and the payment link is disabled. Fintoc re-enables the payment link if the automatic charge fails. ## Reconcile payments with invoices and subscriptions Use the `invoices` field of the `payment_intent` to link each payment to the invoice it pays. The field lists the IDs of the invoices the payment intent covers. Fintoc includes the `invoices` field in the API and in `payment_intent.*` webhooks for every payment on an invoice. Covered payments include automatic charges, their retries, and payments from the `hosted_invoice_url`. To find the subscription of any payment, read the invoice ID from `invoices`, then [get the invoice](/api/payments-api/invoices/invoices-get) and read its `subscription` field. The invoice's `payments` array also lists the `payment_intent` of every attempt. The payment intent's `metadata` comes from the invoice. If the invoice has no `metadata`, the payment intent's `metadata` is empty. To add your own references, [update the invoice metadata](/api/payments-api/invoices/invoices-update). ## Charge an amount outside the billing cycle Fintoc issues the subscription invoices for you. You can also create an invoice yourself for an amount the subscription does not cover. Use this for a one-off adjustment, an extra service, or a charge outside the billing calendar. Create it for the same `customer`, with the payment method enrolled during checkout as `default_payment_method`. ![fintoc-invoice-creation-diagram](https://mintcdn.com/fintoc-49b8bee8/3flF6A2hSLiRffRb/images/invoice-flow-diagram.png?fit=max\&auto=format\&n=3flF6A2hSLiRffRb\&q=85\&s=b2611362498d3d40a09b5a0498bb1726) Fintoc's Node and Python libraries don't create invoices. Call the [Create an invoice](/api/payments-api/invoices/invoices-create) endpoint over HTTP, as in this `curl` example. **Server** ```bash curl theme={null} curl --request POST "https://api.fintoc.com/v2/invoices" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_NffrFeUfNV2Hib", "default_payment_method": "pm_NffrFeUfNV2Hib", "collection_method": "charge_automatically", "lines": [ { "name": "Plan upgrade", "amount": 50000, "currency": "CLP", "quantity": 1 } ], "metadata": { "order_id": "order_98765" } }' ``` ```json theme={null} { "id": "inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe", "object": "invoice", "attempt_count": 0, "collection_method": "charge_automatically", "created_at": "2026-08-10T15:22:11.474Z", "currency": "CLP", "customer": "cus_NffrFeUfNV2Hib", "default_payment_method": "pm_NffrFeUfNV2Hib", "external_payment": false, "hosted_invoice_url": null, "lines": [ { "id": "il_3cWeY1QrKt7SiOv0GnAmUp3FzLr", "object": "line_item", "amount": 50000, "currency": "CLP", "description": null, "name": "Plan upgrade", "period_end": null, "period_start": null, "quantity": 1 } ], "metadata": { "order_id": "order_98765" }, "mode": "live", "next_payment_attempt_at": null, "payments": [], "status": "draft", "subscription": null, "total": 50000 } ``` Fintoc returns the invoice in `draft` status, with `subscription` set to `null`. The invoice bills the customer, not the subscription, so it does not change the subscription's billing cycle or amount. [Finalize the invoice](/api/payments-api/invoices/invoices-finalize) to move it to `open` and charge `default_payment_method`. Unlike the invoices of a subscription, which Fintoc finalizes on its own after an hour in `draft`, an invoice you create stays `draft` until you finalize it. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/invoices/inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe/finalize" \ --header "Authorization: YOUR_SECRET_API_KEY" ``` After finalization, the invoice behaves like a subscription invoice. It emits the same `invoice.*` events, keeps the same `payments` history, and exposes the same `hosted_invoice_url` to fall back on when a charge fails. You can also retry a failed charge with [Pay an invoice](/api/payments-api/invoices/invoices-pay), against the enrolled payment method or another active payment method of the same customer. For the full on-demand flow, including how to collect an invoice from a customer with no enrolled payment method, see [Save a payment method for future charges](/guides/payments/accept-recurring-payments/setup-a-payment-method-for-future-charges). ## Collect the invoices yourself instead of charging automatically With `collection_method` set to `send_invoice`, Fintoc stops making automatic charges. Fintoc still issues one invoice per billing period, but each invoice stays `open` and you decide how to collect it. You have three ways to settle an open invoice: 1. Send your customer the payment link in `hosted_invoice_url` and let them pay through the Fintoc-hosted page. 2. Charge the invoice on demand with [Pay an invoice](/api/payments-api/invoices/invoices-pay), using the payment method attached to the subscription. 3. Collect the money outside Fintoc, by bank transfer or cash, and mark the invoice as paid. Fintoc records this with `external_payment` set to `true`. Because `send_invoice` never charges automatically, it does not require a payment method. To create this subscription with the API, without sending your customer through a checkout enrollment, see [Issue invoices without charging](/guides/payments/accept-recurring-payments#issue-invoices-without-charging). You can still attach a payment method later, which lets you charge invoices on demand. Fintoc does not contact your customer through any channel. Reaching out is your responsibility, whichever option you use. Collecting the invoices yourself has three consequences: * Unpaid invoices accumulate. Each billing period adds one invoice, and each one settles separately. * The subscription starts `active`, and that does not mean your customer paid. With `send_invoice`, no automatic charge waits to complete, so Fintoc skips the `incomplete` status used with `charge_automatically`. Track the `status` of each invoice to know what your customer owes. * Only [Update a subscription](/api/payments-api/subscriptions/subscriptions-update) changes the collection method. Attaching a payment method does not switch the subscription to `charge_automatically`. The events differ depending on who collects. See [Invoice payment events](/api/main-resources/events-reference/types-of-events#invoice-payment-events). ## Close an invoice you will not collect An `open` invoice stays open until it is paid or you close it. This matters most with `send_invoice`, where unpaid invoices accumulate one per billing period. Choose how to close an invoice based on what happened to the debt: | Situation | Action | Resulting status | | - | - | - | | Your customer paid you outside Fintoc, by bank transfer or cash. | Mark the invoice as paid outside Fintoc. | `paid`, with `external_payment` set to `true` | | The invoice was issued by mistake or your customer no longer owes it. | [Void the invoice](/api/payments-api/invoices/invoices-void). | `void` | | Your customer owes the amount, but you no longer expect to collect it. | [Mark the invoice as uncollectible](/api/payments-api/invoices/invoices-mark-uncollectible). | `uncollectible` | Mark an invoice as uncollectible to write off a debt while keeping a record that your customer owed it. Unlike a voided invoice, an `uncollectible` invoice reflects a real debt that went unpaid. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/invoices/inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe/mark_uncollectible" \ --header "Authorization: YOUR_SECRET_API_KEY" ``` Fintoc returns the `Invoice` object with `status` set to `uncollectible` and emits the `invoice.marked_uncollectible` event: ```json theme={null} { "id": "inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe", "object": "invoice", "attempt_count": 0, "collection_method": "charge_automatically", "created_at": "2026-05-01T12:00:00Z", "currency": "CLP", "customer": "cus_2bVdWyTnGq4PfLs7DkXjRm0CwIo", "default_payment_method": null, "external_payment": false, "hosted_invoice_url": null, "lines": [ { "id": "il_2bVdX0PqJs6RhNu9FmZlTo2EyKq", "object": "line_item", "amount": 30000, "currency": "CLP", "description": "Monthly subscription", "name": "Monthly subscription", "period_end": "2026-06-01T00:00:00Z", "period_start": "2026-05-01T00:00:00Z", "quantity": 1 } ], "metadata": {}, "mode": "live", "next_payment_attempt_at": null, "payments": [], "status": "uncollectible", "subscription": null, "total": 30000 } ``` Marking an invoice as uncollectible has the following restrictions: * The invoice must be `open`. Fintoc returns `409 Conflict` with code `invoice_not_markable_uncollectible` for an invoice in any other status, including one that is already `uncollectible`. * The invoice must have no payment in progress. Fintoc returns `422 Unprocessable Entity` with code `invoice_has_pending_payment` while a payment is pending. Wait for the payment to succeed or fail before you retry. * The change is final. You cannot void, pay, or reopen an `uncollectible` invoice. ## Test invoice creation with status `draft` To test an invoice that Fintoc creates in `draft` status, create a subscription with a line item using the product name `sandbox_draft`: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "subscription", "amount": 350000, "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "payment_method_types": ["pac"], "customer_data": { "tax_id": { "type": "cl_rut", "value": "11.111.111-1" }, "name": "Felipe Castro", "email": "jon@snow.com" }, "line_items": [ { "price_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "sandbox_draft" }, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'subscription', amount: 350000, currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', payment_method_types: ['pac'], customer_data: { tax_id: { type: 'cl_rut', value: '11.111.111-1' }, name: 'Felipe Castro', email: 'jon@snow.com' }, line_items: [ { price_data: { currency: 'CLP', unit_amount: 350000, product_data: { name: 'sandbox_draft' }, recurring: { interval: 'month', interval_count: 1 } }, quantity: 1 } ] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='subscription', amount=350000, currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', payment_method_types=['pac'], customer_data={ 'tax_id': { 'type': 'cl_rut', 'value': '11.111.111-1', }, 'name': 'Felipe Castro', 'email': 'jon@snow.com', }, line_items=[ { 'price_data': { 'currency': 'CLP', 'unit_amount': 350000, 'product_data': { 'name': 'sandbox_draft', }, 'recurring': { 'interval': 'month', 'interval_count': 1, }, }, 'quantity': 1, } ], ) ``` Fintoc creates the `Checkout Session`: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "flow": "subscription", "status": "created", "amount": 350000, "currency": "CLP", "payment_method_types": ["pac"], "customer": { "id": "cus_NffrFeUfNV2Hib", "object": "customer", "name": "Felipe Castro", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "11.111.111-1" } }, "line_items": [ { "price": { "product": { "name": "sandbox_draft", "description": "Fixed-amount monthly plan" }, "currency": "CLP", "unit_amount": 350000, "recurring": { "interval": "month", "interval_count": 1 } }, "quantity": 1 } ], "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235" } ``` Fintoc creates the invoice in `draft` status, so you can edit its items with the [Add lines](/api/payments-api/invoices/invoices-add-lines) endpoint before the invoice leaves `draft`. # Save a payment method for future charges Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/setup-a-payment-method-for-future-charges Save a customer's payment method with a setup Checkout Session, then charge it later on demand by creating an invoice or a Payment Intent. Save a customer's payment method once and charge it later for on-demand or variable-amount payments, without creating a recurring subscription. Unlike the [subscription flow](/guides/payments/accept-recurring-payments), the setup flow does not couple enrollment with recurring billing, so you decide when and how much to charge. Set up a payment method and charge it later in four steps: 1. On your backend, create a Checkout Session with `flow: setup`. 2. Redirect your customer to complete the enrollment at the Fintoc-hosted checkout page. 3. Handle post-session events to save the `payment_method` and `customer`. 4. Charge the saved payment method on demand, by creating an invoice or a Payment Intent. The following diagram shows how the setup flow works: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/631ce18a4aba7161afa8a940208b2248df08d83804b3c1060792ec1e4d58cd54-setup-diagram.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=2456dfcdc845a652cbae71a182a3a9fa) *** ## Create a Checkout Session The [Checkout Session](/api/payments-api/checkout-sessions/checkout-session-object) with the `setup` flow represents your intent to save a payment method for future charges, without creating a recurring subscription. Using your [Secret Key](/guides/home/api-keys), create a Checkout Session on your backend with `flow` set to `setup`: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "setup", "currency": "CLP", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "customer_data": { "tax_id": { "type": "cl_rut", "value": "41.579.263-8" }, "name": "Felipe Castro", "email": "jon@snow.com" }, "metadata": {} }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'setup', currency: 'CLP', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', customer_data: { tax_id: { type: 'cl_rut', value: '41.579.263-8' }, name: 'Felipe Castro', email: 'jon@snow.com' }, metadata: {} }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='setup', currency='CLP', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', customer_data={ 'tax_id': { 'type': 'cl_rut', 'value': '41.579.263-8' }, 'name': 'Felipe Castro', 'email': 'jon@snow.com' }, metadata={} ) ``` After creating the Checkout Session, Fintoc responds with the session details and a `redirect_url`: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "flow": "setup", "status": "created", "currency": "CLP", "customer": { "id": "cus_NffrFeUfNV2Hib", "object": "customer", "email": "jon@snow.com", "metadata": {}, "name": "Felipe Castro", "tax_id": { "type": "cl_rut", "value": "111111111" } }, "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {} } ``` | Parameter | Example | Description | | - | - | - | | `flow` | `setup` | **Required.** Flow type for the session. One of `payment`, `setup`, or `subscription`. Use `setup` to save a payment method without charging. | | `currency` | `CLP` | **Required.** Three-letter ISO 4217 currency code. One of `CLP` or `MXN`. | | `success_url` | `https://merchant.com/success` | **Required.** URL to redirect the customer after a successful enrollment. | | `cancel_url` | `https://merchant.com/cancel` | **Required.** URL to redirect the customer if they cancel the enrollment. | | `payment_method_types` | `["pac"]` | Payment methods available for the enrollment. One or more of `pac` (Chilean direct debit), `mx_direct_debit` (Mexico, `test` mode with `MXN`), or `card`. | | `customer` | `cus_3B2bODrQFje7ZVkT69xyaTSDwXQ` | **Required if no `customer_data`.** ID of an existing `Customer`. | | `customer_data` | `{ tax_id: {...}, ... }` | **Required if no `customer`.** Data for inline customer creation. Send at least one of `email` or `tax_id`. If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `payment_method_options` | `{ pac: { ... } }` | Options specific to each payment method, keyed by values in `payment_method_types` (for example, `pac`). For `pac`, restrict the `sender_account` with `types` (`checking_account`), `institution_id`, or `holder_id`; for `card`, restrict `kinds` (`credit`, `debit`). To apply no restriction, omit the option instead of sending an empty array because an empty array allows nothing. | | `metadata` | `{ "order": "987654321" }` | Set of key-value pairs for storing additional information. | > [!NOTE] > > **Difference from the subscription flow** > > When you create a Checkout Session with `flow: setup`, Fintoc enrolls the customer's payment method and creates a `PaymentMethod`, but does **not** create a `subscription` or schedule any recurring charges. You control when and how much to charge by creating future payment intents. ### Include customer data When creating a Checkout Session for setup, you must include customer information. | Attribute | Type | Description | | - | - | - | | `tax_id` | `object` | **Required if no `email`.** Object that identifies the customer at a fiscal or regulatory level. The `type` is one of `cl_rut` (Chilean tax ID, RUT), `mx_rfc` (Mexican tax ID, RFC), or `custom` (any other identifier), and `value` is the tax identifier as a string. For `custom`, send any non-empty value. Fintoc removes leading and trailing spaces and does not validate its format. See the [Customer object](/api/payments-api/checkout-sessions/checkout-session-object#customer-object). If a `Customer` with the same `tax_id` already exists, the request returns a `409 Conflict` error. To reuse an existing `Customer`, send its `id` in `customer` instead of `customer_data`. | | `name` | `string` | Full name of the customer. | | `email` | `string` | **Required if no `tax_id`.** Email used to notify the customer about the enrollment and charges. | | `metadata` | `object` | Set of key-value pairs for storing additional information. | *** ## Redirect the customer to complete the enrollment Next, redirect the customer to the `redirect_url` from the response. The customer sees the Fintoc-hosted checkout page where they complete the enrollment. After the customer completes the enrollment, Fintoc automatically redirects them to your `success_url` or `cancel_url`, depending on the outcome. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` *** ## Handle post-session events Always use [webhooks](/guides/resources/webhooks-walkthrough) to determine the final outcome. Customers may close the tab, lose connection, or never reach your `success_url`. ### Checkout Session events When the enrollment completes, Fintoc sends a `checkout_session.finished` event with the `customer` and `payment_method` information: ```json theme={null} { "id": "evt_a4xK32BanKWYn", "object": "event", "type": "checkout_session.finished", "data": { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "live", "flow": "setup", "status": "finished", "currency": "CLP", "customer": { "id": "cus_NffrFeUfNV2Hib", "name": "Felipe Castro", "email": "jon@snow.com", "tax_id": { "type": "cl_rut", "value": "111111111" } }, "payment_method": "pm_NffrFeUfNV2Hib", "metadata": {}, "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel" } } ``` ### Payment Method events Fintoc also sends a `payment_method.activated` event. The event's `data` field contains a `PaymentMethod` like this: ```json theme={null} { "id": "pm_NffrFeUfNV2Hib", "object": "payment_method", "created_at": "2021-10-15T15:22:11.474Z", "customer": "cus_NffrFeUfNV2Hib", "mode": "live", "pac": { "account_holder_id": "111111111", "account_number": "000000000000", "account_type": "checking_account", "institution": { "id": "cl_banco_falabella", "country": "cl", "name": "Banco Falabella" }, "status": "active" }, "type": "pac" } ``` Store both the `customer` ID and the `payment_method` ID. You need them to create charges later. ### Events summary You should subscribe to all the following post-session events: | Event | Description | Recommended action | | :- | :- | :- | | `checkout_session.finished` | Session successfully completed. Method enrolled. | Store `customer` + `payment_method`. | | `checkout_session.expired` | Session expired before the customer completed enrollment. | Allow the customer to retry. | | `payment_method.activated` | Payment method is active and ready for charges. | Create charges against this method when needed. | | `payment_method.canceled` | Payment method is canceled and not available for charges. | Stop creating charges against the method. | *** ## Create a charge against the saved payment method Once the payment method is `active`, you can charge it in two ways: * **Create an invoice** and let Fintoc collect it. The invoice records what your customer owes, keeps the history of every charge attempt, and gives you a payment link to fall back on. Use it when the charge settles a debt, including recurring collection. * **Create a Payment Intent** directly. Use it for a one-off charge that you don't need to track as a debt. Both paths end in a `payment_intent`. The difference is where the `payment_intent` lives: a charge made through an invoice stays anchored to the invoice, so you can retry it, switch payment methods, and reconcile it against the amount owed. ### Charge the payment method through an invoice Collecting an invoice takes two calls: you create the invoice, and then you finalize it. Fintoc never finalizes an invoice you create yourself. ![fintoc-invoice-creation-diagram](https://mintcdn.com/fintoc-49b8bee8/3flF6A2hSLiRffRb/images/invoice-flow-diagram.png?fit=max\&auto=format\&n=3flF6A2hSLiRffRb\&q=85\&s=b2611362498d3d40a09b5a0498bb1726) #### 1) Create the invoice Create the [Invoice](/api/payments-api/invoices/invoice-object) for the `customer`, with `default_payment_method` set to the payment method you saved. Fintoc's Node and Python libraries don't create invoices. Call the [Create an invoice](/api/payments-api/invoices/invoices-create) endpoint over HTTP, as in this `curl` example. **Server** ```bash curl theme={null} curl --request POST "https://api.fintoc.com/v2/invoices" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_NffrFeUfNV2Hib", "default_payment_method": "pm_NffrFeUfNV2Hib", "collection_method": "charge_automatically", "lines": [ { "name": "Monthly plan", "amount": 150000, "currency": "CLP", "quantity": 1 } ], "metadata": { "order_id": "order_98765" } }' ``` | Parameter | Example | Description | | - | - | - | | `customer` | `cus_NffrFeUfNV2Hib` | **Required.** ID of the `Customer` the invoice bills. | | `lines` | `[{ "name": "Monthly plan", "amount": 150000, "currency": "CLP", "quantity": 1 }]` | **Required.** Line items to include in the invoice. Each line needs `name`, `amount`, `currency`, and `quantity`; `amount` is in the smallest currency unit. All lines share the same currency, and their sum becomes the invoice `total`. | | `default_payment_method` | `pm_NffrFeUfNV2Hib` | The saved payment method Fintoc charges when you finalize the invoice. Required with `charge_automatically`. Must belong to `customer`. | | `collection_method` | `charge_automatically` | How Fintoc collects the invoice. One of `charge_automatically`, which charges `default_payment_method` on finalization, or `send_invoice`, which leaves the invoice open for you to collect. Defaults to `charge_automatically`. | | `metadata` | `{ "order_id": "order_98765" }` | Set of key-value pairs for storing additional information. Use `metadata` or the invoice `id` to reconcile the charge, instead of the amount. | Fintoc responds with the invoice in `draft` status: ```json theme={null} { "id": "inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe", "object": "invoice", "attempt_count": 0, "collection_method": "charge_automatically", "created_at": "2026-08-10T15:22:11.474Z", "currency": "CLP", "customer": "cus_NffrFeUfNV2Hib", "default_payment_method": "pm_NffrFeUfNV2Hib", "external_payment": false, "hosted_invoice_url": null, "lines": [ { "id": "il_2bVdX0PqJs6RhNu9FmZlTo2EyKq", "object": "line_item", "name": "Monthly plan", "description": null, "amount": 150000, "currency": "CLP", "period_end": null, "period_start": null, "quantity": 1 } ], "metadata": { "order_id": "order_98765" }, "mode": "live", "next_payment_attempt_at": null, "payments": [], "status": "draft", "subscription": null, "total": 150000 } ``` A `draft` invoice charges nothing. Use the `draft` status to review the amount or change the items with [Add lines](/api/payments-api/invoices/invoices-add-lines) and [Update a line item](/api/payments-api/invoice-line-items/invoice-lines-update) before you collect. #### 2) Finalize the invoice to charge it [Finalize the invoice](/api/payments-api/invoices/invoices-finalize) to move it to `open`. Because `collection_method` is `charge_automatically`, Fintoc charges `default_payment_method` after finalization: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/invoices/inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe/finalize" \ --header "Authorization: YOUR_SECRET_API_KEY" ``` The charge is asynchronous: the invoice stays `open` with a `pending` payment until the payment resolves. Track the outcome with `invoice.payment_succeeded` or `invoice.payment_failed`; Fintoc sends those invoice events alongside `payment_intent.succeeded` or `payment_intent.failed`. #### 3) Retry a failed charge A failed charge leaves the invoice `open`, so the amount your customer owes stays open on the invoice. Retry the charge with [Pay an invoice](/api/payments-api/invoices/invoices-pay), against the same payment method or against another active payment method of the same customer: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/invoices/inv_2bVdWxLpzXq8RkNcM3JtUv9AhTe/pay" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "payment_method": "pm_OtherMethodOfTheCustomer" }' ``` Omit `payment_method` to charge the invoice's `default_payment_method`. Fintoc appends every attempt to the invoice's `payments` array with its own `payment_intent` and `status`, so the invoice holds the full history of how you tried to collect it. To settle an invoice you collected outside Fintoc, by bank transfer or in cash, call the same endpoint with `external_payment` set to `true`. Fintoc moves the invoice to `paid` without charging anything, and reports `external_payment` as `true`. #### Collect the invoice without charging the saved method To let your customer pay instead of charging them, create the invoice with `collection_method` set to `send_invoice`. Fintoc then leaves the invoice `open` when you finalize it, instead of charging it, and `default_payment_method` becomes optional: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/invoices" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_NffrFeUfNV2Hib", "collection_method": "send_invoice", "lines": [ { "name": "Monthly plan", "amount": 150000, "currency": "CLP", "quantity": 1 } ] }' ``` Call [Finalize an invoice](/api/payments-api/invoices/invoices-finalize) to move it to `open`. Once the invoice reaches `open`, its `hosted_invoice_url` points to a Fintoc-hosted payment page. Your customer can pay there with the payment methods enabled on your organization's account, without needing a saved payment method. Send that link to your customer through your own channel, such as email or WhatsApp. Fintoc does not contact your customer through any channel. #### Handle invoice events Subscribe to the following events to track the invoice: | Event | Description | Recommended action | | - | - | - | | `invoice.created` | Sent when you create the invoice. | Store the invoice `id` against your own record of the amount owed. | | `invoice.finalized` | Sent when the invoice becomes `open` and ready for payment. | Store the `hosted_invoice_url`. Send it to your customer only if you are not charging automatically, or if the charge fails. | | `invoice.payment_created` | Sent when a payment on the invoice starts, either from your charge or from your customer using the `hosted_invoice_url`. | Treat the event as informational. An invoice accepts only one payment at a time. | | `invoice.payment_succeeded` | Sent when Fintoc collects the invoice payment. | Confirm the payment to your customer. | | `invoice.paid` | Sent on every transition to `paid`, whether Fintoc collected the invoice or you marked it as paid outside Fintoc. | Settle the amount owed in your records. Read `external_payment` to tell whether the money went through Fintoc. | | `invoice.payment_failed` | Sent when a payment attempt on the invoice fails. | Retry with [Pay an invoice](/api/payments-api/invoices/invoices-pay), or send the `hosted_invoice_url`. | | `invoice.voided` | Sent when you [void the invoice](/api/payments-api/invoices/invoices-void) and Fintoc disables its `hosted_invoice_url`. | Update your records. | ### Charge the payment method with a Payment Intent Charge the saved `payment_method` directly by creating a Payment Intent with the `payment_method` ID: **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/payment_intents" \ --header "Authorization: YOUR_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 150000, "currency": "CLP", "payment_method": "pm_NffrFeUfNV2Hib", "metadata": { "order_id": "order_98765" } }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_SECRET_API_KEY'); const paymentIntent = await fintoc.v2.paymentIntents.create({ amount: 150000, currency: 'CLP', payment_method: 'pm_NffrFeUfNV2Hib', metadata: { order_id: 'order_98765' } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_SECRET_API_KEY') payment_intent = client.v2.payment_intents.create( amount=150000, currency='CLP', payment_method='pm_NffrFeUfNV2Hib', metadata={ 'order_id': 'order_98765' } ) ``` | Parameter | Example | Description | | - | - | - | | `amount` | `150000` | **Required.** A positive integer representing the amount to charge in the smallest currency unit (for example, `150000` for `CLP 150000`, since CLP has no minor unit, or `10000` for `MXN 100.00`). | | `currency` | `CLP` | **Required.** Three-letter ISO 4217 currency code. One of `CLP` or `MXN`. | | `payment_method` | `pm_NffrFeUfNV2Hib` | **Required.** The saved payment method ID. | | `metadata` | `{ "order_id": "order_98765" }` | Set of key-value pairs for storing additional information. | Fintoc responds with the created Payment Intent: ```json theme={null} { "id": "pi_34i0T5AWRfIDMOJnhq9BgxXUiyt", "object": "payment_intent", "status": "created", "amount": 150000, "currency": "CLP", "customer": "cus_NffrFeUfNV2Hib", "payment_method": "pm_NffrFeUfNV2Hib", "metadata": { "order_id": "order_98765" } } ``` ### Handle payment events Fintoc sends these events for every charge, whether you created the charge through an invoice or as a standalone Payment Intent. Subscribe to them to track the payment outcome: | Event | Description | Recommended action | | - | - | - | | `payment_intent.succeeded` | The charge was successful. | Fulfill the order and confirm to the customer. | | `payment_intent.failed` | The charge failed. | Retry the charge or ask for another payment method. | *** ## Test your integration Using your [test mode API Secret Key](/guides/resources/test-mode), create Checkout Sessions that simulate the full setup and payment flow without moving any money. ### 1) Create a setup Checkout Session using test credentials Create a Checkout Session with `flow: setup` using your test mode Secret Key. Complete the enrollment flow on the Fintoc-hosted page using the following credentials: **Test credentials:** #### PAC * Username (RUT): `41.579.263-8` * Password: `jonsnow` Select the account based on the final outcome you want to test: | Account number | Type of MFA | Correct code | | :- | :- | :- | | 813990168 | Security device | `000000` | | 422159212 | Mobile Application - Success | `N/A` | | 5233137377 | Mobile Application - Failure | `N/A` | | 170086177 | SMS | `0000` | | 746326042 | Coordinate Card | `['00', '00', '00']` | #### Card Use these test cards for card setup flows in Chile: | Card number | Expiration date | CVV | Holder name | 3DS challenge code | Final result | | - | :- | :- | :- | :- | - | | 4111111111111111 | Any future date | Any | Any | - | ✅ Succeeded | | 4456524869770255 | Any future date | Any | Any | 1234 | ✅ Succeeded if code is correct | | 4574441215190335 | Any future date | Any | Any | - | ❌ Failed due to invalid credentials | | 4349003000047015 | Any future date | Any | Any | - | ❌ Failed due to rejected transaction | ### 2) Verify the saved payment method After completing the test enrollment, you should receive the `checkout_session.finished` and `payment_method.activated` webhook events. Verify that: * The `payment_method` ID is present in the event payload. * The `customer` ID matches the customer you enrolled. ### 3) Create a test charge against the saved method Using the `customer` and `payment_method` IDs from step 2, create a Payment Intent against the saved method. Verify that: * You receive the `payment_intent.succeeded` event. * The amount matches what you sent. * The payment method used is the saved PAC or card. Then test the invoice path with the same IDs: create an invoice with `default_payment_method` set to the saved method, finalize it, and verify that: * You receive `invoice.created`, `invoice.finalized`, `invoice.payment_created`, `invoice.payment_succeeded`, and `invoice.paid`, along with `payment_intent.succeeded`. * The invoice ends in `paid` status, with the attempt recorded in `payments` and your `metadata` persisted. > [!NOTE] > > To save a Mexican bank account or debit card in `test` mode, follow [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico). # Update the payment method on a subscription Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/update-the-payment-method-on-a-subscription Change the payment method a Fintoc subscription charges, with a re-enrollment link for your customer or directly through the API. When a customer's payment method fails, or when the customer wants to switch payment methods, you can update the payment method associated with a subscription. The update affects future billing cycles only. It does not charge open invoices. Collect open invoices separately using each invoice's `hosted_invoice_url`, one per invoice. Two flows let you update a subscription's payment method: * **Case A (customer-initiated):** Send the customer a new enrollment link. Use this when the customer must authorize a new Chilean automatic debit (PAC) mandate or enter new card details. * **Case B (merchant-initiated):** Associate an already-active payment method directly through the API, with no customer interaction. ## Case A: Send a re-enrollment link Create a `CheckoutSession` with `flow: "setup"` and pass the existing subscription ID in `subscription`. The customer opens the link and enrolls a new payment method. For cards, Fintoc associates the payment method with the subscription when enrollment completes. For PAC, Fintoc associates the payment method once the mandate activates. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "flow": "setup", "currency": "CLP", "subscription": "sub_456789abcdef", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "customer": "cus_01234567", "payment_method_types": ["pac"] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ flow: 'setup', currency: 'CLP', subscription: 'sub_456789abcdef', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/cancel', customer: 'cus_01234567', payment_method_types: ['pac'] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( flow='setup', currency='CLP', subscription='sub_456789abcdef', success_url='https://merchant.com/success', cancel_url='https://merchant.com/cancel', customer='cus_01234567', payment_method_types=['pac'], ) ``` Fintoc responds with the `CheckoutSession` object: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "flow": "setup", "status": "created", "currency": "CLP", "mode": "test", "subscription": "sub_456789abcdef", "customer": { "id": "cus_01234567", "object": "customer", "name": "Test Customer 1", "email": "jon@snow.com", "metadata": {}, "tax_id": { "type": "cl_rut", "value": "11.111.111-1" } }, "payment_method_types": ["pac"], "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235" } ``` Redirect the customer to `redirect_url` so the customer completes the enrollment. ### PAC activation window For PAC, bank confirmation takes approximately 5 business days. The new payment method stays in `pending` status during this window, and Fintoc has not yet executed the swap. `checkout_session.finished` signals that the customer completed the enrollment flow, not that the swap occurred. Wait for `subscription.payment_method_updated` before you treat the new payment method as active. To check the activation state while the mandate is pending, call `GET /v2/payment_methods/{id}` and read `pac.status`: ```json theme={null} { "id": "pm_000000000001", "object": "payment_method", "customer": "cus_01234567", "type": "pac", "pac": { "account_holder_id": "11.111.111-1", "account_number": "000000000000", "account_type": "checking_account", "institution": { "id": "cl_banco_de_chile", "country": "cl", "name": "Banco de Chile" }, "status": "pending" } } ``` ### Handle re-enrollment events Subscribe to the following events when you update a subscription's payment method through a re-enrollment link: | Event | Description | Action | | - | - | - | | `checkout_session.finished` | The customer completed the enrollment flow. | Store the new `payment_method` ID. For cards the swap already occurred; for PAC, wait for `subscription.payment_method_updated`. | | `checkout_session.expired` | The session expired before the customer completed enrollment. | Create a new session and send the customer the updated link. | | `subscription.payment_method_updated` | The bank confirmed the new mandate. The subscription now charges against the new payment method. | Resume normal billing. Collect any open invoices using each invoice's `hosted_invoice_url`. | | `subscription.payment_method_update_failed` | The bank rejected the mandate activation. The subscription keeps its previous payment method. | Create a new session so the customer can re-enroll. Collect open invoices using each invoice's `hosted_invoice_url`. | ## Case B: Associate an existing payment method If the customer already has an active payment method on file, associate the payment method with a subscription directly, without a new enrollment link. ### Swap the payment method on an existing subscription Call `PATCH /v2/subscriptions/{id}` with the ID of the active payment method. The payment method must belong to the same customer as the subscription. **Server** ```bash theme={null} curl --request PATCH "https://api.fintoc.com/v2/subscriptions/sub_456789abcdef" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "payment_method": "pm_000000000001" }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const subscription = await fintoc.v2.subscriptions.update('sub_456789abcdef', { payment_method: 'pm_000000000001' }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') subscription = client.v2.subscriptions.update( 'sub_456789abcdef', payment_method='pm_000000000001', ) ``` Fintoc returns the updated `Subscription`: ```json theme={null} { "id": "sub_456789abcdef", "object": "subscription", "billing_cycle_anchor": "2025-08-01T00:00:00Z", "collection_method": "charge_automatically", "created_at": "2025-08-01T12:00:00Z", "customer": "cus_01234567", "items": [ { "id": "si_89abcdef0123", "object": "subscription_item", "price": { "currency": "CLP", "product": { "name": "Pro Plan" }, "recurring": { "interval": "month", "interval_count": 1 }, "unit_amount": 15000 }, "quantity": 1 } ], "metadata": {}, "mode": "test", "payment_method": "pm_000000000001", "status": "active", "trial_end": null } ``` The payment method's mandate is already active, so the swap is immediate. The `payment_method` value in the response points to the new payment method. Fintoc also emits `subscription.payment_method_updated`. ### Create a new subscription with an existing payment method Creating a subscription against a payment method the customer already has is not an update, so it lives with the rest of subscription creation. Pass the `payment_method` to [Create a subscription](/api/payments-api/subscriptions/subscriptions-create), as described in [Charge automatically against a payment method](/guides/payments/accept-recurring-payments#charge-automatically-against-a-payment-method). ## Updating the payment method on a subscription does not pay open invoices Updating the payment method changes which method Fintoc charges for future billing cycles. It does not pay open invoices from previous cycles. If the subscription has open invoices when the swap occurs, collect them separately using each invoice's `hosted_invoice_url`, one per invoice. ## Edge cases **One update at a time:** Only one payment method update can be in progress per subscription. A second attempt while a PAC mandate is `pending` returns a `payment_method_update_in_progress` error (`409 Conflict`). **Billing cycle during the activation window:** If a billing cycle anchor falls while a new PAC mandate is still `pending`, Fintoc creates the invoice in `open` status without an automatic charge. Collect the invoice using its `hosted_invoice_url`. **Cancellation during activation:** If you cancel the subscription while a PAC mandate awaits bank confirmation, the swap does not execute. Fintoc creates and stores the new payment method on the customer's record, but does not associate the payment method with any subscription. ## Test your integration Using your [test mode Secret Key](/guides/resources/test-mode), run both flows against a test subscription without moving money. ### 1) Test the re-enrollment link Create the setup `Checkout Session` with the `subscription` of an existing test subscription, then complete the enrollment on the Fintoc-hosted page with the test credentials listed in [Save a payment method for future charges](/guides/payments/accept-recurring-payments/setup-a-payment-method-for-future-charges). Verify that: * You receive `checkout_session.finished`, carrying the new `payment_method` ID. * You receive `subscription.payment_method_updated`, and your integration treats the new payment method as active only after this event. * [Get a subscription](/api/payments-api/subscriptions/subscriptions-get) reports the new `payment_method`. Do not treat the swap as done on `checkout_session.finished` alone. That is the failure the [PAC activation window](#pac-activation-window) describes. ### 2) Test the API swap Enroll a second payment method for the same test customer, then swap it in with [Update a subscription](/api/payments-api/subscriptions/subscriptions-update). Verify that: * The response reports the new `payment_method` and keeps the subscription `active`. * You receive `subscription.payment_method_updated`. * A second update while another one is still in progress returns `payment_method_update_in_progress` with `409 Conflict`. # Buy now, pay later (Chile only) Source: https://docs.fintoc.com/guides/payments/buy-now-pay-later Offer Buy Now Pay Later (BNPL) on Fintoc-hosted checkout in Chile so customers can split a payment across installments funded by a third-party lender. You can accept the method of Buy Now Pay Later (installments payments without a credit card) from customers in Chile by using the Checkout Session API. Customers will have an offer to pay in installments by subscribing for the automatic charge on their bank of each installment related to the payment. Our Buy Now Pay Later product is in partnership with [Banca.me](https://www.banca.me/). ## Create a Buy Now Pay Later payment Using your secret key, create a `Checkout Session` on your server with an `amount`, `currency` (`CLP` only for installment payments), `success_url`, `cancel_url`, and `payment_method_types: ["installments"]`: ```bash theme={null} curl --request POST \ --url https://api.fintoc.com/v2/checkout_sessions \ --header 'Authorization: YOUR_TEST_SECRET_API_KEY' \ --header 'content-type: application/json' \ --data ' { "amount": 100000, "currency": "CLP", "cancel_url": "https://merchant.com/987654321", "success_url": "https://merchant.com/success", "customer_email": "customer@example.com", "metadata": { "order": "123456" }, "payment_method_types": ["installments"] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 100000, currency: 'CLP', cancel_url: 'https://merchant.com/987654321', success_url: 'https://merchant.com/success', customer_email: 'customer@example.com', metadata: { order: '123456' }, payment_method_types: ['installments'] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=100000, currency='CLP', cancel_url='https://merchant.com/987654321', success_url='https://merchant.com/success', customer_email='customer@example.com', metadata={ 'order': '123456' }, payment_method_types=['installments'] ) ``` | Parameter | Example | Explanation | | - | - | - | | `amount` | `100000` | Positive integer in the smallest currency unit. For CLP, `100000` represents CLP 100000. The minimum is CLP 20,000 and the maximum is CLP 400,000. Contact Fintoc if your average ticket exceeds this range. | | `currency` | `CLP` | Three-letter ISO 4217 currency code. Must be `CLP` for installment payments. | | `cancel_url` | `https://merchant.com/987654321` | URL to redirect the user in case they decide to cancel the payment and return to your website. | | `success_url` | `https://merchant.com/success` | URL to redirect the user in case of payment succeeded. | | `customer_email` | `customer@example.com` | **Required for `installments`.** Customer email linked to the Checkout Session. | | `payment_method_types` | `["installments"]` | Payment methods available to the customer. `installments` represents the Buy Now Pay Later method and must be the only method set. **You cannot include more than one payment method.** | | `metadata` | `{ "order": "123456" }` | Optional set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. | > [!NOTE] > > **Installments Payment Only Available via the Redirect Page Flow** > > To accept installments payments you must use the integration via a [Redirect Page](/guides/payments/accept-a-payment#redirect-the-customer-to-complete-the-payment) where you will redirect users to a Fintoc-hosted payment page. > > After completing the payment, they’ll be automatically redirected back to your site on the `success_url` or `cancel_url`, based on the outcome of the payment. ## Response when creating a Checkout Session for an installments payment After making the request, Fintoc responds with the Checkout Session with the status `created` including the `redirect_url` you use to redirect your user to complete the payment: ```json theme={null} { "id": "cs_li5531onlFDi235", "created_at": "2025-02-15T15:22:11.474Z", "object": "checkout_session", "expires_at": "2025-02-15T15:37:11.474Z", "mode": "live", "status": "created", "metadata": { "order": "123456" }, "payment_method_types": ["installments"], "currency": "CLP", "amount": 100000, "cancel_url": "https://merchant.com/987654321", "success_url": "https://merchant.com/success", "redirect_url": "https://pay.fintoc.com/payment?checkout_session=cs_li5531onlFDi235" } ``` | Parameter | Example | Explanation | | :- | :- | :- | | `redirect_url` | `https://pay.fintoc.com/payment?checkout_session=cs_li5531onlFDi235` | URL to redirect the user to complete the payment | ## Handle post-payments events Once a Checkout Session finishes, you handle the payment result in your frontend and complete the payment in your backend. For your frontend you use `success_url` and `cancel_url`, and for your backend you use the events sent by webhooks. Fintoc sends a `checkout_session.finished` event when the payment completes. [Follow the webhook guide](/guides/resources/webhooks-walkthrough) to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow. You should handle the following events: | Event | Description | Action | | :- | :- | :- | | `checkout_session.finished` | Sent when a payment associated to a Checkout Session reaches a final state | Complete the order based on the payment's final status | | `checkout_session.expired` | Sent when a session expires | Offer the customer another attempt to pay. | ## Test your integration To simulate a successful or failed Buy Now Pay Later Payment, you can use one of the following RUT numbers during the payment process: | **RUT number** | **Final Result** | | - | - | | Any number, except 11111111-1, 44444444-4 or 22222222-2 | ✅ Succeeded | | 11111111-1 | ❌ Failed due to no available credit offer | | 44444444-4 | ❌ Failed due to an active credit | | 22222222-2 | ❌ Failed during the credit contract signing step | In test mode, the payment process does not include the PAC subscription step. So when accessing the `redirect_url`, the steps will be: 1. Input RUT number 2. View and select an installment plan offer: In test mode, only one installment option is available (a single payment of 103,103 CLP), regardless of the amount specified when creating the Checkout Session. 3. Confirm mobile number via SMS code. In test mode you can input any mobile number to proceed, since you can use the following codes: 1. Any code except 123456 to proceed to the next step. 2. 123456 to simulate a failure at this step. 4. Sign the credit contract: you will receive a code at the `customer_email` you set when creating the Checkout Session. Use this code to proceed to a successful payment. 5. Payment successful: you will be redirected to the `success_url` and receive the `checkout_session.finished` event. ## Checkout UX guideline To ensure a good experience and understanding for your users, add the Buy Now Pay Later button on your checkout using the images below depending on your configuration: | Image | Description | HTML | | :- | :- | :- | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/17bae8e8816db69bd877063cd00399f76f844e928122a56a9c004365ed5f77b1-bnpl_bancame_fintoc_combo_cl_light.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=f47250edaaa7f5dbb9dad0233f338d63) | Light button to use with the text "Paga en cuotas sin Tarjeta" | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/eef6f427a77ff194e937374d567ec5e1da3c21685251c5ae360772c9b631e17f-bnpl_banca.me_fintoc_combo_cl_dark.svg?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=843e52997e6e3657546a8c9edc4a4965) | Dark button to use with the text "Paga en cuotas sin Tarjeta" | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/8d52ee81db5137549174d3bac6ff2e7a3af594531c9cb3f6b74d98625c73714b-bancame_fintoc_light.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=13c1e2aa1a5b541a47a37171de1d7bd7) | Light logos to use with the text + bank logos image | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/b169eac9b4e51b5e9ca676b2e3e0de0edd466da1934eea83dbde341b5ac64f19-bancame_fintoc_dark.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=7aabafb0908543e7d707ad2026c44120) | Dark logos to use with the text + bank logos image | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/0b5270387120f15d40535dd93a832582ad73a08652f388737be1296515c5e179-bnpl_fintoc_combo_cl_light.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=0bb797d662848bf6ff58ec443de3e576) | Light text + bank logos to use with the logos | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/368c60ba72d3fa0b09935231a3c6fc138ff9c5e4767897668425e88fdd985d09-bnpl_fintoc_combo_cl_dark1.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=1b53c79227f1f2d898c0f41ca4c6b2bc) | Dark text + bank logos to use with the logos | `` | > [!NOTE] > > **Make sure the Buy Now, Pay Later option is hidden for amounts below the minimum.** > > Since the minimum amount for installment payments is CLP 20,000, you should ensure that the Buy Now, Pay Later button is not displayed at checkout for orders below this threshold. This helps avoid a poor user experience and potential drop in conversion rates. # Accept cash payments in Mexico Source: https://docs.fintoc.com/guides/payments/cash-payment-direct-api Create a cash Payment Intent with the Fintoc API to accept cash payments in Mexico at convenience stores, and reconcile them via webhook. You can accept cash payments from customers in Mexico. Customers pay by providing a reference (number or barcode) at more than 13,000 available locations. Fintoc notifies you after the customer completes the payment. You can offer cash in three ways: * **Payment Links**: If your organization has cash enabled, your [Payment Links](/guides/payments/payment-links) offer cash automatically. * **Checkout Sessions**: Add `cash` to `payment_method_types` when you create an `MXN` [Checkout Session](/guides/payments/accept-a-payment). Your customer chooses to pay in cash on the Fintoc-hosted checkout page. * **Payment Intent API**: Create a cash `PaymentIntent` directly and show the reference to your customer, as described in this guide. ## Offer cash in a Checkout Session Include `cash` in `payment_method_types` on its own, or combine it with `card` and `bank_transfer`. You can't combine `cash` with `installments`. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 250000, "currency": "MXN", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "payment_method_types": ["card", "bank_transfer", "cash"] }' ``` Fintoc responds with the session object, including `cash` in `payment_method_types`: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 250000, "currency": "MXN", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/cancel", "redirect_url": "https://pay.fintoc.com/checkout/cs_li5531onlFDi235", "metadata": {}, "payment_method_types": [ "card", "bank_transfer", "cash" ] } ``` To have Fintoc send the cash voucher to your customer, include `customer_email` or `customer_phone` (E.164 format, for example `+525512345678`) when you create the session. You can also set `payment_method_options.cash.notification_preferences` with the same options described in [Configure voucher notifications](#configure-voucher-notifications). Fintoc copies the phone number and preferences to the cash payment when your customer chooses cash. If `customer_phone` isn't in E.164 format, Fintoc returns an `invalid_phone` error. If your customer's card or bank transfer payment fails and `cash` is available in the session, your customer can retry the payment in cash from the same checkout. To finish the integration, follow the [Accept a payment](/guides/payments/accept-a-payment) guide. ## Offer cash in a Payment Link If your organization has cash enabled, every `MXN` [Payment Link](/guides/payments/payment-links) you create offers cash. You don't need to send any extra parameter. Your customer sees a **Paga en efectivo** option next to the other payment methods and can generate a voucher to pay at the store. Fintoc doesn't show the cash option when: * No store accepts the Payment Link's amount. * Your organization's checkout session lasts less than the time your customer needs to pay in cash. ## Create a payment Using your secret key, create a `PaymentIntent` on your server with an `amount`, `currency` (`MXN` only for cash payments), and `payment_type: "cash"`. ```bash theme={null} curl --request POST \ --url https://api.fintoc.com/v1/payment_intents \ --header 'Authorization: YOUR_TEST_SECRET_API_KEY' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data '{ "amount": 2476, "currency": "MXN", "customer_email": "name@example.com", "customer_phone": "+525512345678", "payment_type": "cash", "metadata": { "order": "987654321" }, "expires_at": "2025-12-18T23:59:59" }' ``` ```javascript Node theme={null} // Install Fintoc's Node SDK before running this example: https://github.com/fintoc-com/fintoc-node const paymentIntent = await fintoc.paymentIntents.create({ amount: 2476, currency: 'MXN', customer_email: 'name@example.com', customer_phone: '+525512345678', payment_type: 'cash', expires_at: '2025-12-18T23:59:59', metadata: { order: '987654321' } }); ``` ```python theme={null} # Install Fintoc's Python SDK before running this example: https://github.com/fintoc-com/fintoc-python payment_intent = client.payment_intents.create( amount=2476, currency='MXN', customer_email='name@example.com', customer_phone='+525512345678', payment_type='cash', expires_at='2025-12-18T23:59:59', metadata={ 'order': '987654321' } ) ``` | Parameter | Example | Explanation | | - | - | - | | `amount` | `2476` | Positive integer in the smallest currency unit. For MXN, `2476` represents MXN 24.76. The minimum for cash payments is `2000` (MXN 20.00). | | `currency` | `MXN` | Three-letter ISO 4217 currency code. Cash payments support `MXN`. | | `payment_type` | `cash` | Payment type for the `PaymentIntent`. Use `cash` for cash payments. | | `customer_email` | `name@example.com` | Optional email address of your customer. Fintoc can send the voucher to this address. | | `customer_phone` | `+525512345678` | Optional phone number of your customer in E.164 format. Fintoc can send the voucher to this number by WhatsApp. Fintoc ignores values that aren't in E.164 format. | | `payment_type_options.cash.notification_preferences` | `{ "channels": ["email", "phone"] }` | Optional settings that control how Fintoc sends the voucher to your customer. See [Configure voucher notifications](#configure-voucher-notifications). | | `metadata` | `{ "order": "987654321" }` | Optional set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. | | `expires_at` | `2025-12-18T23:59:59` | Optional ISO timestamp (UTC) that indicates when the payment will expire and no longer be available for the consumer to be paid. By default, payments expire after 3 days. | ## Response when creating a Payment Intent for a cash payment After making the request, Fintoc responds with the Payment Intent with the status `created`, including `payment_type_options.cash` with the cash payment reference: ```json theme={null} { "id": "pi_BO381oEATXonG6bj", "object": "payment_intent", "amount": 2476, "currency": "MXN", "status": "created", "transaction_date": "2025-12-15T15:24:15.474Z", "metadata": { "order": "987654321" }, "error_reason": null, "mode": "live", "expires_at": "2025-12-18T05:59:59.000Z", "payment_type": "cash", "payment_type_options": { "cash": { "reference_number": "6614622682371910296083739445", "barcode_url": "https://assets.fintoc.com/cash_assets/sandbox_barcode", "voucher_url": "https://cash.fintoc.com/voucher/6614622682371910296083739445", "notification_preferences": { "channels": ["phone"], "send_voucher": true, "send_reminders": true } } }, "created_at": "2025-12-15T15:23:11.474Z" } ``` | Parameter | Example | Explanation | | :- | :- | :- | | `voucher_url` | `https://cash.fintoc.com/voucher/6614622682371910296083739445` | The URL for the voucher with instructions on how to complete the payment. | | `barcode_url` | `https://assets.fintoc.com/cash_assets/sandbox_barcode` | The URL for the barcode image of the reference number. | | `reference_number` | `6614622682371910296083739445` | Cash payment reference number. | | `notification_preferences` | `{ "channels": ["phone"], "send_voucher": true, "send_reminders": true }` | The voucher notification settings Fintoc applies to the payment, including the defaults for any value you didn't send. | ### Share the reference and instructions to pay with your customer After creating the payment, share the voucher with your customer for clear instructions on how to complete the payment at one of the available locations. > [!NOTE] > > **Fintoc can send the voucher automatically to your customer** > > When you create a cash payment through the API, Fintoc sends the voucher as soon as the payment is created. Fintoc sends it by email to `customer_email` and by WhatsApp to `customer_phone`, depending on the channels in `notification_preferences`. Fintoc doesn't send the voucher if you turned off voucher notifications in your preferences or if your account suppresses customer communications. In `test` mode, Fintoc also sends real messages, so use an email address and phone number you control. > > You can still share the voucher through your own channels or build your own instructions with the fields below. ### Configure voucher notifications Use `notification_preferences` to choose how Fintoc sends the voucher to your customer. Send it in `payment_type_options.cash` when you create a Payment Intent: ```json theme={null} { "amount": 2476, "currency": "MXN", "payment_type": "cash", "customer_email": "name@example.com", "customer_phone": "+525512345678", "payment_type_options": { "cash": { "notification_preferences": { "channels": ["email", "phone"], "send_voucher": true } } } } ``` | Parameter | Type | Explanation | | :- | :- | :- | | `channels` | array of strings | Channels Fintoc uses to send the voucher. Accepts `email` and `phone`. If you omit it, Fintoc uses `phone` when you send `customer_phone`. Otherwise, Fintoc uses `email` when you send `customer_email`. | | `send_voucher` | boolean | Whether Fintoc sends the voucher when the payment is created. Defaults to `true` when you send `customer_email` or `customer_phone`. | | `send_reminders` | boolean | Whether Fintoc sends payment reminders while the payment is pending. See [Payment reminders](#payment-reminders). Defaults to `true` when you send `customer_email` or `customer_phone`. | Fintoc validates the preferences when you create the payment: * If `channels` includes `email` without `customer_email`, or `phone` without `customer_phone`, Fintoc returns a `missing_parameter` error. * If `send_voucher` or `send_reminders` is `true` and you don't send any contact, Fintoc returns a `missing_parameter` error. * If `channels` is empty or includes a value other than `email` or `phone`, Fintoc returns an `invalid_param_value` error. To send the voucher only by email even if you have the customer's phone, set `channels` to `["email"]`. To stop Fintoc from sending the voucher for a payment, set `send_voucher` to `false`. #### Payment reminders When `send_reminders` is `true`, Fintoc reminds your customer to pay a pending cash payment. Fintoc sends reminders at 10:00 and 19:00 (Mexico City time) through the same `channels` it uses for the voucher. Your customer receives up to 2 reminders per channel. Fintoc doesn't send a reminder when: * The payment is in `test` mode. * The payment was created less than 6 hours ago. * The payment expires in less than 30 minutes. * Your account suppresses customer communications. To turn off reminders for a payment, set `send_reminders` to `false`. Example of a cash payment voucher: ![Cash payment voucher with the amount, available stores, and barcode.](https://mintcdn.com/fintoc-49b8bee8/3f51gOnwUSpWMLlq/images/cash-payment-voucher.svg?fit=max\&auto=format\&n=3f51gOnwUSpWMLlq\&q=85\&s=2f22c09bd9a988ff31692aafe51d8557) If you build your own payment instructions, use `barcode_url` and `reference_number`. Prioritize the barcode so your customer doesn't need to dictate the reference number at the store. The following table lists the Pespay chains, their maximum payment amounts, and the fees charged to the payer. All amounts are in Mexican pesos (MXN): | Chain | Maximum payment amount (MXN) | Fee charged to the payer (MXN) | | :- | -: | -: | | 7 Eleven | 5,000.00 | 14.00 | | Farmacias del Ahorro | 5,000.00 | 12.00 | | Soriana | 10,000.00 | 10.00 | | Super Kiosko | 6,500.00 | 12.00 | | Waldos | 5,000.00 | 12.00 | | Walmart (Walmart, Bodega Aurrerá, Sam's, and Walmart Express) | 10,000.00 | 12.00 | | Chedraui (not yet available) | 10,000.00 | 10.00 | | Circle K (not yet available) | 5,000.00 | 12.00 | | Extra (not yet available) | 5,000.00 | 12.00 | > [!NOTE] > > **Maximum amount limit by location** > > Show only the available chains that accept your payment amount. Each chain's maximum appears in the table above. ## Handle post-payment events Once a Payment Intent is completed, handle the payment result using the events sent by the webhooks to complete the payment in your backend. Fintoc sends a `payment_intent.succeeded` event when the payment is successfully completed. Use the [webhook guide](/guides/resources/webhooks-walkthrough) to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow. ```json theme={null} { "id": "evt_987654321", "type": "payment_intent.succeeded", "object": "event", "created_at": "2025-12-15T16:10:00.000Z", "data": { "id": "pi_BO381oEATXonG6bj", "object": "payment_intent", "amount": 2476, "currency": "MXN", "status": "succeeded" } } ``` You should handle the following events when using our Payment Initiation product: | Event | Description | Action | | :- | :- | :- | | `payment_intent.succeeded` | Sent when the cash payment succeeds. | Complete the customer's order. | | `payment_intent.expired` | Sent when the cash payment expires and is no longer available to be paid. | Cancel the order and inform the customer. | ## Expire a payment in progress If needed, you can expire a payment that is in the `created` status using the Payment Intent [expire endpoint](/api/payments-api/cash/cash-payment-intents-expire) like in the example below: ```bash theme={null} curl --request POST \ --url https://api.fintoc.com/v1/payment_intents/{id}/expire \ --header 'Authorization: YOUR_TEST_SECRET_API_KEY' \ --header 'accept: application/json' ``` ```javascript Node theme={null} const paymentIntent = await fintoc.paymentIntents.expire('pi_000000000'); ``` ```python theme={null} payment_intent = client.payment_intents.expire('pi_00000000000') ``` After the payment expires, your customer can no longer pay using the reference. ## Refunds Fintoc doesn't support refunds for cash payments. If you [create a refund](/api/payments-api/refunds/refunds-create) for a cash payment, Fintoc responds with a `403 Forbidden` error with the code `payment_method_not_refundable`. You also can't refund a cash payment from the [Dashboard](https://dashboard.fintoc.com). To return money to a customer who paid in cash, use a channel outside of Fintoc refunds. ## Test your integration To simulate a successful or expired cash payment, use one of the following amounts when creating the `PaymentIntent` with `payment_type: "cash"`: | Amount | Final result | | - | - | | Any value except `50000` | `succeeded` | | `50000` | `expired` | In test mode, the `succeeded` scenario delivers an immediate webhook notification of the `payment_intent.succeeded` event. For the `expired` scenario, the Payment Intent goes to the `created` status, so you can test the endpoint to [expire a Payment Intent](/api/payments-api/cash/cash-payment-intents-expire) or wait for the end of the expiration time to receive the `payment_intent.expired` event. # Checkout UX guidelines for Chile Source: https://docs.fintoc.com/guides/payments/checkout-ux-guidelines/chile Buttons, images, and terminology to present Fintoc bank transfer and card payments at your Chilean checkout, with ready-to-use asset URLs. ## Button and image assets **Accepted terminology:** *Paga con tu banco* or *Tarjeta de crédito o débito* **Supporting images:** Combo of Chilean bank logos for *Paga con tu banco* and Visa + Mastercard logos for *Tarjeta de crédito o débito* To use our assets, you can directly use the URLs we provide, for example: ```html HTML theme={null} ``` > [!CAUTION] > > **Refrain from downloading our assets for use** > > We recommend using the direct URLs to our assets instead. This way, you’ll always have the latest versions without needing to make updates whenever Fintoc changes in the future. ## Bank transfer payment button If your checkout lists multiple payment methods, you can follow one of these options: ### Combination (recommended) If you have more space available, we recommend supporting bank images with the full Fintoc logo. Fintoc provides a single image you can reference. Use the terminology *Paga con tu banco*. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/e5d8b34253e72e10fdc1d38a28d77fb690484de930eaea9934cb3ea334cae453-Frame_12.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=cb78207556282daac550ba20225dd476) | Image | Description | HTML | | :- | :- | :- | | ![](https://assets.fintoc.com/?img_name=combo_cl_dark) | Combination of dark isotype with bank logos | `` | | ![](https://assets.fintoc.com/?img_name=combo_cl_light) | Combination of light isotype with bank logos | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d9d1e29215b8fa51f4d80885f36c1219ccca5eefcae16dc010161efc37a859dd-download_4.svg?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=eb0fb9d24fe689355bed3b1091afd0a1) | Combination of text "Paga con tu banco" with light isotype and bank logos +12 | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/a3896385aa60d4936d7bdd6f62aeda94e5bf252f211209272df34a1b8fb8855e-download_7.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=00a9c07e5bfebf25e0236542043d550f) | Isotype and bank logos +12 | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/cf798665cce1a84647c24874a68af5ae6d2b9a4c8b77d84ad0c7b2b69bbc66f4-download_5.svg?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=c020def0c40f0d8059416882461a58cc) | Combination of text "Paga con tu banco" with light isotype and bank logos +16 | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/f46777b223e16594273b660f5835a5ac08200a06c5cd6abe6d7b47a632feb36d-download_8.svg?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=d5bb692f6c613ce4e54f7c5a5040b1d5) | Isotype and bank logos +16 | `` | ### Individual banks In Chile, Fintoc provides the option to pre-select a bank. Use our [widget guide](/guides/resources/widget/web-integration) to get more information on how to enable these options. Our recommendation depends on your checkout screen: * **If Fintoc is your only payment method in Chile:** Place single bank buttons outside the widget. * **If Fintoc is one of your multiple payment methods in Chile:** We recommend placing your user’s top-most used banks (maximum two) as a quick access button outside the widget and placing a general Fintoc button alongside the rest of your payment methods. This ensures quick access for high volume usage of a specific bank. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/ec018b9b44da82ef3daeffb7fb919872c4b76f464ab2fa081dcb839e82c43dd5-individual_banks_example_2.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=acdc1ca335ae0a7e637df1e24c18f2ea) | Image | Description | HTML | | :- | :- | :- | | ![](https://assets.fintoc.com/?img_name=bank_bci_dark) | BCI bank logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_bci_light) | BCI bank logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_bice_dark) | BICE bank logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_bice_light) | BICE bank logo and light isotype | `` | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/676d9950c8f126dbbc87665710321faa77749fd1eec77e903c5182e26f7811bf-bank_de_chile_dark.svg?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=698837eda625ddfb5a308f4d58d7daa9) | Banco de Chile logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_de_chile_light) | Banco de Chile logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_estado_dark) | Banco Estado logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_estado_light) | Banco Estado logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_falabella_dark) | Banco Falabella logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_falabella_light) | Banco Falabella logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_itau_dark) | Banco Itaú logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_itau_light) | Banco Itaú logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_ripley_dark) | Ripley bank logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_ripley_light) | Ripley bank logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_santander_dark) | Santander bank logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_santander_light) | Santander bank logo and light isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_scotiabank_dark) | Scotiabank bank logo and dark isotype | `` | | ![](https://assets.fintoc.com/?img_name=bank_scotiabank_light) | Scotiabank bank logo and light isotype | `` | ### Logo If you display the full logos of other brands, use the full Fintoc logo. Use the terminology *Paga con tu banco*. | Image | Description | HTML | | :- | :- | :- | | ![Dark logotype](https://assets.fintoc.com/?img_name=logo_dark) | Dark logotype | `` | | ![Light logotype](https://assets.fintoc.com/?img_name=logo_light) | Light logotype | `` | ## Card payment button Add the credit or debit card payment button that matches your checkout configuration: Example of checkout button on light and dark modes following the guidelines: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/e350c817919b3d3828e708c4cb33a0c5bca154e900a9ca9c5fa603d58a9e179f-card-payment-buttons.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=46cf741791d79f4a5caf3603b7ef6063) | Image | Description | HTML | | - | - | - | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/3f137f9632c737362a8783aa9c1853808b73903ab5a7f3c09eb0cdcf3a7a06ba-directionhorizontal.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=2c6ec38c32c78be407989f2ff0478823) | Horizontal logos to use with the text "Tarjeta de crédito o débito" | `Fintoc and Card Brands Logos` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/ee156abf75536518de6eb25d687346e6e84cf62b3ba00f6192b722dcdd722f20-directionvertical.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=f3e51674d2490aa84c87df31e817b921) | Vertical logos to use with the text "Tarjeta de crédito o débito" | `Fintoc and Card Brands Logos` | ## Other logo usage To show your users that you work with Fintoc, display the Fintoc logo. Fintoc provides two URLs that you can embed in your website or app. Leave the recommended safe space around the logo. | Image | Description | HTML | | :- | :- | :- | | ![Dark imagotype](https://assets.fintoc.com/?img_name=imagotype_dark) | Dark imagotype | `` | | ![Light imagotype](https://assets.fintoc.com/?img_name=imagotype_light) | Light imagotype | `` | ![Clearance Image](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/2f89f582b2c0a0d5d9a3fa6aff5883688ce3f26da627e979078dab2e248420d3-Clearance_explanation.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=208b6ad257c4f99987dd89a871f021d0) ## Other recommendations ### Pre-fill your user's information Similar to preselecting your user's bank, you can pre-fill your user's payment information, such as their Chilean tax ID (RUT), if you have access to that information. You can make the field editable or not. Pre-filling avoids extra steps and helps you meet any regulatory requirements regarding who makes the payment.\ Use our [widget guide](/guides/resources/widget/web-integration) to get more information on how to pre-fill the username field. ### Keep your current background When opening the widget, don’t redirect users to a new page as this will create new friction points for your users. Instead, keep them in your app or website and open the widget on top and overlay your current screen. ### Avoid duplicated UI elements Avoid repeating navigation elements. Fintoc already includes navigation in the widget, so users can move through the payment flow without duplicate controls. ### React appropriately when there are errors Fintoc handles recoverable errors inside the widget. For final-state errors, use `error_reason` to explain why the transaction failed and guide your user to retry. See [Payment Intent Error Reason](/api/payments-api/payment-intents/payment-intent-error-reason) for the full list of reasons. Ask your user to retry with the required changes. Tell them that no money moved because the payment failed. ### Close the loop When a payment succeeds, it’s important to minimize friction from Fintoc’s flow back into your website or app. We highly suggest you show the *consequence* of using Fintoc, explaining to your user what happens next. Here are some common use cases: * **P2P Transfers**: Reiterate that the money has been sent and show their account minus the money that was just moved. * **Fintech wallets/investment:** show their account screen with new money clearly added and visualized. * **E-commerce:** show a confirmation screen that includes information about the amount paid, billing information, the products purchased, address and delivery date if applicable, or further instructions to obtain the product. # Checkout UX guidelines Source: https://docs.fintoc.com/guides/payments/checkout-ux-guidelines/index Best practices for embedding Fintoc's checkout buttons and images by URL, keeping approved terminology, sizing, and colors consistent across your site. This guide covers how to use Fintoc's checkout buttons and images so your integration stays consistent and compliant. ### Best Practices ✅ Do: * Only use buttons and images provided by Fintoc by embedding the URL provided. * Use the same button or image style throughout your site. * Button text should only include Fintoc-approved terminology. * Make sure the size of Fintoc buttons is equal to or larger than other buttons. * Make sure you choose a background color that contrasts with the button color. * Try to add the supporting images by country. ❌ Do not: * Do not create your own Fintoc buttons or modify the font, color, button radius, or padding inside the button in any way. * Do not utilize a png, jpg or non URL version of the buttons and images provided. * Do not make the Fintoc button smaller than other buttons. * Do not use a background color that is similar to the button color. * Do not add shadow effects to the button. * Do not add hover effects. * Do not add external strokes to the button. * Do not utilize any other terminology than the one approved for that country. ### Why use URLs in your checkout We recommend that you use the URL links directly in your application or website to get the most up-to-date version of the images. This way you don't have to update your checkout every time there is a change. To use our assets, you can directly use the URLs we provide, for example: ```html HTML theme={null} ``` If you have questions about how to implement these recommendations, contact our team. ### Country specific guidelines [Chile](/guides/payments/checkout-ux-guidelines/chile) [Mexico](/guides/payments/checkout-ux-guidelines/mexico) # Checkout UX guidelines for Mexico Source: https://docs.fintoc.com/guides/payments/checkout-ux-guidelines/mexico Buttons, Sistema de Pagos Electrónicos Interbancarios (SPEI) and card logos, and accepted terminology for presenting bank transfer, card, and cash payments. ## Button and image assets **Accepted terminology:** *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI* for bank transfers, *Tarjeta de crédito o débito* for cards, and *Paga en efectivo* for cash **Supporting images:** SPEI logo for bank transfers and Visa + Mastercard logos for *Tarjeta de crédito o débito* Reference Fintoc assets directly with the provided URLs. For example: ```html HTML theme={null} ``` > [!CAUTION] > > **Refrain from downloading our assets for use** > > We recommend using the direct URLs to our assets instead. This way, you’ll always have the latest versions without needing to make updates whenever Fintoc changes in the future. ## Bank transfer payment button ### Button Use a button when your checkout lists other payment methods as buttons. | Image | Description | HTML | | :- | :- | :- | | ![Mexico dark button with trailing isotype](https://assets.fintoc.com/?img_name=button_mx_dark_trailing) | Mexican dark button with trailing isotype | `` | | ![Mexico light button with trailing isotype](https://assets.fintoc.com/?img_name=button_mx_light_trailing) | Mexican light button with trailing isotype | `` | | ![Mexico dark button with leading isotype](https://assets.fintoc.com/?img_name=button_mx_dark_leading) | Mexican dark button with leading isotype | `` | | ![Mexico light button with leading isotype](https://assets.fintoc.com/?img_name=button_mx_light_leading) | Mexican light button with leading isotype | `` | ### Combination (recommended) If you have more space available, we recommend using the isotype with the SPEI logo. Fintoc provides a single image you can reference. Use the terminology *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI*. ![Combo Image](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/ccd6be89311824f1301514a006f80df315b35bbc25b7b4b0dedaabd80d428c1f-combo_mx_example_2.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=3204bf32706dab8be174c8b6d736a118) | Image | Description | HTML | | :- | :- | :- | | ![Combo dark isotype with spei logo](https://assets.fintoc.com/?img_name=combo_mx_dark) | Combination of dark isotype with spei logo | `` | | ![Combo light isotype with spei logo](https://assets.fintoc.com/?img_name=combo_mx_light) | Combination of light isotype with spei logo | `` | ### Logo If you display the full logos of other brands, use the full Fintoc logo. Use the terminology *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI*. ![Logo Image](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/a13d381d44d2fdb76b17149854d42e6f39794071c148c2c1a57046948b55cb84-logo_mx_example.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=f92e4d7512901ad61b9b78b27373deb6) | Image | Description | HTML | | :- | :- | :- | | ![Dark logotype](https://assets.fintoc.com/?img_name=logo_dark) | Dark logotype | `` | | ![Light logotype](https://assets.fintoc.com/?img_name=logo_light) | Light logotype | `` | ## Card payment button Add the credit or debit card payment button that matches your checkout configuration: Example of checkout button on light and dark modes following the guidelines: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/e350c817919b3d3828e708c4cb33a0c5bca154e900a9ca9c5fa603d58a9e179f-card-payment-buttons.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=46cf741791d79f4a5caf3603b7ef6063) | Image | Description | HTML | | - | - | - | | ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/3f137f9632c737362a8783aa9c1853808b73903ab5a7f3c09eb0cdcf3a7a06ba-directionhorizontal.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=2c6ec38c32c78be407989f2ff0478823) | Horizontal logos to use with the text "Tarjeta de crédito o débito" | `Fintoc and Card Brands Logos` | | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/ee156abf75536518de6eb25d687346e6e84cf62b3ba00f6192b722dcdd722f20-directionvertical.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=f3e51674d2490aa84c87df31e817b921) | Vertical logos to use with the text "Tarjeta de crédito o débito" | `Fintoc and Card Brands Logos` | ## Other logo usage To show your users that you work with Fintoc, display the Fintoc logo. Fintoc provides two URLs that you can embed in your website or app. Leave the recommended safe space around the logo. | Image | Description | HTML | | :- | :- | :- | | ![Dark imagotype](https://assets.fintoc.com/?img_name=imagotype_dark) | Dark imagotype | `` | | ![Light imagotype](https://assets.fintoc.com/?img_name=imagotype_light) | Light imagotype | `` | ![Clearance Image](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/2f89f582b2c0a0d5d9a3fa6aff5883688ce3f26da627e979078dab2e248420d3-Clearance_explanation.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=208b6ad257c4f99987dd89a871f021d0) ## Other recommendations ### Pre-fill your user's information If you have access to your user's payment information, such as their telephone number, you can pre-fill the relevant field. Your users can still edit the field. Pre-filling avoids extra steps.\ Use our [widget guide](/guides/resources/widget/web-integration) to get more information on how to pre-fill the username field. ### Keep your current background When opening the widget, don’t redirect users to a new page as this will create new friction points for your users. Instead, keep them in your app or website and open the widget on top and overlay your current screen. ### Avoid duplicated UI elements Avoid repeating navigation elements. Fintoc already includes navigation in the widget, so users can move through the payment flow without duplicate controls. ### React appropriately when there are errors Fintoc handles recoverable errors inside the widget. For final-state errors, use `error_reason` to explain why the transaction failed and guide your user to retry. See [Payment Intent Error Reason](/api/payments-api/payment-intents/payment-intent-error-reason) for the full list of reasons. Ask your user to retry with the required changes. Tell them that no money moved because the payment failed. ### Close the loop After a payment succeeds, show what happens next in your website or app. Common use cases include: * **P2P transfers:** Show a confirmation that the money was sent and update the account balance. * **Fintech wallets or investments:** Show the account screen with the new balance. * **E-commerce:** Show a confirmation screen with the amount paid, billing details, purchased products, address, delivery date, or next steps. A cash payment stays pending after your user gets the payment voucher, until they pay at the store. Tell your user that the purchase is confirmed once they pay. Do not show a fixed payment deadline: the voucher expires when the Checkout Session expires. # Checking payment eligibility Source: https://docs.fintoc.com/guides/payments/direct-payments/check-payment-eligibility-direct-payments Pre-validate a Direct Payment against transfer limits by calling the payment_intents/check_eligibility endpoint or attaching a sender_account object. Pre-validating a payment intent helps reduce the chance of payments failing due to transfer limits. There are two ways to check a payment's eligibility: * Using the `payment_intents/check_eligibility` endpoint to check eligibility before showing a user the accepted payment methods. * Including a `sender_account` object when creating a Checkout Session or Payment Intent to check when a user selects Fintoc as a payment method. When creating a payment intent, you can include a `sender_account` object in your request. This object allows you to specify the sender's account details, enabling our system to perform more accurate validations based on general transfer limits and previous transactions through Fintoc. **This feature is only available in Chile**. > [!CAUTION] > > **This validation only checks payments made through Fintoc.** > > If you’ve already received payments from users on this recipient account, we recommend not using this feature as it could mistakenly block valid payments. ## Using the `payment_intents/check_eligibility` endpoint If you want to check a payment's eligibility before showing a user the accepted payment methods, you can use the following endpoint: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/payment_intents/check_eligibility \ --header 'Authorization: sk_test_0000000000000000' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 1000, "currency": "CLP", "sender_account": { "holder_id": "111111111", "institution_id": "cl_banco_estado" }, "recipient_account": { "holder_id": "222222222", "institution_id": "cl_banco_estado", "type": "checking_account", "number": "0000000" } } ``` The `sender_account` object contains two fields: * `holder_id`: The RUT (Rol Único Tributario) of the account holder * `institution_id`: The [ID](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions#available-sender-banks) of the bank institution Mixing these fields will help you validate certain limits: * If you only send the `institution_id` and no `holder_id`, Fintoc will only validate bank-specific limits for maximum and minimum transfer amounts. * If you send both, Fintoc will perform all validations for the payment intent. If the payment is eligible, this endpoint will respond with the following object: ```json JSON theme={null} { "eligible_payment": true, "error": null } ``` If it isn't valid it will respond with one of the error responses like this: ```json JSON theme={null} { "eligible_payment": false, "error": { "type": "new_contact_error", "message": "The amount exceeds the maximum amount permitted for new contacts. For #{institution_name}, the maximum permissible amount is $250,000. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` ## Including a `sender_account` object When making a POST request to creating a Checkout Session, include the `sender_account` object in your JSON payload. Here's an example: ```json theme={null} { "amount": 1000, "currency": "CLP", "metadata": { "order": "#987654321" }, "customer_email": "customer@example.com", "payment_method_options": { "bank_transfer": { "sender_account": { "holder_id": "111111111", "institution_id": "cl_banco_estado" } } } } ``` The `sender_account` object contains two fields: * `holder_id`: The RUT (Rol Único Tributario) of the account holder * `institution_id`: The [ID](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions#available-sender-banks) of the bank institution Mixing these fields will help you validate certain limits: * If you only send the `holder_id` and no `institution_id`, Fintoc will use general limits for new contacts allowing more payments to go through without incorrectly canceling any. * If you only send the `institution_id` and no `holder_id`, Fintoc will only validate bank-specific limits for maximum and minimum transfer amounts. * If you send both, Fintoc will perform all validations for the payment intent. > [!WARNING] > > **Use the Same Holder ID** > > When setting up the widget to pre-fill a username, use the same holder\_id as for pre-validating payments. This ensures consistency and helps prevent payment failures. ## Validation process When you include the `sender_account` information, our system performs several checks to validate the payment intent: 1. **Institution-specific limits**: We check if the payment amount is within the allowed limits for the specified institution. 2. **New contact limits**: For first-time transfers or transfers within 24 hours of the first transfer, institutions apply stricter limits. 3. **Maximum transfer amounts**: We ensure the payment doesn't exceed the maximum allowed transfer amount for the specified bank. ## Error responses If a validation fails, you'll receive one of the following error responses: 1. **New contact maximum amount limit error**: Fintoc first checks if the `holder_id` has made a transfer. If not, it then checks if the amount exceeds the institution's limit. ```json theme={null} { "error": { "type": "new_contact_error", "message": "The amount exceeds the maximum amount permitted for new contacts. For #{institution_name}, the maximum permissible amount is $250,000. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 2. **New contact payment number limit error**: Fintoc first checks if the `holder_id` has made their first transfer during the same day. If they have, it then checks if the institution allows for more than one transfer to a new contact. ```json theme={null} { "error": { "type": "new_contact_error", "message": "The maximum number of transfers for new contacts in #{institution_name} was reached. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_payment_number_limit_error", "param": "sender_account", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 3. **Minimum amount limit error**: Fintoc checks if the amount is lower than the minimum allowed by the institution. ```json theme={null} { "error": { "type": "amount_error", "message": "The amount is lower than the minimum amount permitted for payments by #{institution_name}. Please enter an amount greater than $1000.", "code": "minimum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 4. **Maximum amount limit error**: Fintoc checks if the amount exceeds the maximum allowed by the institution. ```json theme={null} { "error": { "type": "amount_error", "message": "The amount exceeds the maximum amount permitted for payments by #{institution_name}. Please enter an amount less than $70000000.", "code": "maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` ## Best practices 1. Always include the `sender_account` information when creating a Checkout Session to ensure the most accurate validations. 2. Handle error responses gracefully in your application, providing clear feedback to your users about why a payment couldn't be processed. 3. Make adjustments to your order so users are able to pay. These could be changing the payment amount if possible or setting up reminders for future payments. # Handling payment exceptions Source: https://docs.fintoc.com/guides/payments/direct-payments/dealing-with-payment-exceptions-2 When managing payments, you may encounter situations that require action to reconcile payments and keep customers informed. ## Pending payments Pending payments are instances where Fintoc cannot provide a definitive status of the payment at the moment. These payments can either succeed or fail at a later time, depending on various factors and your process for handling them might depend on your payment scheme and API version. > [!WARNING] > > **Pause internal processes** > > We strongly advise you to pause any internal processes that may be affected by the payment completion, such as charging interest on debts or canceling contracts, until the payment is finalized. ### How to deal with pending payments Fintoc does not have access to your bank statements and might not be able to provide a definite answer regarding the status of some payments. If the Payment is validated as successful or failed, Fintoc will send a webhook (`payment_intent.succeeded` or `payment_intent.failed`) notifying the final status of the payment. Fintoc will attempt to validate pending payments for up to 10 days. If the payment cannot be verified in that time, you will receive a `payment_intent.failed` webhook with a distinct error reason (`unresolved_final_status`). It is highly recommended to check your banks statements to see if the payment was completed or not. If the payment occurs, we recommend handling it depending on your business case: | Action | Description | | - | - | | Return of funds | Inform your client that if the payment is successful, you will promptly return their funds to their bank account within a reasonable timeframe. | | Fulfill their order | Notify your client that their order is complete, but you are awaiting the final payment status before fulfilling it. | #### Previous API versions Since there is no pending state for payments in previous versions of our API, these will always have a failed status initially. Fintoc might be able to determine the final status, but we recommend you check your bank statement for any unknown transfer you might have received related to this payment. If you are not using this current version of the API, we encourage you to check the documentation of your API version to get more details. ## False failed payments False failed payments occur when Fintoc provides a `failed` status for a payment, but the funds are actually deposited into your bank account. ### How to deal with false failed payments Check your bank statements to verify whether each payment was completed. If Fintoc marks a deposited payment as `failed`, handle the payment based on your business case: | Action | Description | | :- | :- | | Return the funds | Inform your client that the payment was successful and that you will promptly return their funds to their bank account within a reasonable timeframe. | | Fulfill the order | Notify your client that the payment was successful and that their order will be processed. | ## External transfers If you are using Direct Payments, your company name may be saved on you client’s recipient contacts in their banks. This means that they can mistakenly transfer funds directly to your account outside of your payment flow. ### How to deal with external transfers Since Fintoc does not have access to your bank statement, there is no way to tell if a movement outside of a regular payment flow was made. To provide a great user experience, we encourage you to identify this cases and handle them according to your business case. As these payments are typically caused by user errors and may have been intended for another bank account, **we encourage you to return these payments to your clients or establish a clear policy on how to handle them**. This proactive approach can help you avoid larger issues with your customer support team and provide a better overall payment experience for your users. ## Fintoc Reconciles If you are using **Fintoc Reconciles**, the reconciliation process run by Fintoc will automatically identify both **Pending Payments** and **External Transfers**. Each business day, Fintoc will analyze the transaction records of your bank account and compare them with the payments received via the Fintoc API. Based on this reconciliation process, Fintoc will provide you with a **file containing the results**. For specific details on the reconciliation results file, visit the **"Reporting and Reconciliation"** section. # Direct payments Source: https://docs.fintoc.com/guides/payments/direct-payments/index Learn about how to handle typical use cases when using Fintoc for direct payments. > [!NOTE] > > **Only available in Chile** > > Direct payments is only available in Chile. It's not available in Mexico yet. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/f3bf947-Frame_4195.svg?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=59708ad7cdd6a25740f303d5bd585440) In direct payments, the money flows directly from your customer's bank account to the recipient account you specify. ## Who can use direct payments Direct payments aren't enabled by default. Fintoc must enable them for your organization in both `test` and `live` modes. To request enablement, email [sales@fintoc.com](mailto:sales@fintoc.com) or contact your account executive. For details, see [Set up direct payments](/guides/payments/direct-payments/setup-direct-payment). Your business must also meet the same requirements as every other Fintoc product: To use Fintoc, your business must meet all of these requirements: * **A company tax ID.** In Mexico, this is your company's Mexican tax ID (RFC), which has 12 characters. In Chile, this is your company's Chilean tax ID (RUT). * **A bank account in your company's name.** Fintoc only sends your payouts to an account associated with your company's RFC or RUT. * **An email address on your company's domain.** Sign up with a corporate email, not a personal one such as Gmail or Hotmail. Fintoc doesn't accept individuals, including a natural person with business activity (persona natural con giro). Your company also needs at least 6 months of business activity, counted from the start date on your business initiation certificate. If your company is younger, the Dashboard shows an error when you upload the certificate and you can't complete the onboarding. ## Reconciliation If you collect the money in a single bank account, you'll need to periodically download your bank statement and run a reconciliation process to track and match Fintoc payments. You'll also need to handle any external bank transfers you may receive. | Advantage | Disadvantage | | :- | :- | | The funds arrive instantly in the recipient's bank account. | You need to run complex reconciliation processes to handle external bank transfers and other border cases, and track and match Fintoc payments. | ### **Fintoc Reconciles** This schema allows you to receive payments directly into your own bank account. Fintoc runs a reconciliation process to help you track and match incoming transactions by accessing your account’s transaction records. ### **How it works** * Your customers send payments directly to your bank account. * Fintoc has read access to your bank account’s transaction records. * Every business day, Fintoc runs a reconciliation process to identify and match transactions. At the end of that process, Fintoc sends you a file with the reconciliation results. ### **Considerations** * Only for Chile. Availability depends on your bank. Contact us to check if your bank account is eligible for this schema. * The integration process is the same for Fintoc Reconciles and Direct Payments. For more details on this reconciliation process, visit the **"Handling Payment Exceptions"** and **"Reporting and Reconciliation"** sections. ## Available sender banks Your customers can pay a direct payment from the following institutions: | Bank name | Fintoc bank ID | | :- | :- | | Banco BCI | `cl_banco_bci` | | Banco BICE | `cl_banco_bice` | | Banco de Chile - Edwards - Citi | `cl_banco_de_chile` | | Banco Estado | `cl_banco_estado` | | Banco Falabella | `cl_banco_falabella` | | Banco Itaú | `cl_banco_itau` | | Banco Ripley | `cl_banco_ripley` | | Banco Santander | `cl_banco_santander` | | Scotiabank | `cl_banco_scotiabank` | To see which institutions can hold recipient accounts, check the [Chile institution codes](/api/fintoc-api/chile-institution-codes). # Reporting and reconciliation Source: https://docs.fintoc.com/guides/payments/direct-payments/reporting-and-reconciliation Get the data you need to complete your accounting and reconciliation workflows. Fintoc's reports help you understand and reconcile the activity in your account. You can view and download these reports directly from the Dashboard or [schedule reports to be sent automatically](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation#available-delivery-channels). ## Select a report When using Fintoc's Payment Initiation API, Fintoc has reports that provide information about your transactions. Start with the task you're looking to perform and use the table below to identify the best report. | Task | Suggested report | | :- | :- | | Download daily transaction history View daily transaction totals | Daily transaction | | View payment exceptions (only for Fintoc Reconciles) | Irregular statement transactions | ## Daily transaction report ### Delivery schedules The daily transaction report can be scheduled for delivery on two schemes: banking cut-off time and chronological day cut-off time. Configured schedules have two effects: * They change the day and hour that reports are delivered. * They change the time window of data that each file contains. | Delivery schedule | Available country | Description | | - | - | - | | chronological day | Chile Mexico | The report will be delivered every day without exception. The file will contain data from a single day from 00:00 to 23:59. Files will be delivered between 00:20 and 01:20. | | banking day | Chile | The report will be delivered according to Chile's banking cut-off time, which is business days at 14:00. Therefore, data for a specific day will be between 14:00 and 13:59 of the next business day. Files will be delivered on business days between 14:20 and 15:20. For example, holidays aside, a report received on a Wednesday will contain data from Tuesday at 14:00 until Wednesday at 13:59. Another example is that a report received on Monday will contain data from the previous Friday at 14:00 until Monday at 13:59. If that Friday happens to be a holiday, the data window will be even larger (it would start on Thursday at 14:00). | ### Structure The daily transaction report is a semicolon-delimited CSV file in which the first row is column headers. The filename is `yyyy-mm-dd-daily-summary-fintoc-.csv`. For example, if your `orgname` is "My Company" the filename will be `yyyy-mm-dd-daily-summary-fintoc-mycompany.csv`. The file contains the following columns: | # | Column | Type | Description | | :- | :- | :- | :- | | 1 | `created_at` | `string` | The Payment Intent's creation date, in ISO 8601 format. | | 2 | `payment_id` | `string` | Unique identifier for the payment. It is case-sensitive. | | 3 | `id_given_by_sender_institution` | `string` | Operation number from the bank of the sender account. | | 4 | `updated_at` | `string` | The Payment Intent update date, in ISO 8601 format. | | 5 | `amount` | `integer` | Amount of the payment, in cents. | | 6 | `currency` | `string` | The payment [currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | 7 | `sender_institution_id` | `string` | The bank that initiated the payment. | | 8 | `sender_institution_cmf_code` | `string` | The CMF code of the bank that initiated the payment. In Mexico, it is empty. | | 9 | `sender_account_number` | `string` | The account number that initiated the payment. | | 10 | `sender_account_type` | `string` | The sender account type. | | 11 | `sender_holder_id` | `string` | Identifier of the owner of the bank account that initiated the payment. In Chile, it is the Chilean tax ID (RUT); in Mexico, it is the Mexican tax ID (RFC). | | 12 | `sender_name` | `string` | The name of the owner of the bank account that initiated the payment. It can be empty. | | 13 | `recipient_holder_id` | `string` | Identifier of the owner of the bank account that received the payment. In Chile, it is a RUT and in Mexico it is an RFC. | | 14 | `recipient_account_number` | `string` | The account number that received the payment. | | 15 | `recipient_institution_id` | `string` | The bank that received the payment. | | 16 | `organization_name` | `string` | Your organization name in Fintoc's system. | | 17 | `metadata` | `string` | A JSON string of the transaction [metadata](/api/fintoc-api/metadata). | ### Sample For an example of the included data, [download a sample of the daily transaction report](https://drive.google.com/file/d/11ACkHoqCXwxKgHrw01xkIlCRIY_1Oswl/view?usp=drive_link). ## Irregular statement transactions report This file includes the payment exceptions identified during the reconciliation process that Fintoc runs on your bank account every business day. If no exceptions are found, the file does not contain any records. The reconciliation process operates within a banking cut-off time, starting at 14:00 on the previous business day and ending at 13:59 on the current business day. The file is delivered at 18:00 on the current business day. ### Structure The irregular statement transactions report is a semicolon-delimited CSV file in which the first row is column headers. The file contains the following columns: | # | Column | Type | Description | | - | - | - | - | | 1 | `movement_id` | `string` | Unique identifier for the movement in the reconciliation process. | | 2 | `payment_id` | `string` | Unique identifier for the payment. It is case-sensitive. If empty, it means the transaction is an external transfer and was not processed via Fintoc. | | 3 | `amount` | `integer` | Amount of the payment, in cents. | | 4 | `currency` | `string` | The payment [currency ISO code](https://www.iso.org/iso-4217-currency-codes.html). | | 5 | `post_date` | `string` | Date and time when the transaction was posted, in `YYYY-MM-DD HH:MM:SS UTC` format. | | 6 | `sender_holder_id` | `string` | Identifier of the owner of the bank account that initiated the payment. In Chile, it is a RUT. | | 7 | `sender_name` | `string` | Name of the owner of the bank account that initiated the payment. It can be empty. | | 8 | `sender_account_number` | `string` | The account number that initiated the payment. | | 9 | `sender_account_type` | `string` | The sender's account type. | | 10 | `sender_institution_id` | `string` | The bank that initiated the payment. | | 11 | `recipient_holder_id` | `string` | Identifier of the owner of the bank account that received the payment. In Chile, it is a RUT. | | 12 | `recipient_account_number` | `string` | The account number that received the payment. | | 13 | `recipient_institution_id` | `string` | The bank that received the payment. | ### Sample For an example of the included data, download a sample of the [irregular statement transactions report](https://drive.google.com/file/d/1zKUSqQywCx21GCXpyiLfs7KBWqZRDEZ9/view?usp=sharing). ## Available delivery channels Instead of manually downloading files from the Dashboard, reports can be scheduled for automatic delivery via different channels. If configured, reports are delivered periodically so that each file contains data for a specific time interval. ## Email Files can be automatically delivered to an email of your choice. The subject of the sent emails is also configurable. For instance, it is common to include the date of a given report on the subject for easier identification. For email and subject configuration, contact our sales team. ## SFTP The recommended way of receiving the reports is via Fintoc's SFTP. This lets you automate the extraction of files. ### Connecting to the SFTP server Use the following information to connect to Fintoc's SFTP server: * Host: `sftp.fintoc.com` * Port: `80` * Username: your organization's ID. It starts with `org_` * Password: the password provided by your Account Executive. For access credentials, contact our sales team. ### Reports path Fintoc uploads each report in the following paths: | Report | File path | | :- | :- | | Daily transaction | `OUT/daily_summary//yyyy-mm-dd-daily-summary-fintoc-.csv` | Where `` can be either `live` or `test`. # Set up direct payments Source: https://docs.fintoc.com/guides/payments/direct-payments/setup-direct-payment Configure the recipient account for a Direct Payment on the Fintoc API so funds settle into the correct bank account when your customer completes the transfer. > [!NOTE] > > **Direct payments availability** > > For now, direct payments are only available in Chile. ## Before you begin Fintoc must enable direct payments for your organization before you can send a `recipient_account`. This applies to both `test` and `live` modes. To request enablement, email [sales@fintoc.com](mailto:sales@fintoc.com) or contact your account executive. If your organization uses [Fintoc Collect](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts), Fintoc presets the recipient account for you. If you send `payment_method_options.bank_transfer.recipient_account` when you create a checkout session, Fintoc rejects the request with a `400 Bad Request` status and this error: ```json theme={null} { "error": { "type": "invalid_request_error", "code": "invalid_payment_recipient_account", "message": "Invalid payment recipient_account: Your organization has collection activated. You must not send recipient account because that is preset for you by Fintoc." } } ``` To resolve the error, remove `recipient_account` from the request, or ask Fintoc to enable direct payments for your organization. ## Create a direct payment To create a direct payment, you need to set the `recipient_account` option when creating a checkout session: ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header 'Authorization: sk_live_0000000000000000' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": 2476, "currency": "CLP", "payment_method_types":["bank_transfer"], "payment_method_options":{ "bank_transfer":{ "recipient_account": { "holder_id": "111111111", "number": "0000000000", "type": "checking_account", "institution_id": "cl_banco_de_chile" } } } } ' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 2476, currency: 'CLP', payment_method_types: ['bank_transfer'], payment_method_options: { bank_transfer: { recipient_account: { holder_id: '111111111', number: '0000000000', type: 'checking_account', institution_id: 'cl_banco_de_chile' } } } }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=2476, currency='CLP', payment_method_types=['bank_transfer'], payment_method_options={ 'bank_transfer': { 'recipient_account': { 'holder_id': '111111111', 'number': '0000000000', 'type': 'checking_account', 'institution_id': 'cl_banco_de_chile' } } } ) ``` In Chile, the recipient account object is defined by 4 attributes: | Parameter | Example | Explanation | | :- | :- | :- | | `holder_id` | 111111111 | Account holder's [RUT](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) | | `number` | 0000000000 | Account number | | `type` | checking\_account | Type of account. Supported types are `checking_account` and `sight_account`. | | `institution_id` | cl\_banco\_de\_chile | Fintoc institution id for the bank receiving the bank transfer. You can see the code for each bank [here](/guides/payments/direct-payments/setup-direct-payment#available-recipient-banks) | Once you set the recipient account in the checkout session, the money arrives directly in the bank account you specify. ## Available recipient banks You can settle a direct payment into an account at any of the institutions listed in [Chile institution codes](/api/fintoc-api/chile-institution-codes). The recipient-account list is different from the [banks your customers can pay from](/guides/payments/direct-payments#available-sender-banks). # Direct Transfer Source: https://docs.fintoc.com/guides/payments/direct-transfer Accept payments sent by a direct transfer from your user. ## Overview Using Direct Transfer your users can pay by manually transferring funds to a bank account. Once the transfer is complete, Fintoc automatically detects and validates the payment. This method allows you to receive payments from banks, prepaid accounts, and wallets in Chile, and from institutions participating in SPEI in Mexico. It works for both individual and business account types. Direct Transfers is only available when [Fintoc collects](/guides/payments/fintoc-collect-payments) your payments. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/ca9043d3ead3b70c437945340f3a814d23788862118d8f63bf615a92dfbab521-flow_tef_directa.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=c75b48ebc71bcc18c57c196efd0adf4c) ## Available sender banks in Chile Users can complete Direct Transfers from the following institutions: | Bank Name | Fintoc Bank ID | | :- | :- | | Banco Estado | `cl_banco_estado` | | Banco BCI | `cl_banco_bci` | | Banco BICE | `cl_banco_bice` | | Banco de Chile - Edwards - Citi | `cl_banco_de_chile` | | Banco Falabella | `cl_banco_falabella` | | Banco Itaú | `cl_banco_itau` | | Banco Ripley | `cl_banco_ripley` | | Banco Santander | `cl_banco_santander` | | Banco Consorcio | `cl_banco_consorcio` | | Scotiabank | `cl_banco_scotiabank` | | Mercado Pago | `cl_mercado_pago` | | Mach | `cl_mach` | | Tenpo | `cl_tenpo` | | Banco Security | `cl_banco_security` | | Tapp | `cl_tapp_caja_los_andes` | | Banco Internacional | `cl_banco_internacional` | | Coopeuch - Dale | `cl_banco_coopeuch` | | Copec Pay | `cl_copec_pay` | | Prepago Los Heroes | `cl_prepago_los_heroes` | | BBVA | `cl_banco_bbva` | | HSBC | `cl_banco_hsbc` | ## How Fintoc matches a transfer to a payment in Chile In Chile, Fintoc links each Direct Transfer to a payment intent using the Chilean tax ID (RUT) your user enters in the payment window. When Fintoc receives a transfer, it looks for an in-progress Direct Transfer payment intent where: * The RUT of the account holder who sent the transfer matches the RUT entered in the payment window. * The transfer amount matches the payment intent amount. If Fintoc finds a match, the payment intent succeeds and you see the payment in your logs. ### Transfers that Fintoc can't match Fintoc can't link a transfer to a payment intent when: * Your user transfers from an account whose holder has a different RUT than the one entered in the payment window. For example, the account of another person or a company. * Fintoc has no in-progress payment intent for the sender's RUT. For example, the payment intent already expired. * Your user transfers directly from their bank without starting a payment in your checkout. In these cases, the payment intent stays unpaid and eventually expires, and the transfer doesn't appear in your logs. Fintoc automatically refunds the transfer to the origin account. Your user sees the refund in their account as a deposit under Fintoc's name, usually within 2 to 3 business days. ### What to tell your users If your user says they paid but you see an expired or unpaid order, tell them that Fintoc refunds the transfer automatically to the origin account. To avoid unmatched transfers, ask your users to: 1. Always start the payment from your checkout and transfer only when the payment window asks them to. 2. Enter the RUT of the holder of the account they will transfer from, and transfer only from that account. 3. Transfer only to the account shown in the payment window, for the exact amount. ## FAQ **Q: What happens if the user transfers a different amount?**\ A: Fintoc tells your user that the transfer will be refunded and asks them to try again with the correct amount. # E-commerce plugins Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/index Use these guides to integrate Fintoc with a plugin for one of the following e-commerce platforms: > [card] [Shopify](/guides/payments/e-commerce-connectors/shopify) > > ![](https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Shopify_logo_2018.svg/960px-Shopify_logo_2018.svg.png) > [card] [WooCommerce](/guides/payments/e-commerce-connectors/woocommerce) > > ![](https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/WooCommerce_logo_%282015%29.svg/330px-WooCommerce_logo_%282015%29.svg.png) > [card] [Magento](/guides/payments/e-commerce-connectors/magento) > > ![](https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Magento_Logo.svg/330px-Magento_Logo.svg.png?20211207023221) > [card] [VTEX (Chile only)](/guides/payments/e-commerce-connectors/vtex) > > ![](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a9/VTEX_Logo.svg/330px-VTEX_Logo.svg.png) # Magento Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/magento Accept payments using Fintoc’s app in your Magento store. This guide walks you through integrating Fintoc into your Magento store to accept payments from your customers. ## Prerequisites Before you start, you need: * A Fintoc account with API credentials (Secret Key and Webhook Secret). * Admin access to your Magento 2 store. * Developer access (if you need to install or update the module). You can find your API credentials in the [Fintoc Dashboard](https://dashboard.fintoc.com/login). ## Getting started: credentials and setup ### 1. Sign Up To initiate the process, head to [Fintoc's dashboard and sign up](/guides/home/dashboard/guides-api-keys). To start receiving payments in Live mode, [fill out your information](https://tally.so/r/mKLrWz) to facilitate account activation and provide you with the necessary credentials. ### 2. Obtain API Keys Within your Fintoc dashboard, you will find both Test and Live API Keys. **You should use your Live API Keys to setup Fintoc within Magento**. To get your Live API Keys, make sure you are in Live mode by checking the button on the top left of our dashboard. Then, head over to For Developers → API Keys to obtain them. ## Integration and configuration process ## Installation (if not preinstalled) Ensure the module is installed and enabled by your developer or partner. * Example (for developers): * composer require fintoc/module-payment * bin/magento module:enable Fintoc\_Payment * bin/magento setup:upgrade * bin/magento cache:flush ## Enabling the plugin in your Magento store 1. **Log in** to your Magento Admin panel. 2. Go to **Stores** → **Configuration** → **Sales** → **Payment Methods** → **Fintoc**. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/1a9965bf2ba52f01db19075a258fcc715f1c3776a1afd11110cedc03cc12ca1f-Screenshot_2025-10-09_at_12.16.15_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=986ab9b0edfaf101803b30d399b9838d) ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/6430fb125c0882cc612bee023655a116be06c1512797285b569ad34905ad5333-Screenshot_2025-10-09_at_12.16.50_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=f91cab0ba3218f678170cdd3ba0cadd2) 3. In **Basic Settings**, enter: * Secret API Key (from the Fintoc Dashboard) * Webhook Secret (from the Fintoc Dashboard, this is explained in the next section.) * (Optional) Adjust logging and debug settings: Enable Logging, Debug Mode, set Debug Level, and toggle Log Sensitive Data 4. In **Payment Initiation**, configure: * Enabled: Yes * Title: Display name (e.g. Pay with Fintoc) * Automatically Invoice All Items (optional) * New Order Status: usually **Pending** or **Processing** depending on your invoicing policy * Applicable Countries: all or selected * Maximum Order Amount (optional) * Sort Order (checkout display order) 5. In **Refunds** (optional): * Enable **Refunds** and **Partial Refunds** * Enable Auto-create Credit Memo * Define status transitions for Refund events (Pending, Succeeded, Failed, Canceled) 6. Click Save Config, then clear caches if prompted. ## Managing Magento's admin **For transactions** 1. Go to Sales → Fintoc → Transactions in the Magento Admin. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/3ea0f0e493b9121a01d826f7b76296f0560c35ab62dece5f30882ba3ee684c01-Screenshot_2025-10-10_at_4.04.57_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=7a7add130cd7d9a4a681a1dbeb2bdec7) 2. Use filters to search by order or transaction ID. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/25d47b38b23503108f0880b1daa1c13f83b317d450036414f5dac0defdc357fe-Screenshot_2025-10-10_at_4.06.58_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=1e1389c369ad9726702c45af195a592b) 3. Click any transaction to view details and webhook logs. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/78c98a92e1ce4513a05e4c56fff9e9604f92fca3ad41798a64ded45edd678941-Screenshot_2025-10-10_at_4.07.49_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=5aede1bb7b4df2c1f26b2e72a5edd87c) **You can issue refunds directly from Magento:** 1. Go to Sales → Fintoc → Refundable Orders, open the refund form, and submit. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/8ddecae4211b22fb41b117c15a65aad0a572cd855b591e6bd0bb0d35d0746cf3-Screenshot_2025-10-10_at_4.12.00_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=98158f3942bc6dcda42302308748b8fd) 2. Or use the standard Credit Memo flow if configured. Magento will automatically send refund requests to Fintoc and update statuses accordingly. ### Webhook setup To keep payment statuses synchronized: 1. In your Fintoc Dashboard, switch to the same mode as your store. Use `live` mode if your store uses your `live` Secret API Key. A webhook created in `test` mode doesn't receive `live` payment events. 2. Go to the [Webhooks](https://dashboard.fintoc.com/webhooks) section and create a new webhook. * Set the **URL** to `{STORE_URL}/fintoc/webhook`. The URL must use HTTPS. * Method `POST` 3. Copy the Webhook Secret. You don't need to generate it yourself. Fintoc creates the Webhook Secret automatically when you save the webhook. To find the Webhook Secret later, open that webhook's settings in the Dashboard. For more details, see [Activate your webhook endpoint](/guides/resources/webhooks-walkthrough/webhooks-activating). 4. Paste the Webhook Secret into your Magento Fintoc settings (Stores → Configuration → Sales → Payment Methods → Fintoc → Basic Settings → Webhook Secret). 5. Test delivery in Fintoc and verify Magento responds with `200 OK`. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d7f2612e2fd38027bf8901de365f37c8473a6803f3ef63f9a81b13e436c14d3b-Screenshot_2025-10-10_at_3.36.08_PM.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=93906dee8e1022845fd50ac463d05c9c) ### Best practices * Keep logging enabled in production at a reasonable Debug Level. Avoid logging sensitive data unless requested by support. * Verify that your server is publicly reachable by Fintoc for webhooks (firewalls, maintenance mode, IP allowlists). * If customers report missing payment method, check country restrictions and maximum order amount settings. ### Troubleshooting Here are some issues you might encounter and how to solve them. | Issue | Cause | Solution | | :- | :- | :- | | 401/400 Webhook errors | Invalid Webhook Secret | Recheck the secret in both Fintoc and Magento | | 5xx Webhook errors | Server unreachable or internal error | Check logs in var/log/fintoc.log | | Payment not showing | Disabled, restricted, or over limit | Verify settings under Payment Methods | | Refund not processed | Webhook delivery issue | Check refund settings and webhook logs | ### Support * Provide recent entries from var/log/fintoc\*.log when contacting support. * Share the order increment ID and (if available) the Fintoc transaction\_id for faster diagnosis. ## Testing 1. In Fintoc's app, switch to Test mode by using the checkbox to test payments without affecting live orders. 2. Place test orders to ensure that payments are processed correctly. For more information on testing, [refer to our testing guidelines](/guides/payments/payment-initiation-test-your-integration). ## Go live 1. Once you're satisfied with testing, switch the app to Live or Production mode by unchecking the checkbox. 2. Test a few more orders in the live environment to ensure everything is functioning as expected. Your Magento store is now set up to accept payments through Fintoc. ## FAQs **Q: How do I handle refunds and disputes?** A: Refunds can be managed directly within your Magento dashboard. Navigate to an Order, where you'll find a Refund button on the top-right corner. Here, you can input the refund amount and any comments you wish to track. For more details on how refunds work in Fintoc, [consult our Refunds Guide](/guides/payments/fintoc-collect-payments/payment-initiation-refunds). > [!WARNING] > > **Refunds for E-Commerce Plugins** > > You can **issue** refunds directly from your e-commerce platform (Magento, VTEX, Shopify), but due to how the plugins work, **refunds requested from e-commerce plugin platforms cannot be cancelled from their dashboards**. > > If you issued a refund from one of these platforms and wish to cancel it, you can use our [Cancel Refunds](/api/payments-api/refunds/refunds-cancel) API endpoint or contact our support team, but note that **the cancellation will not be reflected in your Magento, VTEX or Shopify Dashboard** # Shopify Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/shopify Accept payments with Fintoc in your Shopify store in Mexico and Chile. Install the app, register your company, and manage payouts and refunds. By the end of this guide, you'll have Fintoc activated as a payment method in your Shopify store's checkout. ## Who can use Fintoc To use Fintoc, your business must meet all of these requirements: * **A company tax ID.** In Mexico, this is your company's Mexican tax ID (RFC), which has 12 characters. In Chile, this is your company's Chilean tax ID (RUT). * **A bank account in your company's name.** Fintoc only sends your payouts to an account associated with your company's RFC or RUT. * **An email address on your company's domain.** Sign up with a corporate email, not a personal one such as Gmail or Hotmail. Fintoc doesn't accept individuals, including a natural person with business activity (persona natural con giro). Your company also needs at least 6 months of business activity, counted from the start date on your business initiation certificate. If your company is younger, the Dashboard shows an error when you upload the certificate and you can't complete the onboarding. > [!NOTE] > > A Fintoc organization that you register through the Shopify app can only accept payments in Shopify. You can't use that organization with the API or with other e-commerce plugins, such as WooCommerce or VTEX. To accept payments in another store or integration, complete a separate registration with Fintoc's sales team at [sales@fintoc.com](mailto:sales@fintoc.com). ## I. Install the Fintoc app on Shopify 1. Click on your country's link to begin: * 🇲🇽 [Fintoc App Mexico](https://apps.shopify.com/fintoc-mexico?locale=es) * 🇨🇱 [Fintoc App Chile](https://apps.shopify.com/fintoc) 2. Click "Install" and follow the setup instructions. ## II. Follow the steps and set up your Fintoc account If this is your first time using Fintoc on Shopify, you will need to create an account on the Dashboard. If you already have an account, log in with it to continue. ## III. Complete your company details Within the Dashboard, we will ask you for some information to activate your account. **Mexico:** * Tax status certificate * Legal representative ID * Bank statement cover page * Company incorporation deed * Mexican tax ID (RFC) * Legal name and trade name * Tax address * Bank account where you want to receive your payments **Chile:** * Business initiation certificate * Chilean tax ID (RUT) * Legal name and trade name * Address and district * Business activity * Bank account where you want to receive your payments ## IV. Activate Fintoc on Shopify Finally, once you confirm your details, all that's left is to activate Fintoc in your Shopify store. Your customers can now pay through Fintoc, and you receive your payments with lower fees. 🤘 ## Receiving your payouts Fintoc sends the funds you collect in Shopify to the bank account you registered. To change that account, see [Updating your bank account information](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#updating-your-bank-account-information). To understand why a payout shows as canceled, see [Canceled payouts](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#canceled-payouts). ## FAQs If you have any questions, check out our [Shopify FAQ section](https://intercom.help/fintoc/es/articles/11825279-integracion-con-shopify). **Q: A customer says their bank debited them, but the payment failed or doesn't appear. What should I do?**\ A: You don't need to issue a refund. Fintoc automatically returns the money to the account it came from. See [Failed payments where the payer was debited](/guides/payments/fintoc-collect-payments/dealing-with-payment-exceptions#failed-payments-where-the-payer-was-debited). ## Refunds Refunds can be managed directly from your Shopify dashboard. Navigate to an Order, where you'll find a Refund button on the top-right corner. There you can enter the refund amount and any comments you wish to track. For more details, check out our [Refunds Guide](/guides/payments/fintoc-collect-payments/payment-initiation-refunds). > [!WARNING] > > You can **issue** refunds directly from Shopify, but refunds requested from e-commerce plugins **cannot be cancelled from their dashboards**. If you issued a refund from Shopify and wish to cancel it, you can use our [Cancel Refunds](/api/payments-api/refunds/refunds-cancel) endpoint or contact our support team. Note that the cancellation will not be reflected in your Shopify Dashboard. If your available Fintoc balance doesn't cover a refund within 5 business days, the refund transitions to `failed`. A `failed` refund is final, and Fintoc can't retry it. To refund the customer, create the refund again from the order in Shopify. Shopify registers the new refund in Fintoc automatically. For details on how Fintoc funds refunds, see [Available refund balance](/guides/payments/fintoc-collect-payments/payment-initiation-refunds#available-refund-balance). # VTEX (Chile only) Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/vtex Configure Fintoc's payment plugin in your VTEX store in Chile: get your API keys, enable the plugin, and adjust the connector name and decimal settings. Fintoc's VTEX plugin is available only in Chile. Use this guide to configure Fintoc's payment plugin in your VTEX store so your customers can pay without leaving checkout. # Getting started: credentials and setup ### 1. Sign up To initiate the process, head to [Fintoc's dashboard and sign up](/guides/home/dashboard/guides-api-keys). Once you've completed this step, you can start testing out payments using our Test mode. To start receiving payments in Live mode, reach out to your dedicated sales representative or contact us at [sales@fintoc.com](mailto:sales@fintoc.com) to facilitate account activation and provide you with the necessary credentials. ### 2. Obtain API keys Within your Fintoc dashboard, you will find both Test and Live API Keys. These keys are vital for configuring the plugin within your VTEX environment. To get your Live API Keys, make sure you are in Live mode by checking the button on the bottom left of our dashboard. Then, head over to For Developers → API Keys to obtain them. # Integration and configuration process ## Enabling the plugin in your VTEX store Follow these steps to activate Fintoc's plugin within your VTEX store: 1. **Log in** to the VTEX admin platform using your credentials. 2. From the side menu, select the Store Settings icon located at the bottom of the screen. 3. Within the settings, navigate to **PAYMENT: Providers**. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/e12ad85-Group_2337_1.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=5d02e86f1c349117efa7e40fdc60e700) 4. Click on the "New Provider" button to add a new payment provider. 5. Look for **Fintoc** and choose it from the list. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/63f1414-Group_2338_1.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=8f22eccf705ba74678cfec3013d2e8d5) 6. Complete the Configuration options as follows: 1. Enter your **Live Mode Public Key**, which can be located in your Fintoc dashboard, into the Application Key field. 2. Similarly, insert your **Live Mode Secret Key** from your Fintoc dashboard into the Secret Key field. 3. You can insert \***\*\*\*\***\*\*\*\*\* into the Application Token field or leave it blank. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/414b3a1-Group_2339.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=43e32d53c13cae237243a9d5081ad931) 7. To use Test mode, select the **Enable test mode** checkbox and enter your **Test Mode API Keys** 1. When using Test mode, you can try out your integration following the instructions [you can find here](/guides/payments/payment-initiation-test-your-integration). 8. Deactivate the **Enable test mode** checkbox and change your API Keys back to Live to switch to Live mode. 9. Confirm your choices by clicking the **Save** button. 10. Your VTEX store is now fully equipped to process payments via Fintoc. ## Payment configuration ### Change connector's name To improve checkout clarity, change the connector name to **"Pay with your bank" ("Paga con tu banco")** so customers recognize Fintoc as a bank payment method. To do so, you can follow VTEX's guide on [changing payment method names](https://developers.vtex.com/docs/guides/change-payment-method-names-in-checkout). ### Decimal inconsistencies For those setting up a store in Chile, it's essential to make specific adjustments to avoid decimal-related inconsistencies in payments and reconciliations. Here's how to do it: 1. Navigate to **VTEX Store Settings**. 2. Select **ORDERS: Settings**. 3. Within the General section, locate the Cart settings and adjust the **Number of decimal digits to be considered** to **0**. 4. Finalize the process by clicking the **Save button**. > [!WARNING] > > **Refunds for E-Commerce Plugins** > > You can **issue** refunds directly from your e-commerce platform (VTEX or Shopify), but due to how the plugins work, **refunds requested from e-commerce plugin platforms cannot be cancelled from their dashboards**. > > If you issued a refund from one of these platforms and wish to cancel it, you can use our [Cancel Refunds](/api/payments-api/refunds/refunds-cancel) API endpoint or contact our support team, but consider that **the cancellation will not be reflected in your VTEX or Shopify Dashboard**. # Accept payments with WooCommerce Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/woocommerce Set up the Fintoc plugin in your WooCommerce store to accept bank transfer, card, and cash payments, configure webhooks, and manage order statuses and refunds. Set up Fintoc in your WooCommerce store to accept account-to-account **bank transfer**, **card**, and **cash** payments through Fintoc's hosted Checkout Session. Bank transfers and cards support **Chilean pesos (CLP)** and **Mexican pesos (MXN)**. Cash payments are available in Mexico. When your customer places an order, Fintoc redirects the customer to authorize the payment. After the customer returns to your store, the plugin confirms the order in the background with webhooks. The plugin verifies every event against the Fintoc API, which is the source of truth for the payment status. ## Prerequisites Before you start, you need: * A Fintoc account with an API secret key. To get one, contact your sales representative or write to [sales@fintoc.com](mailto:sales@fintoc.com). Fintoc then activates your account and gives you access to the [Fintoc dashboard](https://dashboard.fintoc.com/login). If you registered your existing Fintoc organization through the [Shopify app](/guides/payments/e-commerce-connectors/shopify), you can't use that organization here. Shopify organizations can only accept payments in Shopify, so your WooCommerce store needs its own registration. * Admin access to your WordPress site. * WordPress 6.2+, WooCommerce 7.4+, and PHP 7.4+. ## Get your API credentials Your Fintoc dashboard shows both `test` and `live` secret keys. To get them, go to **For Developers → API Keys**. Use the button on the top left of the dashboard to switch between `test` and `live` modes. **Use your `live` secret key (`sk_live_...`) to set up Fintoc in production.** ## Install the plugin Install the plugin from the WordPress plugin directory: 1. In your WordPress admin, go to **Plugins → Add New**. 2. Search for **Fintoc for WooCommerce**, then select **Install Now**. 3. Select **Activate**. To install it manually instead, download the ZIP from the plugin's [WordPress.org page](https://wordpress.org/plugins/fintoc-for-woocommerce/) and upload it from **Plugins → Add New → Upload Plugin**. Either way, WordPress offers new versions of the plugin under **Plugins**, like any plugin from the directory. The plugin is compatible with High-Performance Order Storage (HPOS) and works with both the classic checkout shortcode and the Blocks (Store API) checkout. ## Configure the plugin 1. Go to **WooCommerce → Settings → Payments → Fintoc**. 2. In the settings screen, configure: * **Enable Fintoc**: the toggle that turns the gateway on. * **Title**: the payment method name shown to customers at checkout. Leave it empty so the plugin names the payment methods enabled for your organization. For example, a Mexican organization with Interbank Electronic Payment System (SPEI) transfers, cards, and cash shows `Pay with SPEI, card or cash`. That text matches what the plugin writes. If you write a title, the checkout always shows that title. * **Description**: the text shown under the payment method at checkout. Leave it empty to use the default description. * **Test mode**: the toggle that uses your test secret key; leave it off to take live payments. * **Live secret key**: your `sk_live_...` key from the dashboard. * **Test secret key**: your `sk_test_...` key, needed only while test mode is enabled. * **Debug log**: the toggle that logs API requests and webhook events under **WooCommerce → Status → Logs** (source `fintoc`). 3. Save changes. The gateway hides itself automatically when the store currency is anything other than CLP or MXN. The **Payment methods** panel on the settings screen shows which methods your Fintoc organization has enabled: bank transfers, cards, and cash in Mexico. Fintoc manages method enablement per organization. You cannot enable payment methods yourself. The plugin learns your organization's payment methods from the first Checkout Session. Until your first order, an empty **Title** shows `Fintoc`. After that, the checkout shows the payment methods and one logo for each. ### Webhook setup The plugin uses webhooks to confirm payments, so this step is required. 1. On the Fintoc settings screen in WooCommerce, copy the **Webhook endpoint** URL shown there. 2. In your [Fintoc dashboard](https://dashboard.fintoc.com/login), create a new webhook endpoint with that URL and method `POST`. 3. Subscribe the endpoint to the `payment_intent.*`, `checkout_session.*`, and `refund.*` events. The plugin uses these events to confirm payments and reconcile refunds. You do not need a webhook secret. Before updating an order, the plugin fetches the payment state directly from the Fintoc API. The plugin uses the webhook payload only to locate the order. ## Order statuses A bank transfer is not always confirmed in seconds. Depending on the bank, the transfer can take minutes, hours, or days. The plugin reflects that wait in the order status. Expect to see **On hold** whenever your customer returns to your store before Fintoc confirms the payment: | WooCommerce status | What it means | | :- | :- | | **Pending payment** | The order is waiting for payment. Your customer has not completed the payment yet. | | **On hold** | Fintoc is validating the payment. | | **Processing** | The payment succeeded, and Fintoc collected the money. | | **Failed** | The payment failed, was rejected, or expired. | ### Orders on hold While an order sits in **On hold**, the plugin protects it: * WooCommerce does not cancel orders in **On hold**. WooCommerce cancels orders in **Pending payment** once they have been unpaid for longer than the **Hold stock (minutes)** setting, 60 minutes by default. Find that setting under **WooCommerce → Settings → Products → Inventory**. * The order reserves its stock, so the products do not sell out to someone else while Fintoc validates the payment. * The customer cannot start a second payment for the same order, so they cannot pay twice. Do not cancel these orders by hand. The plugin resolves each one once Fintoc confirms the outcome: **Processing** when the payment succeeds, **Failed** when it does not. On failure, the plugin restores the stock the order had reserved. Webhooks are the primary signal. As a fallback, the plugin also fetches the payment from the Fintoc API on a schedule. The first retry runs 15 minutes after the order goes on hold. Later retries back off to once a day. The plugin stops after 10 retries, about four days after the order goes on hold. If the payment is still unresolved, the plugin leaves a note on the order and waits for the webhook. Fintoc expires a payment that never confirms, so the order does not sit in **On hold** forever. > [!NOTE] > > Your customer receives WooCommerce's standard **Order on-hold** email when Fintoc starts validating the payment. To disable the email, go to **WooCommerce → Settings → Emails → Order on-hold**. ### Cash payments in Mexico When your customer chooses cash, Fintoc gives them a voucher to pay at a store. When your customer returns to your store, the order received page shows a notice with a link to the voucher. The order stays in **On hold**, with its stock reserved, until your customer pays at the store or the Checkout Session expires, 24 hours by default. The plugin then moves the order to **Processing** or **Failed**. ### Duplicate payments If a second payment succeeds for an order that is already paid, the plugin leaves a note on the order, logs an error, and emails the store admin. The money moved twice, so refund the duplicate payment from the [Fintoc dashboard](https://dashboard.fintoc.com/login). ## Manage refunds You can issue full and partial refunds directly from the WooCommerce order screen. Open the order, select **Refund**, enter the amount, and submit. The plugin sends the request to the Fintoc Refunds API and reconciles the outcome through the `refund.*` webhook events. Refund confirmation times vary by country. For bank transfers, Fintoc may retry for up to 7 days when there is insufficient balance, so a refund can stay pending until Fintoc confirms the refund. > [!WARNING] > > You can **issue** refunds directly from WooCommerce, but you **cannot cancel those refunds** there. To cancel a refund issued from WooCommerce, use the [Cancel Refunds](/api/payments-api/refunds/refunds-cancel) endpoint or contact support. WooCommerce does not show the cancellation. ## Test the integration 1. Enable **Test mode** on the settings screen and paste your test secret key (`sk_test_...`). 2. Place a test order with each enabled payment method and complete the authorization in Fintoc's sandbox. After a successful payment, the plugin moves the order to **Processing** and records the matching `payment_intent.*` and `checkout_session.*` webhook events. For test credentials and sandbox details, see [Test your integration](/guides/payments/payment-initiation-test-your-integration). 3. Enable **Debug log** and review **WooCommerce → Status → Logs** (source `fintoc`) to inspect API requests and webhook events. ## Go live 1. Confirm that Fintoc has activated Payments for your organization. Until then, `live` checkouts fail with `Missing required param: payment_method_options.bank_transfer.recipient_account`. 2. After testing each enabled payment method, disable **Test mode** so the gateway uses your `live` secret key. 3. Place one order in `live` mode with each enabled payment method to confirm the full end-to-end flow. Your WooCommerce store now accepts payments through Fintoc. ## Troubleshooting Common issues and their fixes: | Issue | Cause | Solution | | :- | :- | :- | | Fintoc not showing at checkout | Store currency is not CLP or MXN, or the gateway is disabled | Verify the store currency and that the gateway is enabled | | Orders not confirming | Webhook endpoint not registered or unreachable | Register the endpoint and subscribe to `payment_intent.*` and `checkout_session.*` | | Refunds never confirm or revert | `refund.*` events not subscribed | Subscribe the webhook endpoint to `refund.*` | | Cross-mode refund error | Order paid in `test`, gateway in `live` (or vice versa) | Set the gateway to the mode used to pay for the order | | WooCommerce canceled orders while Fintoc was still validating the payment | Plugin older than `1.2.4` | Update the plugin from **Plugins** in your WordPress admin | | `This organization is not allowed to create payments through the API` | The secret key belongs to an organization registered through Shopify. Those organizations can only accept payments in Shopify | Register a separate organization for your WooCommerce store. Contact [sales@fintoc.com](mailto:sales@fintoc.com), then use that organization's secret key in the plugin | | `Missing required param: payment_method_options.bank_transfer.recipient_account` | Payments isn't activated yet for your organization, so it has no collection account to receive bank transfers | Complete your organization's onboarding and business requirements, then contact [sales@fintoc.com](mailto:sales@fintoc.com) to activate Payments. After activation, retry the checkout | ## Frequently asked questions **Q: Which currencies are supported?** A: CLP and MXN. The gateway hides itself automatically when the store currency is anything else. **Q: Do I need a webhook secret?** A: No. The plugin verifies every event by fetching the payment state directly from the Fintoc API before updating an order. You do not configure a webhook secret in the plugin or in the dashboard. **Q: Is the Blocks checkout supported?** A: Yes. The plugin supports both the classic shortcode checkout and the Blocks (Store API) checkout. **Q: Why is an order in On hold?** A: Fintoc is validating the payment. Bank transfers can take hours or days to confirm. The plugin moves the order to **Processing** or **Failed** once Fintoc confirms the outcome. Do not cancel the order by hand. The order reserves its stock, and the customer cannot pay again while the order waits. **Q: Why does a customer receive an order on-hold email?** A: WooCommerce sends that email whenever an order moves to **On hold**, which now happens while Fintoc validates the payment. To turn it off, go to **WooCommerce → Settings → Emails → Order on-hold**. **Q: A customer says their bank debited them, but the order is Failed. Do I need to refund them?** A: No. Fintoc automatically returns the money to the account it came from. See [Failed payments where the payer was debited](/guides/payments/fintoc-collect-payments/dealing-with-payment-exceptions#failed-payments-where-the-payer-was-debited). # Checking payment eligibility Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/check-payment-eligibility Check whether a Fintoc Collect payment is likely to succeed by calling the check_eligibility endpoint or passing a sender_account when creating the session. Pre-validating a payment intent helps reduce the chance of payments failing due to transfer limits. There are two ways to check a payment's eligibility: * Using the `payment_intents/check_eligibility` endpoint to check eligibility before showing a user the accepted payment methods. * Including a `sender_account` object when creating a Checkout Session or Payment Intent to check when a user selects Fintoc as a payment method. When creating a payment intent, you can include a `sender_account` object in your request. This object allows you to specify the sender's account details, enabling our system to perform more accurate validations based on general transfer limits and previous transactions through Fintoc. **This feature is only available in Chile**. ## Using the `payment_intents/check_eligibility` endpoint If you want to check a payment's eligibility before showing a user the accepted payment methods, you can use the following endpoint: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/payment_intents/check_eligibility \ --header 'Authorization: sk_test_0000000000000000' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 1000, "currency": "CLP", "sender_account": { "holder_id": "111111111", "institution_id": "cl_banco_estado" } }' ``` The `sender_account` object contains two fields: * `holder_id`: The RUT (Rol Único Tributario) of the account holder * `institution_id`: The [ID](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions#available-sender-banks) of the bank institution Mixing these fields will help you validate certain limits: * If you only send the `institution_id` and no `holder_id`, Fintoc will only validate bank-specific limits for maximum and minimum transfer amounts. * If you send both, Fintoc will perform all validations for the payment intent. If the payment is eligible, this endpoint will respond with the following object: ```json JSON theme={null} { "eligible_payment": true, "error": null } ``` If it isn't valid it will respond with one of the error responses like this: ```json JSON theme={null} { "eligible_payment": false, "error": { "type": "new_contact_error", "message": "The amount exceeds the maximum amount permitted for new contacts. For #{institution_name}, the maximum permissible amount is $250,000. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` ## Including a `sender_account` object when creating a Checkout Session When making a POST request to creating a Checkout Session, include the `sender_account` object in your JSON payload. Here's an example: ```json theme={null} { "amount": 1000, "currency": "CLP", "metadata": { "order": "#987654321" }, "customer_email": "customer@example.com", "payment_method_options": { "bank_transfer": { "sender_account": { "holder_id": "111111111", "institution_id": "cl_banco_estado" } } } } ``` The `sender_account` object contains two fields: * `holder_id`: The RUT (Rol Único Tributario) of the account holder * `institution_id`: The [ID](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions#available-sender-banks) of the bank institution Mixing these fields will help you validate certain limits: * If you only send the `holder_id` and no `institution_id`, Fintoc will use general limits for new contacts allowing more payments to go through without incorrectly canceling any. * If you only send the `institution_id` and no `holder_id`, Fintoc will only validate bank-specific limits for maximum and minimum transfer amounts. * If you send both, Fintoc will perform all validations for the payment intent. > [!WARNING] > > **Use the Same Holder ID** > > When setting up the widget to pre-fill a username, use the same holder\_id as for pre-validating payments. This ensures consistency and helps prevent payment failures. ## Validation process When you include the `sender_account` information, our system performs several checks to validate the payment intent: 1. **Institution-specific limits**: We check if the payment amount is within the allowed limits for the specified institution. 2. **New contact limits**: For first-time transfers or transfers within 24 hours of the first transfer, institutions apply stricter limits. 3. **Maximum transfer amounts**: We ensure the payment doesn't exceed the maximum allowed transfer amount for the specified bank. ## Error responses If a validation fails, you'll receive one of the following error responses: 1. **New contact maximum amount limit error**: Fintoc first checks if the `holder_id` has made a transfer. If not, it then checks if the amount exceeds the institution's limit. ```json theme={null} { "error": { "type": "new_contact_error", "message": "The amount exceeds the maximum amount permitted for new contacts. For #{institution_name}, the maximum permissible amount is $250,000. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 2. **New contact payment number limit error**: Fintoc first checks if the `holder_id` has made their first transfer during the same day. If they have, it then checks if the institution allows for more than one transfer to a new contact. ```json theme={null} { "error": { "type": "new_contact_error", "message": "The maximum number of transfers for new contacts in #{institution_name} was reached. This restriction ends at 2024-08-20T16:08:28Z", "code": "new_contact_payment_number_limit_error", "param": "sender_account", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 3. **Minimum amount limit error**: Fintoc checks if the amount is lower than the minimum allowed by the institution. ```json theme={null} { "error": { "type": "amount_error", "message": "The amount is lower than the minimum amount permitted for payments by #{institution_name}. Please enter an amount greater than $1000.", "code": "minimum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` 4. **Maximum amount limit error**: Fintoc checks if the amount exceeds the maximum amount allowed by the institution. ```json theme={null} { "error": { "type": "amount_error", "message": "The amount exceeds the maximum amount permitted for payments by #{institution_name}. Please enter an amount less than $70000000.", "code": "maximum_amount_limit_error", "param": "amount", "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` ## Best practices 1. Always include the `sender_account` information when creating a Checkout Session to ensure the most accurate validations. 2. Handle error responses gracefully in your application, providing clear feedback to your users about why a payment couldn't be processed. 3. Make adjustments to your order so users are able to pay. These could be changing the payment amount if possible or setting up reminders for future payments. # Handling payment exceptions Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/dealing-with-payment-exceptions When you manage payments, some cases require action to reconcile the payment and keep customers informed. ## Pending payments Pending payments are instances where Fintoc cannot provide a definitive status of the payment at the moment. These payments can either succeed or fail at a later time, depending on various factors and your process for handling them might depend on your payment scheme and API version. ### How to deal with pending payments If you’ve integrated pending payments, they will remain in a pending state until Fintoc can provide a conclusive status update. In this scenario, you have the flexibility to handle the payment according to your business requirements: | Action | Description | | - | - | | Return of funds | If the payment later succeeds, refund the funds to your customer's bank account; if it fails, you don't need to issue a refund. If you use Refunds, request one when the payment succeeds; see [Failed payments where the payer was debited](#failed-payments-where-the-payer-was-debited). | | Fulfill their order | Notify your client that their order is complete, but you are awaiting the final payment status before fulfilling it. | Allowing customers to wait for the payment to complete will enhance their experience if the funds were transferred, and you won't need to capture the payment again. > [!WARNING] > > **Pause internal processes** > > We strongly advise you to pause any internal processes that may affect the payment completion, such as charging interest on debts or canceling contracts, until the payment is finalized. If the payment is validated as successful or failed, Fintoc will send a webhook (`payment_intent.succeeded` or `payment_intent.failed`) notifying the final status of the payment. Fintoc will attempt to validate pending payments for up to 10 days. If the payment cannot be verified in that time, you will receive a `payment_intent.failed` webhook with a distinct error reason (`unresolved_final_status`). #### Previous API versions In previous versions of our API, there is no pending state for payments, resulting in these payments always having a failed status. **In such cases, if the funds were indeed transferred, Fintoc will return these funds to your customer within a maximum of 2 business days** (Only under [Fintoc Collects schema](/guides/payments/overview-payment-initiation/payments-use-cases)). ## Failed payments where the payer was debited Sometimes a payment intent shows as `failed` in your dashboard, or your order doesn't show a payment. Your customer may still say their bank already took the money. This happens when Fintoc receives the transfer but can't apply it to the payment. For example: * Fintoc couldn't confirm the transfer while the payment was in progress. * Your customer transferred a different amount than the one requested. * Your customer transferred from another person's or company's account. * Your customer transferred after the payment window closed. In these cases, the payment intent ends as `failed` and Fintoc automatically returns the money to the account it came from. You don't need to issue a refund. Your customer sees the return in their bank account as a deposit under Fintoc's name within 2 business days after Fintoc receives the transfer. This applies under the [Fintoc Collects schema](/guides/payments/overview-payment-initiation/payments-use-cases). ### What to tell your customer Tell your customer that the payment failed and that Fintoc returns the money automatically to the account it came from. To complete their purchase, they must start a new payment from your checkout. To avoid another failed payment, ask them to: 1. Start the payment from your checkout and transfer only when the payment window asks them to. 2. Transfer only from the account that belongs to the Chilean tax ID (RUT) holder they entered. 3. Transfer the exact amount shown in the payment window. ### When your customer disputes a charge If your customer says their bank debited the money and they haven't received it back, contact Fintoc support with: * The Fintoc payment ID (`pi_...`) or the RUT of the account holder who paid. * The full transfer receipt issued by the customer's bank. A screenshot of the activity in a banking app isn't enough, because it doesn't confirm that the bank completed the charge. Fintoc support can share a receipt of the return transfer as proof that Fintoc returned the money. ## Unmatched Direct Transfers If a user pays with [Direct Transfer](/guides/payments/direct-transfer) and Fintoc can't link the transfer to a payment intent, the order shows as expired. The transfer doesn't appear in your logs. Fintoc refunds these transfers automatically to the origin account. To learn how matching works and what to tell your users, see [How Fintoc matches a transfer to a payment in Chile](/guides/payments/direct-transfer#how-fintoc-matches-a-transfer-to-a-payment-in-chile). # Fintoc collects Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/index Learn how Fintoc collects payments on your behalf. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/52c586cf0c023d2839f166654a4c6b399dd66bd3fa0ad65e53746bc5f23e0209-Presentacion_sin_titulo.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=283d541a24f72f3975c00f98ac78907d) When Fintoc collects your payments, the funds go to a bank account that Fintoc manages. Fintoc tracks each payment and reconciles it after settlement. Fintoc also handles payments sent to this account through external channels, such as bank transfers. Fintoc then sends the funds to your bank account according to your [payout schedule](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts). Fintoc deducts fees directly from your payouts. This integration has the following advantage and disadvantage: | Advantage | Disadvantage | | - | - | | Fintoc tracks and reconciles your payments and handles external bank transfers for you. | The funds reach your bank account after a delay and may arrive on the next business day. See the [receiving payouts guide](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts). | Use this integration to receive payments without tracking reconciliation or handling external bank transfers. # Receiving payouts Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts Add your bank account, pick a payout schedule, see how Fintoc groups payments into daily payouts, and turn the settlement email on or off from the Dashboard. For you to receive funds, Fintoc makes payouts to your bank account. In Chile, one payout covers every payment method Fintoc collects with on your behalf: bank transfers, cards, installments, and payment buttons. Fintoc disburses recurring charges in a separate payout. Payout availability depends on the country where you operate. Fintoc processes payouts according to your chosen [payout schedule](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#payout-schedule). Fintoc deducts fees from each daily payout based on your pricing plan. For more details on how Fintoc calculates fees, see the [Fintoc Fees Guide](/guides/payments/fintoc-fees). ## Adding your bank account information You need to have a bank account located in the country you are operating in. Fintoc does not support cross-border payouts. The bank account owner also needs to be the company that signed the contract with Fintoc. ### Accepted account types The following account types can receive payouts: | Country | Accepted account types | | :- | :- | | Chile | Cuenta corriente (checking account) or cuenta vista (sight account) | | Mexico | Bank account identified by its standardized Mexican bank account number (CLABE) | The account holder's Chilean tax ID (RUT) or Mexican tax ID (RFC) must match the tax ID of your Fintoc organization. The account type doesn't change this rule. Fintoc rejects personal accounts held under an individual's tax ID, even when that person is the company's sole owner or legal representative. ### Updating your bank account information To change the bank account that receives your payouts, or to correct its details, contact your Account Executive. If you don't have an Account Executive, contact Fintoc support from the chat in your [dashboard](https://dashboard.fintoc.com) or at [soporte@fintoc.com](mailto:soporte@fintoc.com). Use support if you signed up through the [Shopify app](/guides/payments/e-commerce-connectors/shopify). Send the following details for the new account: * Account holder's legal name * Account holder's Chilean tax ID (RUT) or Mexican tax ID (RFC), which must match the tax ID of your Fintoc organization * Bank * Account type * Account number The new account must belong to the same company tax ID (RUT in Chile, RFC in Mexico) you registered with Fintoc. Fintoc can't send payouts to an account owned by a different person or company. Once Fintoc confirms the change, the next payouts go to the new account. ## Canceled payouts A payout shows as canceled (`canceled`, or "cancelado" in the Spanish dashboard) when Fintoc tried to send it and the transfer to your bank account failed. The most common reasons are: * **Invalid bank account details.** Your bank rejected the transfer because the registered details, such as the tax ID, the account number, or the relationship between the two, don't correspond to a valid account. * **Monthly deposit limit reached.** Some bank accounts have a monthly limit on deposits. Once your account hits that limit, your bank rejects new transfers until the limit resets, usually at the start of the next month. When a payout is canceled, you don't lose the funds. Fintoc keeps the amount and adds it to your next payout attempt. Each later payout includes the pending balance plus that day's payments, until a transfer succeeds. Because of this, don't add up the amounts of your canceled payouts. The successful payout already includes them. To resume your payouts: * If the account details are invalid, [update your bank account information](#updating-your-bank-account-information). Fintoc sends the accumulated balance in a later payout to the corrected account. * If your account reached its monthly deposit limit, Fintoc retries the pending payouts once the limit resets. You can also change to another account that belongs to your company. Fintoc sends a `payout.canceled` [webhook](#webhooks) every time a payout is canceled. ## Small payments and fixed fees If your pricing plan includes a fixed fee per transaction, payments below that fixed fee may not generate a payout. When the fees are equal to or greater than the amount you collected, the net amount is zero or negative, so Fintoc has nothing to send. Once you collect payments that cover the fees, Fintoc resumes your payouts as usual. See the [Fintoc fees guide](/guides/payments/fintoc-fees) to learn how Fintoc calculates fees. ## Payout schedule Your payout schedule refers to how often Fintoc sends money to your bank account. You can see the available payout schedules by country below. > [!NOTE] > > **Payout schedule time zones** > > Fintoc processes all payments and payouts according to the local time zone. ### Chile Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. In Chile, Fintoc has two payout schedules available. | Payout schedule | Cut-off time | Payout speed | | :- | :- | :- | | Daily with banking cut-off time | 14:00 | \<1 business day | | Daily with business days cut-off time | 00:00 | 1 business day | The default payout schedule is **daily with banking cut-off time**. To change your payout schedule, contact your Account Executive. #### Daily with banking cut-off times | Day of the week | Funds available on | | :- | :- | | Monday 14:00 to Tuesday 13:59 | Tuesday before 19:00 | | Tuesday 14:00 to Wednesday 13:59 | Wednesday before 19:00 | | Wednesday 14:00 to Thursday 13:59 | Thursday before 19:00 | | Thursday 14:00 to Friday 13:59 | Friday before 19:00 | | Friday 14:00 to Monday 13:59 | Monday before 19:00 | #### Daily with business days cut-off times | Day of the week | Funds available on | | :- | :- | | Monday 00:00 to Monday 23:59 | Tuesday before 19:00 | | Tuesday 00:00 to Tuesday 23:59 | Wednesday before 19:00 | | Wednesday 00:00 to Wednesday 23:59 | Thursday before 19:00 | | Thursday 00:00 to Thursday 23:59 | Friday before 19:00 | | Friday 00:00 to Sunday 23:59 | Monday before 19:00 | ### Mexico In Mexico, Fintoc supports only one payout schedule. | Payout schedule | Cut-off time | Payout speed | | :- | :- | :- | | Daily with business days cut-off time | 00:00 | 1 business day | #### Daily with business days cut-off times | Day of the week | Funds available on | | :- | :- | | Monday 00:00 to Monday 23:59 | Tuesday before 15:00 | | Tuesday 00:00 to Tuesday 23:59 | Wednesday before 15:00 | | Wednesday 00:00 to Wednesday 23:59 | Thursday before 15:00 | | Thursday 00:00 to Thursday 23:59 | Friday before 15:00 | | Friday 00:00 to Sunday 23:59 | Monday before 15:00 | ## Payout notifications When the Settlement email toggle is on, Fintoc sends you an email with the [payout reconciliation report](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation#the-payout-reconciliation-report) for each payout Fintoc makes to your bank account. See the [reporting and reconciliation guide](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation) to learn more. Settings in your [dashboard](https://dashboard.fintoc.com) has a Settlement email toggle in the Communication tab. Turn the toggle on to receive this email, off to stop receiving it. What to know about the toggle: * **Who receives the email:** the operational email in the Communication tab. When you set no operational email, Fintoc sends the email to your organization's main email. * **Starting state:** organizations that already received the email keep the toggle on. New organizations start with the toggle off. * **What the toggle covers:** payout emails for bank transfers, cards, and the separate payout for recurring charges. * **Who can change it:** a user with the Manage access level on Organization settings. See [Permission roles](/guides/home/dashboard/permission-roles). ## Using the Dashboard You can see all past and future payouts from your [dashboard](https://dashboard.fintoc.com) by selecting the **Payouts** tab in the left sidebar. ## Using the Payouts API The Payouts API lets you manage payouts through these endpoints: * **List Historical Payouts:** Retrieve a list of all historical payouts. * **Retrieve Specific Payout:** Fetch details of a specific payout. * **Get Payout Resources by Type:** Access all the resources included in a payout. * **Webhooks:** Receive notifications when a payout starts processing and when it arrives in your bank account. You can get more information about [each method in our API Reference](/api/payments-api/payouts/payout-object). ### Webhooks Fintoc employs webhooks to keep you informed throughout the payout process. Here are the key events we trigger: | Event | Description | | :- | :- | | `payout.created` | Sent when a payout is created and starts processing. | | `payout.succeeded` | Sent when a payout is successfully transferred to your bank account. | | `payout.canceled` | Sent when a payout transfer fails. See [Canceled payouts](#canceled-payouts). | | `payout.returned` | Sent when your bank returns a previously successful payout in Mexico. Fintoc includes the resources from that payout in the next payout. | # Refund payments Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/payment-initiation-refunds Refund a Fintoc Collect payment through the Payment Intent API, including partial and full refunds and how to track refund status with webhooks. You can partially or fully refund any successful bank transfer or card payment. Fintoc doesn't support refunds for [cash payments](/guides/payments/cash-payment-direct-api#refunds). Refunds draw from your available Fintoc balance, which excludes pending funds. If your available balance doesn’t cover the refund amount, Fintoc retries the refund for 5 business days. The refund then transitions to `failed`. Fintoc doesn’t return the original payment’s processing fees when you issue a refund. > [!NOTE] > > **Funding pending refunds** > > Fintoc pays refunds only from the balance of the sales it collects for you. You can't deposit or transfer funds into Fintoc to cover a pending refund. > > If your available balance is too low, the refund stays pending. Fintoc retries the refund for up to 5 business days as new sales add to your balance. Fintoc processes pending refunds in the order you created them. Fintoc updates the refund's status in the [Dashboard](https://dashboard.fintoc.com) after processing the refund. > > If you don't expect enough sales to cover the refund within 5 business days, the refund transitions to `failed` at the end of that period. > > A `failed` refund is final. Fintoc can't retry or force a `failed` refund. To refund the customer, create a new refund for the same payment. The new refund draws on your available balance at the time you create it. > [!WARNING] > > **Refunds for e-commerce plugins** > > You can issue refunds directly from VTEX or Shopify. However, **you can’t cancel these refunds from the VTEX or Shopify dashboard**. > > To cancel a refund issued from one of these platforms, use the [Cancel refunds](/api/payments-api/refunds/refunds-cancel) API endpoint or contact Fintoc support. **The cancellation doesn’t appear in your VTEX or Shopify dashboard**. > > If a refund issued from VTEX or Shopify fails, create the refund again from the same platform. The platform registers the new refund in Fintoc automatically. # Available refund balance Fintoc pays refunds from the balance of your sales that Fintoc hasn't settled yet. Sales that Fintoc already reserved for a payout don't count toward this balance. In Chile, Fintoc reserves the balance for the daily payout at 14:00 Santiago time. A refund you create later that day can only draw on sales you received after 14:00. Each payment method has its own refund balance: * Fintoc refunds bank transfer payments from the balance of your unsettled bank transfer sales. * Fintoc refunds card payments from the balance of your new, unsettled card sales. A refund for a card payment can't draw on your bank transfer sales. A refund for a bank transfer payment can't draw on your card sales. To estimate the amount available to refund for a payment method: 1. In the [Dashboard](https://dashboard.fintoc.com), find the payments with that payment method that Fintoc hasn't settled yet. 2. Add up their amounts, minus each payment's commission. 3. Subtract the [refund fee](#refund-fees) of the refund you want to issue. For example, suppose your only unsettled sale is a bank transfer payment of `$50,000 CLP` with a `$800 CLP` commission. You can refund up to `$49,200 CLP` of bank transfer payments, minus the refund fee. You can't refund card payments until you receive new card sales. # Refund destinations The destination of a refund depends on the payment method used. For payments that don't use an alternative payment method, Fintoc refunds to the original bank account. You don't need to specify a destination. For [alternative payment methods](/guides/payments/alternative-payment-methods), Fintoc doesn't have access to the customer's account. The customer authorizes the payment through the bank's checkout. To refund these payments, collect the destination account from the customer. Pass the account as `recipient_account` when you [create the refund](/api/payments-api/refunds/refunds-create). If a customer has closed their bank account, Fintoc marks the refund as `failed`. If you plan to issue refunds, include a `customer_email` when creating your Checkout Session. Fintoc uses the email address to notify the customer about the refund's progress. # Refund lifecycle ### Chile 🇨🇱 You can create refunds 24/7. Fintoc begins disbursing each refund when you create it, instead of holding it for the next daily payout cycle. At 14:00 Santiago time each day, Fintoc reserves the accumulated balance to fund your daily payout. A refund you create after 14:00 can't draw on that reserved balance. Fintoc disburses the refund after new balance accumulates. The refund moves through these statuses: 1. A new refund starts with the `created` status. You can cancel a refund while it's `created`. 2. Fintoc starts disbursing the refund. The refund then transitions to the `in_progress` status. 3. After Fintoc disburses the funds, the refund transitions to the `succeeded` status. Your customer then sees the refund on their bank statement. 4. If your available Fintoc balance doesn't cover the refund amount, Fintoc retries the refund for 5 business days. If the refund doesn't succeed within that period, the refund transitions to the `failed` status. Any other transfer failure also marks the refund as `failed`. Fintoc includes the refund amount in your next payout. ### Mexico 🇲🇽 You can create refunds 24/7. Fintoc begins disbursing each refund when you create it, instead of holding it for the next daily payout cycle. The refund moves through these statuses: 1. A new refund starts with the `created` status. You can cancel a refund while it's `created`. 2. Fintoc starts disbursing the refund. The refund then transitions to the `in_progress` status. 3. After Fintoc disburses the funds, the refund transitions to the `succeeded` status. Your customer then sees the refund on their bank statement. 4. If your available Fintoc balance doesn't cover the refund amount, Fintoc retries the refund for 5 business days. If the refund doesn't succeed within that period, the refund transitions to the `failed` status. Any other transfer failure also marks the refund as `failed`. Fintoc includes the refund amount in your next payout. 5. If the recipient's bank returns the transfer after the refund succeeded, the refund transitions to the `returned` status. A `returned` refund is different from a `failed` refund: Fintoc disbursed the funds, and the bank sent them back afterward. Fintoc sends the `refund.returned` webhook event. The [Dashboard](https://dashboard.fintoc.com) shows a `returned` refund as a failed refund. # Issue refunds You can issue refunds from the [Dashboard](https://dashboard.fintoc.com) or by using the [Refunds API](/api/payments-api/refunds). A refund reaches the `succeeded` status when Fintoc disburses the funds, but the recipient's bank can still return the transfer. Keep handling the `refund.returned` event after a refund succeeds. You can issue more than one refund against a payment, but you can't refund a total greater than the original payment amount. Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. ## Issue a refund using the API To refund a payment with the API, [create a refund](/api/payments-api/refunds/refunds-create) with the payment's ID and set `resource_type` to `payment_intent`. The `checkout_session.finished` webhook event includes the payment ID. You can also find the payment ID in the [Dashboard](https://dashboard.fintoc.com). ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/refunds" \ --header 'Authorization: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "resource_id": "pi_ja12Nqa3Lb4s", "resource_type": "payment_intent" }' ``` To partially refund a payment, provide an `amount` in the [smallest currency unit](/guides/home/currencies). For example, use `1000` for `$1000 CLP` or `100` for `$1.00 MXN`. ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/refunds" \ --header 'Authorization: YOUR_API_KEY' \ --header 'Content-Type: application/json' \ --data-raw '{ "resource_id": "pi_ja12Nqa3Lb4s", "resource_type": "payment_intent", "amount": 1000 }' ``` Exception: payments with a split support only full refunds. Create the refund without an `amount`, or set `amount` to the full payment amount. Each recipient funds its share of the refund. See [Refund a split payment](/guides/payments/accept-a-payment/accept-split-payments#refund-a-split-payment). # Cancel a refund You can cancel any refund while its status is `created`. Cancel the refund from the [Dashboard](https://dashboard.fintoc.com) or with the API. Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. ## Cancel a refund using the API To cancel a refund using the API, call the [cancel refund](/api/payments-api/refunds/refunds-cancel) endpoint with the refund's ID. ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/refunds/REFUND_ID/cancel" \ --header 'Authorization: YOUR_API_KEY' \ --header 'Content-Type: application/json' ``` # Refund status updates Fintoc sends [webhook events](/guides/resources/webhooks-walkthrough) to your server when a refund's status changes. Use these events to notify your customer about updates. For example, email your customer when the refund appears on their bank statement. We recommend handling the following events when refunding a payment: | Event | Description | Action | | :- | :- | :- | | `refund.in_progress` | Fintoc sends this event after starting to disburse the refund. | Notify your customer that the refund is in progress, and wait for the `refund.succeeded` event before telling them the money arrived. | | `refund.succeeded` | Fintoc sends this event after completing the refund. | Notify your customer that the money is in their bank account. | | `refund.failed` | Fintoc sends this event when the refund fails. For example, the customer's bank couldn't process the refund or your balance has insufficient funds. | Notify your customer that the refund couldn't be completed. | | `refund.returned` | Fintoc sends this event when the customer's bank returns the transfer of a refund that had already succeeded. | Notify your customer that the refund didn't reach their account. | # Refund vouchers Refund vouchers confirm a successful refund to your customer's bank account. Download a voucher with the [refund voucher endpoint](/api/payments-api/refunds/refunds-voucher). You must [start the download within 5 minutes](/api/main-resources/vouchers/vouchers-object). # Refund notifications When you create a Checkout Session, you can include [a `customer_email` for notifications](/api/payments-api/payment-intents/payment-intents-create). If you provide a valid email address, Fintoc notifies your customer when you create a refund. Fintoc also sends notifications when the funds reach the customer's bank account or the refund fails. # Refund fees Fintoc deducts refund fees from your payout. If a refund fails, Fintoc reimburses the fee in your next payout. # Reporting and reconciliation Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation Use Fintoc's payout reconciliation and daily transaction reports to break down each payout, download daily transaction history, and close your accounting. Fintoc's reports help you understand and reconcile the activity in your account. ## Select a report When using Fintoc's Payment Initiation API, Fintoc has two reports that provide information about your transactions. Start with the task you’re looking to perform and use the table below to identify the best report. | Task | Suggested Report | | :- | :- | | - Break down the individual transactions included in each payout to your bank account | Payout reconciliation | | - Download daily transaction history - View daily transaction totals | Daily transaction | > [!NOTE] > > **Payout reconciliation report** > > The payout reconciliation report is only available when [Fintoc collects payments](/guides/payments/fintoc-collect-payments). ### The payout reconciliation report The Payout reconciliation report shows which transaction is included in a specific payout. This report helps you reconcile each payout you received in your bank account against the transactions included in that batch. Fintoc sends you an email with the payout reconciliation report each time Fintoc makes a payout to your bank account, unless the Settlement email toggle is off. To turn this email on or off, see [payout notifications](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#payout-notifications). For the other delivery channels, see [automatic report delivery](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation#available-delivery-channels). #### Structure The payout reconciliation report is a comma-delimited CSV file with column headers in the first row. The filename is `yyyy-mm-dd-fintoc-payout-.csv`. For example, if your `orgname` is "My Company", the filename is `yyyy-mm-dd-fintoc-payout-mycompany.csv`. The file contains the following columns: | # | Column | Type | Description | | :- | :- | :- | :- | | 1 | `id` | `string` | Unique identifier for the transaction. It is case-sensitive. | | 2 | `created_at` | `string` | Transaction creation date and time, with a UTC offset. Example: `2026-09-30 10:00:00 +0000`. | | 3 | `amount` | `integer` | Gross transaction amount, in the smallest currency unit. Negative for refunds and chargebacks; positive for adjustments that restore a deducted amount. | | 4 | `fee` | `integer` | Transaction fee, in the smallest currency unit. Negative for adjustments that restore a deducted fee; `0` when no fee is deducted. | | 5 | `net_amount` | `integer` | Net transaction amount, in the smallest currency unit. Equals `amount - fee`. | | 6 | `currency` | `string` | Transaction [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html), in uppercase. | | 7 | `payout_holder_id` | `string` | Tax ID of the payout recipient account holder: Chilean tax ID (RUT) or Mexican tax ID (RFC). | | 8 | `payout_recipient_account` | `string` | The account number the payout was sent to. | | 9 | `payout_recipient_bank` | `string` | The bank the payout was sent to. | | 10 | `resource_type` | `string` | Transaction type: `payment_intent`, `charge`, `refund`, `refund_adjustment`, `chargeback`, or `chargeback_adjustment`. | | 11 | `resource_subtype` | `string` | Payment method for the transaction. The report notes describe when this column appears; the payment method table lists its values. | | 12 | `metadata` | `string` | A JSON string of the transaction [metadata](/api/fintoc-api/metadata). | | 13 | `payout_id` | `string` | Identifier of the payout that includes the transaction. | Report notes: * Amounts use pesos for `CLP` and centavos for `MXN`. For example, `10000` represents 10,000 CLP or 100.00 MXN. * The `resource_subtype` column is present for organizations created after February 16, 2026. It is also present when cash, installment, or card payments are enabled or trialing. Non-bank-transfer payments or refunds also cause the column to appear. Otherwise, the column is omitted, and `metadata` and `payout_id` follow `resource_type`. * Rows for recurring charges leave `resource_subtype` empty. Use `resource_subtype` to split a payout by payment method: | `resource_subtype` | Payment method | | :- | :- | | `bank_transfer` | Bank transfer. | | `credit_card`, `debit_card`, `prepaid_card`, `card` | Card. The value is `card` when the card type is unknown. | | `installment`, `installments` | Installments. | | `pac` | Pago Automático de Cuentas (PAC). | | `cash` | Cash. | | `getnet`, `boton_banco_estado` | Payment button, by provider. | #### Sample For examples of payments, recurring charges, refunds, chargebacks, and adjustments, [open the sample report in Google Sheets](https://docs.google.com/spreadsheets/d/1w6PWq2gu8U2dyWHcfMMoZEQKMCGTY-qenKWcro3m-rc/edit?gid=1079898323#gid=1079898323) or [download the CSV](https://docs.google.com/spreadsheets/d/1w6PWq2gu8U2dyWHcfMMoZEQKMCGTY-qenKWcro3m-rc/export?format=csv\&gid=1079898323). The sample uses fictitious data. The inline CSV example uses fictitious data and includes all 13 columns, including `resource_subtype` and `payout_id`. It covers every payment method value in the table, a recurring charge, and a refund. Group rows by `payout_id` to reconcile each payout. The payment and refund rows total 102,700 CLP; the recurring charge belongs to a separate payout of 11,760 CLP. ```csv 2026-10-01-fintoc-payout-example.csv theme={null} id,created_at,amount,fee,net_amount,currency,payout_holder_id,payout_recipient_account,payout_recipient_bank,resource_type,resource_subtype,metadata,payout_id pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678901,2026-09-30 10:00:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,bank_transfer,"{""order_id"":""order_001""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678902,2026-09-30 10:05:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,credit_card,"{""order_id"":""order_002""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678903,2026-09-30 10:10:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,debit_card,"{""order_id"":""order_003""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678904,2026-09-30 10:15:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,prepaid_card,"{""order_id"":""order_004""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678905,2026-09-30 10:20:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,card,"{""order_id"":""order_005""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678906,2026-09-30 10:25:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,installment,"{""order_id"":""order_006""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678907,2026-09-30 10:30:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,installments,"{""order_id"":""order_007""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678908,2026-09-30 10:35:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,pac,"{""order_id"":""order_008""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678909,2026-09-30 10:40:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,cash,"{""order_id"":""order_009""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678910,2026-09-30 10:45:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,getnet,"{""order_id"":""order_010""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 pi_a1b2c3d4-e5f6-4a7b-8c9d-012345678911,2026-09-30 10:50:00 +0000,10000,200,9800,CLP,000000000,000000001,cl_banco_bice,payment_intent,boton_banco_estado,"{""order_id"":""order_011""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 ch_2f3e4d5c-6b7a-4890-8abc-012345678901,2026-09-30 11:00:00 +0000,12000,240,11760,CLP,000000000,000000001,cl_banco_bice,charge,,"{""invoice_id"":""invoice_001""}",po_9b8a7c6d-5e4f-4321-8abc-012345678902 ref_7e6d5c4b-3a2f-4109-8abc-012345678901,2026-09-30 12:00:00 +0000,-5000,100,-5100,CLP,000000000,000000001,cl_banco_bice,refund,bank_transfer,"{""order_id"":""order_001""}",po_9b8a7c6d-5e4f-4321-8abc-012345678901 ``` ### Daily transaction report #### Delivery schedules The daily transaction report can be scheduled for delivery on two schemes: banking cut-off time and chronological day cut-off time. Configured schedules have two effects: * They change the day and hour that reports are delivered. * They change the time window of data that each file contains. | Delivery schedule | Available country | Description | | - | - | - | | chronological day | Chile Mexico | The report will be delivered every day without exception. The file will contain data from a single day from 00:00 to 23:59. Files will be delivered between 00:20 and 01:20. | | banking day | Chile | The report will be delivered according to Chile's banking cut-off time, which is business days at 14:00. Therefore, data for a specific day will be between 14:00 and 13:59 of the next business day. Files will be delivered on business days between 14:20 and 15:20. For example, holidays aside, a report received on a Wednesday will contain data from Tuesday at 14:00 until Wednesday at 13:59. Another example is that a report received on Monday will contain data from the previous Friday at 14:00 until Monday at 13:59. If that Friday happens to be a holiday, the data window will be even larger (it would start on Thursday at 14:00). | #### Structure The daily transaction report is a semicolon-delimited CSV file in which the first row is column headers. The filename is `yyyy-mm-dd-daily-summary-fintoc-.csv`. For example, if your `orgname` is "My Company" the filename will be `yyyy-mm-dd-daily-summary-fintoc-mycompany.csv`. The file contains the following columns: | # | Column | Type | Description | | :- | :- | :- | :- | | 1 | `created_at` | `string` | The Payment's creation date, in ISO 8601 format. | | 2 | `payment_id` | `string` | Unique identifier for the payment. It is case-sensitive. | | 3 | `id_given_by_sender_institution` | `string` | Operation number from the bank of the sender account. | | 4 | `updated_at` | `string` | The Payment update date, in ISO 8601 format. | | 5 | `amount` | `integer` | Amount of the payment, in cents. | | 6 | `currency` | `string` | The payment [currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | 7 | `sender_institution_id` | `string` | The bank that initiated the payment. | | 8 | `sender_institution_cmf_code` | `string` | The CMF code of the bank that initiated the payment. In Mexico is empty. | | 9 | `sender_account_number` | `string` | The account number that initiated the payment. | | 10 | `sender_account_type` | `string` | The sender account type. | | 11 | `sender_holder_id` | `string` | Identifier of the owner of the bank account that initiated the payment. In Chile, it is a RUT and in Mexico it is an RFC. | | 12 | `sender_name` | `string` | The name of the owner of the bank account that initiated the payment. It can be empty. | | 13 | `recipient_holder_id` | `string` | Identifier of the owner of the bank account that received the payment. In Chile, it is a RUT and in Mexico it is an RFC. | | 14 | `recipient_account_number` | `string` | The account number that received the payment. | | 15 | `recipient_institution_id` | `string` | The bank that received the payment. | | 16 | `organization_name` | `string` | Your organization name in Fintoc's system. | | 17 | `metadata` | `string` | A JSON string of the transaction [metadata](/api/fintoc-api/metadata). | #### Sample For an example of the included data, [download a sample of the daily transaction report](https://drive.google.com/file/d/11ACkHoqCXwxKgHrw01xkIlCRIY_1Oswl/view?usp=sharing). ## Tax documents in Chile Fintoc's reports help you reconcile your sales, but Fintoc doesn't report every payment to the Servicio de Impuestos Internos (SII) on your behalf. What Fintoc reports depends on the payment method: | Payment method | Reported to the SII by Fintoc | What you need to do | | :- | :- | :- | | Bank transfer | No | Issue the tax documents (for example, boletas or facturas) for these sales and report them to the SII yourself. | | Card (credit, debit, or prepaid) | Yes | No action needed for reporting these payments. | To find the sales you need to document, filter the payout reconciliation report by `resource_subtype`. ## Available delivery channels Instead of manually downloading files from the Dashboard, reports can be scheduled for automatic delivery via different channels. If configured, reports will be delivered periodically so that each file contains data for a specific time interval. ### Email Files can be automatically delivered to an email of your choice. The subject of the sent emails is also configurable. For instance, it is common to include the date of a given report on the subject for easier identification. Use the operational email in the Communication tab in Settings to set the recipient. Turn the payout email on or off with the Settlement email toggle. See [payout notifications](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#payout-notifications). To configure the subject, contact our sales team. ### SFTP Use Fintoc's SFTP server to receive reports and automate file extraction. #### Connecting to the SFTP server Use the following information to connect to Fintoc's SFTP server: * Host: `sftp.fintoc.com` * Port: `80` * Username: your organization's ID. It starts with `org_` * Password: the password provided by your Account Executive. For access credentials, get in touch with our sales team. #### Reports path Fintoc uploads each report in the following paths: | Report | File path | | :- | :- | | Payout reconciliation | `OUT/payout//yyyy-mm-dd-fintoc-payout-.csv` | | Daily transaction | `OUT/daily_summary//yyyy-mm-dd-daily-summary-fintoc-.csv` | Where `` can be either `live` or `test`. # Fintoc fees Source: https://docs.fintoc.com/guides/payments/fintoc-fees Learn how Fintoc calculates fees for our Payment Initiation product. ## Fee calculation Fees are calculated live, and each product resource has an associated fee (i.e. each payment intent has a fee, each refund has a fee). To make sure what shows up in the API is the same as what shows up in your bank statement, fees + VAT are rounded to the smallest currency unit. ### Step by step 1. A **fee** is calculated for each resource, based on your pricing plan. 2. The **VAT** is calculated as a percentage of this **fee**, depending on your country's [VAT rate](/guides/payments/fintoc-fees#vat-rates). 3. The **fee** + **VAT** add up to the **total fee** of each resource. 4. Finally, what is deducted from your **payout** is the **total fee**, **rounded** to the nearest currency unit. Here is an example of the steps to calculate a single resource’s fee (for this example we are using CLP currency and a fee of 1.35%). | Resource type | Amount | Fee | VAT | Total fee | Rounded total fee | | :- | :- | :- | :- | :- | :- | | payment\_intent | 1000 | 13.5 | 2.57 | 16.07 | 16 | \*Fees and taxes are recalculated based on the rounded fee. At the invoice level, the sum is direct and no rounding is necessary. The following table illustrates how we calculate the total amount that will show up in your end-of-period invoice. For this example we are using CLP currency and a fee of 1.35% for payments. We are using 0.014 UF fee for refunds (UF value \$36.730 CLP). | | Amount | Fee | VAT | Total fee | Rounded total fee | | :- | :- | :- | :- | :- | :- | | payment\_intent\_1 | 10000 | 135 | 25.65 | 160.65 | 161 | | payment\_intent\_2 | 2000 | 27 | 5.13 | 32.13 | 32 | | refund\_1 | 10000 | 514.22 | 97.7 | 611.92 | 612 | | **Invoice total** | | **676.22** | **128.48** | **804.7** | **805** | The total amount of the invoice will be the sum of **rounded fees** of the resources consumed by your organization in the past billing period. The total VAT of the invoice will be the VAT rate, calculated over the **rounded fee**. ## How you're billed How you pay Fintoc's fees depends on whether automatic fee deduction is active for your organization. * **With automatic fee deduction:** Fintoc deducts the total fee of each resource from your daily settlements. At the end of the month, Fintoc still issues an invoice for that usage. The invoice arrives already paid because Fintoc deducted the fees from your settlements. You are not charged twice. * **Without automatic fee deduction:** Fintoc bills your fees on the end-of-period invoice, and you pay that invoice. ### Download your invoices You can download Fintoc's invoices from the Dashboard in **Settings > Invoices**. Each invoice shows its issue date, folio, amount (tax included), and status. To download an invoice, open the **Download files** menu on its row. Available files can include PDF, XML, and CSV formats. Invoices can have the following statuses: | Status | Description | | :- | :- | | Issued | The invoice was issued and is pending payment. | | Paid | The invoice is paid. Invoices covered by automatic fee deduction show this status. | | Expired | The invoice expired without being paid. | | Void | The invoice was voided. | > [!NOTE] > > An invoice's status can take up to 24 business hours to update. To access invoices, your Dashboard user needs the permission to access the billing and invoices section. ## VAT Rates To calculate fees and end-of-period billing, a VAT rate is included over the fee. This amount varies based on your country. | Country | VAT Rate | | :- | :- | | Chile | 19% | | Mexico | 16% | # Go-live checklist Source: https://docs.fintoc.com/guides/payments/go-live-checklist Checklist to move your Fintoc integration from test to live: production API keys, webhook endpoints, redirect URLs, and pre-launch verifications. After testing your integration in test mode, complete these tasks before you go live with Payment Initiation. Fintoc's test environment behaves like live mode, but you still need to test your live setup. ## Who can use Fintoc To use Fintoc, your business must meet all of these requirements: * **A company tax ID.** In Mexico, this is your company's Mexican tax ID (RFC), which has 12 characters. In Chile, this is your company's Chilean tax ID (RUT). * **A bank account in your company's name.** Fintoc only sends your payouts to an account associated with your company's RFC or RUT. * **An email address on your company's domain.** Sign up with a corporate email, not a personal one such as Gmail or Hotmail. Fintoc doesn't accept individuals, including a natural person with business activity (persona natural con giro). Your company also needs at least 6 months of business activity, counted from the start date on your business initiation certificate. If your company is younger, the Dashboard shows an error when you upload the certificate and you can't complete the onboarding. *** > [!NOTE] > > **Make sure your integration supports backwards-compatible changes** > > We constantly make backwards-compatible changes to our API to add new features. Make sure your integration can support such changes once you go live. For more information, read our guide on [Changes to the API](/guides/home/changes). * [ ] **Setup the Live API Keys in your backend** In your dashboard, open the API Keys tab. Confirm that you are in `live` mode by checking the toggle indicator in the bottom-left corner. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/3f3098c12c490eba82c12603f93e4874ed03ccc76e7510ceaf8accb247ec1124-Captura_de_pantalla_2025-01-14_a_las_11.08.33.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=44d5d015efe67f1d37b84aa8c31fd878) Generate your Live Secret Key and set it up in your back end to make requests to the API in Live Mode > [!WARNING] > > **You can only access your Secret API Key once** > > You will only be able to copy and see your API Key when you activate or rotate it. Make sure to store them securely in your backend. * [ ] **Confirm your products are enabled in `live` mode** Products you use in `test` mode are not automatically enabled for your organization in `live` mode. Confirm with your Account Executive, or by emailing [sales@fintoc.com](mailto:sales@fintoc.com), that each product and payment method you use is enabled in `live` mode. For example, subscriptions with `pac` require the Subscriptions product, and subscriptions with `card` require card payments with setup for future charges. If a product is not enabled, API requests in `live` mode return a `403 Forbidden` error with `code` set to `product_access_required`. See [Go live](/guides/payments/accept-recurring-payments#go-live) in the subscriptions guide. * [ ] **Set up new webhooks to keep your application in sync with Fintoc** Webhooks created in test mode will not notify your application about events that occur in Live mode. You will need to set up new webhooks in your production environment to handle any events related to a Checkout Session. If you need help setting up new webhooks, check our [Webhooks Guide](/guides/resources/webhooks-walkthrough). There are several events that you can configure from the dashboard or the API to receive notifications about the payment process, but there are four events associated with the processing of a Checkout Session that are critical to the operation and are sent via webhook: `checkout_session.finished`, `checkout_session.expired`, `payment_intent.succeeded` and `payment_intent.failed`. Check out our [Webhooks Guide](/guides/resources/webhooks-walkthrough) to understand how Fintoc's webhooks work and how you can configure your Webhook endpoints. * [ ] Make sure to follow our [UX Guidelines](/guides/payments/checkout-ux-guidelines) **Choose the correct payment button for your checkout**: Our research has shown that the payment button affects conversion. **Launch the widget without redirecting the customer**: Integrating the payment widget this way promotes trust, making the user more likely to enter their banking credentials and finish the payment. **Avoid additional visual elements during the payment flow**: A focused payment flow reduces distractions and helps customers complete the payment. **Properly redirect the end user after making a payment**: Whether the payment is successful or not, it is important to reduce uncertainty and confirm the final status of the customer's payment. * [ ] **Correctly handle webhook-related edge cases** Some payments may have null fields if the user exits mid-process. Be sure to handle these cases as shown in our [payments guide](/guides/payments/accept-a-payment). * [ ] **Specify the account where you want to receive payouts** If you are using [Fintoc Collects](/guides/payments/fintoc-collect-payments), you will need to specify the bank account in which you want to receive payouts. To do this, send an email to your Account Executive specifying: 🇨🇱 * Bank Name * Account Type * Account Number * RUT * Notifications Email 🇲🇽 * Company Name * Bank Name * CLABE * RFC * Notifications Email * Company Address - [ ] **Perform Certification Tests** Before moving to production, you must be sure that your integration was carried out correctly. **The tests we will perform involve real payments**, therefore you must: * Ask your Sales Executive to activate Live mode on your account. **You must be able to launch the widget in this mode**. If you wish, you can conduct the tests on a development site, but always using the Live mode credentials and making real payments. * Have your webhook endpoints [configured in Live mode](/guides/resources/webhooks-walkthrough/webhooks-activating#add-an-endpoint-through-the-dashboard). **Payment Initiation Tests** 1. Complete a successful payment using Fintoc.\ **Expected results:** 1. You can correctly [initiate a Checkout Session](/api/payments-api/checkout-sessions/checkout-sessions-create) and [display the widget](/guides/resources/widget/web-integration). If your payment flow requires the user to input their RUT (in CL) or phone number (in MX) before the payment, the widget is deployed with the [username field pre-filled](/guides/resources/widget/web-integration#username-and-holderid-objects) 2. After finishing the payment flow, you correctly redirect the end user to a confirmation page on your site 3. Your system registers the payment as successful and the rest of your processes are triggered (for example, sending a confirmation email) 2. Create a new Checkout Session and close the widget before authorizing the payment.\ **Expected results:** 1. Your front end redirects the end user to a page where they can retry the payment or choose another payment method. 2. Your system registers the payment as failed using [webhooks](/guides/resources/webhooks-walkthrough) 3. Simulate a Checkout Session where the end user authorizes the transaction in their banking app and closes the tab immediately after.\ **Expected results:** 1. Your system registers the payment as successful after receiving the confirmation webhook. 2. The rest of your processes are triggered (for example, sending a confirmation email) 4. Simulate a payment that results in a pending status\ **Expected Results:** 1. Your system registers the payment as pending after recieving the `checkout_session.finished` webhook with a pending final status 2. A message is shown to the end user indicating the payment has not been confirmed yet 3. You can decide how to handle the rest of the payment flow according to your business requirements and our [pending payments guide](/guides/payments/fintoc-collect-payments/dealing-with-payment-exceptions#how-to-deal-with-pending-payments) * [ ] **Go Live** After completing the certification tests, you are ready to set your integration Live. # Payment initiation overview Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/index Use Fintoc's Checkout Session API to accept bank transfers and card payments in your store, payment platform, wallet, or peer-to-peer application. This overview explains how you can use the Checkout Session API to accept bank transfers and card payments in your application or website. You can use Checkout Sessions in these scenarios: * You run an online store and want your customers to pay by bank transfer or card. * You operate a payment platform and want to offer bank transfers and cards to your customers. * You build a wallet or digital banking application and want your customers to add funds to their accounts. * You build an application and want your customers to send money to one another (*peer-to-peer* transfers). ![](https://mintcdn.com/fintoc-49b8bee8/PEjaWCftVUfZv38h/images/payment-initiation-flow-screens.png?fit=max\&auto=format\&n=PEjaWCftVUfZv38h\&q=85\&s=c15a9ebb05acc22d0b38736c35775bde) Bank transfer payment flow # Countries and institutions Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions Sender banks available for payment initiation in Chile and Mexico, plus Chilean banks that support Pago Automático de Cuentas (PAC) for recurring payments. This page lists the institutions available for payment initiation in Chile and Mexico, and the Chilean banks available for recurring payments. ## Chile 🇨🇱 ### Available sender banks In Chile, the payment initiation module supports the following sender banks: | Bank name | Fintoc bank ID | | :- | :- | | Banco BCI | `cl_banco_bci` | | Banco BICE | `cl_banco_bice` | | Banco Consorcio | `cl_banco_consorcio` | | Banco de Chile - Edwards - Citi | `cl_banco_de_chile` | | Banco Estado | `cl_banco_estado` | | Banco Falabella | `cl_banco_falabella` | | Banco Internacional | `cl_banco_internacional` | | Banco Itaú | `cl_banco_itau` | | Banco Ripley | `cl_banco_ripley` | | Banco Santander | `cl_banco_santander` | | Banco Security | `cl_banco_security` | | BBVA | `cl_banco_bbva` | | Coopeuch - Dale | `cl_banco_coopeuch` | | Copec Pay | `cl_copec_pay` | | HSBC | `cl_banco_hsbc` | | Mach | `cl_mach` | | Mercado Pago | `cl_mercado_pago` | | Prepago Los Heroes | `cl_prepago_los_heroes` | | Scotiabank | `cl_banco_scotiabank` | | Tapp | `cl_tapp_caja_los_andes` | | Tenpo | `cl_tenpo` | ### Available banks for recurring payments with Pago Automático de Cuentas (PAC) [Recurring payments](/guides/payments/accept-recurring-payments) use PAC, a direct debit mandate that your customer enrolls at their bank. In Chile, only the following banks support PAC enrollment: | Bank name | Fintoc bank ID | | :- | :- | | Banco BCI | `cl_banco_bci` | | Banco de Chile - Edwards - Citi | `cl_banco_de_chile` | | Banco Estado | `cl_banco_estado` | | Banco Falabella | `cl_banco_falabella` | | Banco Itaú | `cl_banco_itau` | | Banco Santander | `cl_banco_santander` | | Scotiabank | `cl_banco_scotiabank` | ## Mexico 🇲🇽 ### Available sender banks In Mexico, the payments module supports every institution participating in the Sistema de Pagos Electrónicos Interbancarios (SPEI). # Payment scenarios Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/payments-use-cases Compare Fintoc collects and direct payments to choose a payment integration Fintoc supports two payment scenarios based on where you operate. Use your business model to identify the appropriate integration: | Payment scenario | Description | Best for | Supported in | | - | - | - | - | | Fintoc collects | Your customer's payment goes to a bank account managed by Fintoc. Fintoc sends the money to your bank account according to your payout schedule and remains **in** the flow of funds. | Online retailers and other companies that sell goods or services online. | Chile and Mexico | | Direct payments | Your customer's bank transfer goes directly to the bank account you specify. Fintoc is **not** in the flow of funds. | Fintech companies such as wallets, neobanks, and peer-to-peer applications. | Chile | # Fintoc collects ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/0fac3f9acb607dd7538a40beef4aaad0d7bcca8b579c85c4e7d52a65ad53ac21-Presentacion_sin_titulo.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=cb007009e15b6befee8ba35fd3f863cd) When Fintoc collects your payments, the money goes to a bank account managed by Fintoc. Fintoc tracks and matches payments as they settle in this account. Fintoc also handles external payments that reach this account through other channels, such as regular bank transfers. Based on your [payout schedule](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts), Fintoc sends the funds to your bank account. Fintoc deducts your [application fees](/guides/payments/fintoc-fees#how-you’re-billed) directly from your payouts. This scenario has the following tradeoffs: | Advantage | Disadvantage | | - | - | | You do not need to reconcile Fintoc payments or handle external bank transfers. Fintoc handles both processes. | Funds arrive according to your payout schedule rather than immediately. See the [receiving payouts guide](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts) for payout timing. | We recommend the Fintoc collects scenario for online retailers and other companies that want Fintoc to handle payment reconciliation and external bank transfers. # Direct payments ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/a6be80ca2e738f6b406394f665e597130002c5ea81a4b6e844173fbe94dd4ef9-Presentacion_sin_titulo_1.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=95ee3b05c9034840ce24f0108982d6fb) > [!NOTE] > > **Availability** > > Direct payments are available only for bank transfers in Chile. In direct payments, the money flows directly from your customer's bank account to the recipient account you specify. If you collect payments in one bank account, periodically download the bank statement. Reconcile Fintoc payments and handle any external bank transfers that arrive in the account. Direct payments have the following tradeoffs: | Advantage | Disadvantage | | :- | :- | | Funds go directly to the recipient's bank account. | You must reconcile Fintoc payments and external bank transfers. | # Quickstart Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/quickstart-payments Get started with Fintoc's Payment Initiation API and create your first Checkout Session in under ten minutes using test API keys and the Widget. To start using Fintoc's Checkout Session API, you just need to create an account on our Dashboard and follow these five steps: 1. Get your test API keys 2. Create a Checkout Session 3. Redirect your customer to the Fintoc-hosted checkout page 4. Handle post-payment events 5. Make your first payment # Step 1: Initial setup ## Get your test API keys Every interaction with the Fintoc API must be authenticated with the [API keys](/guides/home/api-keys) of your Fintoc account. If an interaction with the API does not include your API key or includes an incorrect API key, Fintoc will return an error. Every Fintoc account has two key pairs: one corresponds to the [test mode](/guides/resources/test-mode), while the other corresponds to the actual API environment. Every resource is stored either in [test mode or in live mode](/guides/resources/test-mode), and resources from one environment cannot be manipulated by resources from the other environment. Your API keys will be available in the [Dashboard](https://app.fintoc.com). First you need to create an account on the Fintoc Dashboard. After you create your Fintoc account, you can get your API keys. In this case, you must use the **Public Key** and **Secret Key** from [test mode](/guides/resources/test-mode). To easily identify them, Fintoc adds the prefix **pk\_test\_** and **sk\_test\_**, respectively. ## Optional: Install Fintoc's backend SDK > [tab] Python > > If you’re using Python, you can install our [Python SDK](https://github.com/fintoc-com/fintoc-python) to make it easier to interact with our API. The SDK automatically handles pagination, lets you easily verify Fintoc's webhooks, and offers many other helpful features. > > ```bash theme={null} > pip install fintoc > ``` > [tab] Node > > If you’re using Node, you can install our [Node SDK](https://github.com/fintoc-com/fintoc-node) to make it easier to interact with our API. The SDK automatically handles pagination, lets you easily verify Fintoc's webhooks, and offers many other helpful features. > > ```bash theme={null} > npm install fintoc > ``` # Step 2: Create a Checkout Session Using your test **Secret Key**, create a Checkout Session from your backend with the amount and currency of the payment. Always create the Checkout Session from your backend, or a malicious user could alter any of those fields. If you plan on using the Refunds product, you must include a `customer_email` in the Checkout Session request. Here's an example of creating a Checkout Session for Chile: ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/checkout_sessions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "amount": 2476, "currency": "CLP", "customer_email": "name@example.com", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/987654321" }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.v2.checkoutSessions.create({ amount: 2476, currency: 'CLP', customer_email: 'name@example.com', success_url: 'https://merchant.com/success', cancel_url: 'https://merchant.com/987654321' }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.v2.checkout_sessions.create( amount=2476, currency='CLP', customer_email='name@example.com', success_url='https://merchant.com/success', cancel_url='https://merchant.com/987654321' ) ``` If you want to create a Checkout Session for Mexico, change the currency to `MXN`. > [!WARNING] > > **Currencies are represented as integers** > > The Fintoc API represents currencies in its smallest possible units with no decimals (as an integer). That means that an **amount of MXN 10.29 gets represented by Fintoc as 1029**. You can read more about currencies [here](/guides/home/currencies). The response should look like this: ```json theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "mode": "test", "status": "created", "amount": 350000, "currency": "CLP", "created_at": "2024-06-04T15:32:46.721Z", "success_url": "https://merchant.com/success", "cancel_url": "https://merchant.com/987654321", "redirect_url": "https://checkout.fintoc.com/checkout_session_01HXY3Z7X5YQ54V8G2E1KJQAVF", "metadata": {}, "customer": {} } ``` # Step 3: Redirect your customer to the Fintoc-hosted checkout page Your new created `checkout_session` should contain the `redirect_url` attribute. You must redirect your customer to this URL to complete the payment flow. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d39b082fafc3431f6752955cfa1bb4825fd80b45c0ec19ab071cb35768529c65-bank-transfer-payment-flow.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=5264a6ee2e783b2de54f1e13a177a63a) Payment flow when the user selects "Paga con tu banco" # Step 4: Handle post-payment events Fintoc sends a `checkout_session.finished` event when the payment related to a session is completed. Use the [webhook guide](/guides/resources/webhooks-walkthrough) to receive these events and run actions, such as sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow. Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. We recommend handling the following events: | Event | Description | Action | | :- | :- | :- | | `checkout_session.finished` | Sent when a customer has completed a payment. The webhook contains information about the Payment including its final status. | Depending on the final status of the related payment, confirm the order to the customer or offer to retry the payment. | | `checkout_session.expired` | Sent when a customer leaves the payment flow before finishing. | Offer the customer another attempt to pay. | | `payment_intent.succeeded` | Sent when the payment related to a checkout session succeeds. Useful for confirming payments that were previously in pending status. | Confirm the customer's order. | | `payment_intent.failed` | Sent when the payment related to a checkout session fails. Useful for determining the final status of payments that were previously in pending status. | Offer the customer another attempt to pay. | > [!NOTE] > > **Learn more about webhooks** > > To learn more about how to create your own webhook endpoint, test your webhook endpoint and security best practices read our [Webhooks guide](/guides/resources/webhooks-walkthrough). # Step 5: Make your first payment Once you access the Fintoc-hosted checkout page, follow the payment flow using [Fintoc's test special values](/guides/payments/payment-initiation-test-your-integration). For a successful payment, you can use one of these values: * In Chile, select any bank and log in using the `41614850-3` RUT and `jonsnow` password. Once you are logged in to the bank, select the account with the number `422159212`. After you select that account, wait 5 seconds and the payment should be successful. * For Mexico, select any bank and write the number `5555555555`. Wait 5 seconds and the payment should be successful. You should have received a `checkout_session.finished` event containing a successful payment in your webhook endpoint. Congratulations! You just made your first Fintoc payment! To test different payment flows, see [Fintoc's test special values](/guides/payments/payment-initiation-test-your-integration). # Transaction limits Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/transaction-limits Daily transaction limits by bank for payments in Chile, based on multi-factor authentication method, account type, and whether the recipient is new or existing. Transaction limits vary depending on the country you are operating in. These are constantly changing, so contact us if your experience differs from the information below. ## Chile 🇨🇱 In Chile, banks have certain daily limits when dealing with payments that may have an impact on your business. These limits vary based on the type of Multi-Factor Authentication (MFA) chosen by the user, the type of account, and whether the payment is to a new or existing recipient. | **Bank** | **New recipient** | **Existing recipient** | **Minimum amount** | | - | - | - | - | | **Banco BCI** | MultiPass (MFA): \$250.000 BciPass (MFA): \$600.000 (Maximum 1 transaction in the first 24h) | MultiPass (MFA): \$5.000.000 BciPass (MFA): \$7.000.000 | \$1 | | **Banco de Chile** | \$350.000 | DigiPass/Mi Pass (MFA): \$5.000.000 DigiCard (MFA): \$2.000.000 | \$1 | | **Banco Santander** | \$250.000 (Maximum 1 transaction in the first 24h) | \$5.000.000 | \$1.000 | | **Banco Estado** | From Cuenta Rut: \$100.000 Other accounts: \$250.000 (Maximum 1 transaction in the first 24h) | From Cuenta Rut: \$1.000.000 Other accounts: \$5.000.000 From Cuenta Rut to a digital account like Tenpo/Mach/Tapp: \$100.000 From other accounts to Tenpo/Mach: \$250.000 | \$1 | | **Banco Itaú** | \$300.000 (Maximum 1 transaction in the first 24h) | \$7.000.000 | \$1 | | **Banco Falabella** | To Banco Estado: \$200.000 Other Accounts: \$1.000.000 | To Cuenta Vista: \$2.000.000 To Cuenta Corriente: \$7.000.000 | \$1 | | **Scotiabank** | \$300.000 (Maximum 1 transaction in the first 24h) | \$5.000.000 | \$1 | | **BICE** | \$250.000 | From Cuenta BICE GO (Daily accumulated total): \$5.000.000 From Cuenta BICE GO (In a single transfer): \$2.500.000 From Cuenta Corriente: \$7.000.000 | \$1 | | **Banco Ripley** | \$250.000 | Daily accumulated total: \$7.000.000 In a single transfer: \$2.000.000 | \$1 | ## Mexico 🇲🇽 There are currently no single transaction or daily amount limits for transactions in México. # Test your integration Source: https://docs.fintoc.com/guides/payments/payment-initiation-test-your-integration Simulate bank transfer and card payments in test mode with special credentials to exercise successful, rejected, and refund scenarios, plus webhook delivery. To confirm that your integration works correctly, simulate payments without moving any money using special values in test mode. Test accounts let you simulate several scenarios: * Successful and failed payments by payment method * [Refund](/guides/payments/fintoc-collect-payments/payment-initiation-refunds) a payment Any time you work with a test account, use test [API Keys](/guides/home/api-keys) in all API calls. ## Bank transfer payments > [!NOTE] > > To test alternative payment methods in Chile, follow the [alternative payment methods testing guide](/guides/payments/alternative-payment-methods/alternative-payment-method-test-your-integration). You can test Mach and the payment buttons from BancoEstado, Banco de Chile, and Banco Santander. The guide covers test amounts, the sandbox simulator, and webhook outcomes. For bank transfer payments, in test mode you use distinct test credentials to simulate the payment flow and error types for each Multi-Factor Authentication (MFA) type: ### Available MFA types These are the different MFA types available within test mode: * **Security device**: electronic device that banks give their clients to authorize transactions. They generally show a number that changes after some time. * **Mobile application**: banks offer to authorize transactions through their mobile apps. In this case, your customer authorizes the transaction from their *smartphone*. Fintoc detects the authorization automatically. * **SMS**: the bank sends a code (generally numeric) to your customer's phone, and your customer uses it to authorize the transaction. * **Coordinate card**: card that banks give their clients with a table with numbers. Your customer inserts the numbers at the coordinates the bank asks for. You can read more about coordinate cards on [Wikipedia](https://es.wikipedia.org/wiki/Tarjeta_de_coordenadas). ### Test special values Fintoc provides test special values for Chile and Mexico. Each country has its own payment authorization flow, and Fintoc test mode lets you test every authorization flow your customer might follow. ### Chile 🇨🇱 In Chile, a payment has two or three steps depending on the bank: 1. Your customer logs in to their bank account. 2. In some banks and specific cases, your customer authorizes a new contact before authorizing the payment. 3. Your customer authorizes the payment. Fintoc provides test special values for each one of those steps. #### Test credentials You can use the following test credentials to log in to a bank account. | Username | Password | Detail | | :- | :- | :- | | 41614850-3 | jonsnow | Use to simulate normal flows (login + payment authorization). | | 40427672-7 | jonsnow | Use to simulate normal flows (login + payment authorization). | | 41579263-8 | jonsnow | Use to simulate normal flows (login + payment authorization). | | 41885440-5 | jonsnow | Pending-only: use this credential to simulate a payment that ends up in `pending` status. | #### MFA to simulate a new contact Your customer might need to add the recipient's account before confirming the transaction. To simulate an MFA that asks your customer to add the recipient account of the Checkout Session as a new contact, **use specific last digits for the `amount` attribute of the Checkout Session**. For example, if you create a Checkout Session with an amount of `15001`, your customer authorizes the new contact using their **Security device**. The table below lists the digit combinations, the MFA type each combination triggers, and the correct code to enter. A different code fails the authorization: | Last digits of the amount | MFA type | Example | Correct code | | :- | :- | :- | :- | | 01 | Security device | `amount: 10701` | `0000` | | 02 | Mobile Application - Success | `amount: 10702` | Does not apply | | 03 | Mobile Application - Failure | `amount: 10703` | Does not apply | | 04 | SMS | `amount: 10704` | `000000` | | 05 | Coordinate Card | `amount: 17505` | `['00', '00', '00']` | If the amount of the Checkout Session doesn't end with any of the previous digits, your customer skips MFA for creating a new contact and goes directly to confirm the bank transfer. #### MFA to confirm operation To choose which authorization method to use in test mode to confirm the payment, select a specific origin bank account number during the payment flow. The test mode environment **always** shows the same accounts. Here's a list of the test mode bank account numbers and which type of MFA corresponds to each one, along with the correct code to enter. | Account number | Type of MFA | Correct code | | :- | :- | :- | | 813990168 | Security device | `000000` | | 422159212 | Mobile Application - Success | `N/A` | | 5233137377 | Mobile Application - Failure | `N/A` | | 5233138811 | Mobile Application - Failure | `N/A` | | 170086177 | SMS | `0000` | | 746326042 | Coordinate Card | `['00', '00', '00']` | | 4420245701 | Coordinate Card | `['00', '00', '00']` | The account `5233138811` fails with `error_reason` `new_contact_amount_limit_reached`, an amount-limit error for new contacts. See [Payment Intent Error Reason](/api/payments-api/payment-intents/payment-intent-error-reason) for the full list of reasons. #### Simulate pending status payment You can also simulate a pending payment status by choosing specific test origin bank accounts. This lets you validate how your system handles transactions that are not immediately confirmed. | Account number | Type of MFA | Correct code | | :- | :- | :- | | 512347890123 | Mobile Application - Pending → Success | `N/A` | | 983214567890 | Mobile Application - Pending → Failure | `N/A` | ### Mexico 🇲🇽 In Mexico, a payment has only two steps: 1. Your customer enters their phone number to initiate the payment. 2. Your customer authorizes the payment in their bank mobile application. To simulate a successful or failed payment, use one of the following cellphone numbers when the widget asks for it. | Cellphone number | Type of MFA | | :- | :- | | Any number except +52 2222222222. Example: +52 9876543210 | Mobile Application - Success | | +52 2222222222 | Mobile Application - Failure | ## Card payments To simulate a successful or failed card payment, use one of the following card credentials during the payment process: | Country | Card Number | Expiration Date | CVV | Holder Name | 3DS Challenge Code | Final Result | | - | - | :- | :- | :- | :- | - | | Chile | 4111111111111111 | Any future date | Any | Any | - | ✅ Succeeded | | Chile | 4456524869770255 | Any future date | Any | Any | 1234 | ✅ Succeeded if code is correct | | Chile | 4574441215190335 | Any future date | Any | Any | - | ❌ Failed due to invalid credentials | | Chile | 4349003000047015 | Any future date | Any | Any | - | ❌ Failed due to rejected transaction | | Mexico | 5451951574925480 | Any future date | Any | Any | - | ✅ Succeeded | | Mexico | 4574441215190335 | Any future date | Any | Any | - | ❌ Failed when requesting the card token | | Mexico | 4349003000047015 | Any future date | Any | Any | - | ❌ Failed when charging the card | | Mexico | 4349008516656431 | Any future date | Any | Any | - | ❌ Failed because the card is not supported | | Mexico | 4349001210846432 | Any future date | Any | Any | - | ❌ Failed due to insufficient funds | | Mexico | 4349003243371321 | Any future date | Any | Any | - | ❌ Failed because the CVV cannot be verified | | Mexico | 4349001386781322 | Any future date | Any | Any | - | ❌ Failed because the bank blocked the card | ## Test webhooks To test webhooks, perform actions in test mode that send legitimate events to your endpoint. For instance, to trigger the `checkout_session.finished` event, use a test account that produces a successful payment. ## Test refunds Test mode lets you simulate successful and failed refunds. The only difference with live mode is timing. In live mode, refunds take 1 to 2 business days to process. In test mode, Fintoc processes refunds almost immediately, depending on the refund amount. You can use the refund amount to simulate a successful or failed refund. To simulate a total refund, create a checkout session with the amount you want to test. | Description | Refund amount | Details | | - | - | - | | Successful refund | Any amount except `2222` or `3333` | When you initiate the refund, its status begins as `created`. Almost immediately, its status transitions to `in_progress` and then to `succeeded`. | | Failed refund | `2222` CLP or MXN | When you initiate the refund, its status begins as `created`. Almost immediately, its status transitions to `in_progress` and then to `failed`. | | Asynchronous failed refund | `3333` CLP or MXN | When you initiate the refund, its status begins as `created`. Some time later, its status transitions to `in_progress` and then 5 days later to `failed`. You can use this case to simulate a refund you want to [cancel](/guides/payments/fintoc-collect-payments/payment-initiation-refunds#cancel-a-refund). | > [!NOTE] > > **Refund webhooks** > > In test mode you receive the same webhooks as in live mode. # Payment links Source: https://docs.fintoc.com/guides/payments/payment-links Accept payments without writing code by creating shareable Fintoc Payment Links from the dashboard, ideal for one-off charges and no-code checkout flows. With Payment Links you can accept payments without building a website or application. Create a Payment Link using our API and share it with your customers through email or WhatsApp. ## Create a Payment Link Using your [Secret Key](/guides/home/api-keys), create a payment link from your backend with the `amount` and `currency`: ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/payment_links" \ --header 'Authorization: sk_test_0000000000000000' \ --header 'Content-Type: application/json' \ --data-raw '{ "amount": 120900, "currency": "CLP", "expires_after_seconds": 86400, "customer_email": "customer@example.com", "checkout": { "description": "Use this field to add a custom description of the product the customer is buying" }, "metadata": { "your_order_id": "10000" }, "recipient_account": { "holder_id": "111111111", "number": "0000000000", "type": "checking_account", "institution_id": "cl_banco_de_chile" }, "business_profile": { "name": "Merchant Name", "category": "009613", "tax_id": "222222222" } }' ``` > [!NOTE] > > **Currencies represented as integers** > > The Fintoc API represents currencies in its smallest possible units with no decimals (as an integer). That means that an amount of MXN 247.50 gets represented by Fintoc as 24750. You can read more about currencies [here](/guides/home/currencies). The parameters `customer_email`, `checkout`, `metadata` and `business_profile` are optional. Some of the optional parameters you can use to create your payment link are: | Optional parameters | Type | Description | | :- | :- | :- | | `expires_after_seconds` | `integer` | The number of seconds after which the payment link will expire. By default, a payment link will not expire. | | `max_completed_sessions` | `integer` or `null` | Maximum number of completed checkout sessions. The only non-null value is `1`, which creates a single-use link that closes after its first successful payment. If you omit this parameter or send `null`, the payment link is reusable. | | `customer_email` | `string` | If a customer email is set, Fintoc will send the customer an email in case of a refund. | | `checkout` | `dictionary` | Customize the checkout for your customers. For now, you can only add a custom description alongside the buy button. | | `metadata` | `hash` | Set of key-value pairs that you can attach to the payment link. This can be useful for storing additional information that you can use to reconcile the payment with your internal systems. | | `recipient_account` | `object` | The recipient account object must be included if your organization uses [Direct Payments](/guides/payments/direct-payments). | | `business_profile` | `object` | Object to identify enrolled merchants for category-based pricing. | The recipient account object is defined by 4 attributes: | Parameter | Example | Explanation | | :- | :- | :- | | `holder_id` | 111111111 | Account holder's [RUT](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) | | `number` | 0000000000 | Account number | | `type` | checking\_account | Type of account. Supported types are `checking_account` and `sight_account`. | | `institution_id` | cl\_banco\_de\_chile | Fintoc institution id for the bank receiving the bank transfer. You can see the code for each bank [here](/guides/payments/direct-payments/setup-direct-payment#available-recipient-banks) | For a complete list of parameters, check the Payment Link API. ## Share your Payment Link Each payment link contains a `url` that you can share with your customers through email, WhatsApp, or through other channels. ```json theme={null} { "id": "plink_K2zwNNSxPyx8w3GZ", "object": "payment_link", "amount": 120900, "currency": "CLP", "status": "active", "created_at": "2024-08-02T20:28:13Z", "expires_at": "2024-08-02T21:28:13Z", "max_completed_sessions": null, "mode": "test", "url": "https://pay.fintoc.com/plink_K2zwNNSxPyx8w3GZ", "customer_email": "customer@example.com", "checkout": { "description": "Use this field to add a custom description of the product the customer is buying" }, "metadata": { "your_order_id": "10000" }, "recipient_account": { "holder_id": "111111111", "number": "0000000000", "type": "checking_account", "institution_id": "cl_banco_de_chile" } } ``` ## Offer cash payments in Mexico If your organization has [cash payments](/guides/payments/cash-payment-direct-api) enabled, your `MXN` Payment Links offer cash automatically. You don't need to send any extra parameter when you create the link. Your customer sees a **Paga en efectivo** option next to the other payment methods, with the logos of the stores that accept the link's amount. After choosing it, your customer generates a voucher with the reference to pay at the store. Fintoc hides the cash option when: * No store accepts the Payment Link's amount. * Your organization's checkout session lasts less than the time your customer needs to pay in cash. ## Track payments When customers use a payment link to complete a payment, Fintoc [sends a `payment_intent.succeeded` webhook](/api/main-resources/events-reference/types-of-events) that you can use for fulfillment and reconciliation. **This webhook will contain the `metadata` keys you used to create the payment link**. For more information, see our guide on [how to complete the payment on your backend](/guides/payments/accept-a-payment#complete-the-payment-on-your-backend). For payment links, we recommend that you only listen for `payment_intent.succeeded` events. You can also see a Payment Link's successful payments in the [Dashboard](https://dashboard.fintoc.com/): * **From the Payment Links table:** Click the count in the **Payments received** column. If the link has one successful payment, the Dashboard opens that payment's detail. If the link has more than one successful payment, the Dashboard opens your payment history filtered by that link and the **Succeeded** status. Links without successful payments show `--`. * **From the payment history:** Use the **Payment Link** filter and enter the exact Payment Link ID. The filter appears when your organization has at least one Payment Link in the current mode. * **From a payment's detail:** If the payment came from a Payment Link, the **Payment Link** row shows the link's ID. Click it to open the Payment Links table filtered by that ID. To see all of a Payment Link's details in one place, click its row in the Payment Links table. The detail page shows the link amount, the number of payments received, the total received, the link's details, and the link's metadata. It also includes a **Payments** table with every payment made through the link. The **Total received** amount doesn't deduct refunds or chargebacks. ## Cancel a Payment Link You can cancel an active payment link from the Dashboard or through the API. You can only cancel active links. You can't cancel expired links, canceled links, or single-use links with a **Completed** status. ### From the Dashboard 1. Go to the Payment Links table in the [Dashboard](https://dashboard.fintoc.com/). 2. Click the three-dot menu on the row of the payment link you want to cancel. You can also open the payment link's detail page and click the three-dot menu at the top. 3. Select **Deactivate**. 4. In the confirmation modal, click **Deactivate**. The three-dot menu also has **Copy URL** and **Open link**. The Dashboard only shows **Deactivate** to users with permission to manage payment links, and only enables it for active links. > [!NOTE] > > You can't undo the deactivation of a payment link. Payments that are already in progress when you deactivate the link can still complete. ### Through the API Cancel a payment link using the cancel endpoint: ```bash theme={null} curl --request PATCH \ --url https://api.fintoc.com/v1/payment_links/plink_K2zwNNSxPyx8w3GZ/cancel \ --header 'Authorization: sk_test_0000000000000000' \ --header 'accept: application/json' ``` After you cancel a payment link, customers can’t finalize purchases using the link anymore and are redirected to an expiration page. # Agent Skills Source: https://docs.fintoc.com/guides/resources/building-with-ai/agent-skills Install Fintoc Agent Skills so your coding agent (Claude, Cursor, and others) has API context, patterns, and best practices for building Fintoc integrations. [Agent Skills](https://agentskills.io) are folders of instructions and resources that coding agents such as Claude Code and Cursor discover and use. Fintoc's skills provide product-specific context for your coding agent. Each skill routes your agent to the relevant documentation for the product and country. ## Install Install the skills into your agent: ```bash theme={null} npx skills add fintoc-com/agent-skills ``` The skills are open source at [github.com/fintoc-com/agent-skills](https://github.com/fintoc-com/agent-skills). ## How they work Skills use **progressive disclosure**. At startup, your agent loads only the name and description of each skill. When a task matches a skill, the agent reads the full instructions. This pattern keeps the startup context small and loads Fintoc-specific instructions only when needed. The skills pair well with the [Fintoc Model Context Protocol (MCP) servers](/guides/resources/building-with-ai/model-context-protocol-mcp). The skills explain *how* to build with Fintoc. The API MCP server lets your agent make API calls. ## Available skills Fintoc publishes one skill: * The **`building-with-fintoc`** skill provides context for building Fintoc integrations across the API, command-line interface, software development kits, and MCP servers. This skill identifies the relevant product area (Payments, Business Accounts, Movements, or Direct Debit) and country before suggesting endpoints or flows. # Building with AI Source: https://docs.fintoc.com/guides/resources/building-with-ai/index Speed up your Fintoc integration with AI: connect coding agents through the MCP server, install Agent Skills, and use LLM-friendly docs and patterns. You can use AI to help build your Fintoc integration. This page covers the tools Fintoc provides for AI-assisted integration. These tools include the in-product Ask AI dropdown, plain-text and `llms.txt` access to the documentation, and the Fintoc command-line interface (CLI). Fintoc also provides two Model Context Protocol (MCP) servers and a set of Agent Skills. ## Ask AI dropdown ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/b0df7c5d8c1d153ea9a6199dcc74af6847ed2b1059323debb8dd9f3910e16b7e-Screenshot_2025-07-19_at_8.56.01_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=eb96adbb31c0b62e234efa7b5ec429ad) Open the Ask AI dropdown on any guide page to ask questions about the API, request code samples, or copy the page in plain text. ## Plain text docs You can also use the Ask AI dropdown to copy any documentation page as Markdown. You can then paste the page into other AI tools, code editors, or documents while preserving the page's formatting. This format helps AI tools and agents consume Fintoc's content. Plain text also lets you copy an entire documentation page into a large language model (LLM). Use plain text instead of scraping or copying Fintoc's HTML and JavaScript-rendered pages because: * Plain text strips HTML and JavaScript wrappers, reducing rendering overhead and context-window usage. * The plain-text version includes content the default view hides, such as text inside a tab. * LLMs can parse and understand Markdown hierarchy. ## `llms.txt` Fintoc also hosts an [`/llms.txt`](https://docs.fintoc.com/llms.txt) file that tells AI agents how to retrieve the plain-text versions of Fintoc's pages. The `/llms.txt` file is an emerging standard for making websites and content more accessible to LLMs. ## Fintoc CLI AI agents such as Claude Code, Cursor, and Codex can drive the [Fintoc CLI](/guides/resources/cli) directly. You can use the Fintoc CLI to make API requests and listen to webhooks from the command line. ## MCP servers The [Fintoc MCP](/guides/resources/building-with-ai/model-context-protocol-mcp) servers let AI agents interact with the Fintoc API and search Fintoc's knowledge base, including the documentation. ## Agent Skills [Fintoc's Agent Skills](/guides/resources/building-with-ai/agent-skills) give coding agents such as Claude Code and Cursor context and best practices for building with Fintoc. Install the skills with `npx skills add fintoc-com/agent-skills`. # Model Context Protocol (MCP) Source: https://docs.fintoc.com/guides/resources/building-with-ai/model-context-protocol-mcp Connect Claude, ChatGPT, Cursor, VS Code, or Claude Code to Fintoc's MCP server so your AI agents can call the Fintoc API and search the docs. The Fintoc Model Context Protocol (MCP) server provides tools that AI agents can use to interact with the Fintoc API. Agents can also search Fintoc's knowledge base, including the documentation. Before you connect, you need an active Fintoc account with `live` mode access. You also need a supported client: Claude, ChatGPT, Cursor, VS Code, or Claude Code. ## Connect to Fintoc's MCP server > [tab] Claude > > Claude supports custom connectors on the web, desktop, mobile, and Cowork. Custom connectors are available on the Free, Pro, Max, Team, and Enterprise plans. For configuration options, see the Claude [documentation](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp). > > **Team / Enterprise:** > > 1. An Owner must first add the connector in **Organization settings → Connectors** (Add → **Custom → Web**). > > 2. Go to **Customize → Connectors**. > > 3. Find the Fintoc custom connector your Owner added and click **Connect**. > > **Pro / Max / Free:** > > 1. Go to **Customize → Connectors**. > > 2. Click **"+"** then **Add custom connector**. > > 3. Enter the server URL `https://mcp.fintoc.com`. > > 4. Click **Add**, then connect and authenticate via OAuth. > > Enable the connector for each conversation from the **"+"** button in chat → **Connectors**. > [tab] ChatGPT > > You can enable MCP servers on ChatGPT with a Pro, Plus, Business, Enterprise, or Education account. Follow the OpenAI [documentation](https://platform.openai.com/docs/guides/developer-mode) for instructions. Use the following parameters when setting up your custom connector: > > * The server URL is `https://mcp.fintoc.com`. > * Use `OAuth` as the connection mechanism. > > Fintoc's MCP server also works with OpenAI's Responses API when you build autonomous agents. > [tab] Cursor > > Add the following to your `~/.cursor/mcp.json` file. For configuration options, see the Cursor [documentation](https://cursor.com/docs). > > ```json theme={null} > { > "mcpServers": { > "fintoc": { > "url": "https://mcp.fintoc.com" > } > } > } > ``` > [tab] VS Code > > Add the following to your `~/.vscode/mcp.json`. For configuration options, see the VS Code [documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers). > > ```json theme={null} > { > "servers": { > "fintoc": { > "type": "http", > "url": "https://mcp.fintoc.com" > } > } > } > ``` > [tab] Claude Code > > Run the following command: > > ```bash theme={null} > claude mcp add --transport http fintoc https://mcp.fintoc.com > ``` > [tab] Other > > MCP is an open protocol supported by many clients. See your client's documentation for connection instructions. Use the server URL `https://mcp.fintoc.com` and `OAuth` as the connection mechanism if possible. > > ```json theme={null} > { > "fintoc": { > "url": "https://mcp.fintoc.com" > } > } > ``` When the client opens the connection, Fintoc shows a consent screen. Authorize the connection and select the scopes to grant to your MCP session. **A token operates only in `live` mode.** The consent screen only lists scopes that meet both of these conditions: * You have the matching resource permission in the dashboard. Each scope corresponds to a resource and access level from your [dashboard role](/guides/home/dashboard/permission-roles). For example, `movement:view` requires Read access to **Movements**. * Your organization has the product that the resource belongs to. For example, `movement:view` only appears if your organization has the Movements product. If a scope is missing from the consent screen, Fintoc can't grant it to your MCP session. An existing connection keeps the scopes you authorized for that connection. To use operations that need a scope added after authorization, reconnect the client. Then grant the required scope, such as **Team** for managing your organization's users, on the consent screen. ### Read-only sessions Each scope has an access level: `view` for reading, or `manage` for creating and changing data. A `manage` scope includes the matching `view` scope. To give an agent read-only access, grant only `view` scopes on the consent screen. Operations that need a `manage` scope then fail, so the agent can't create payments, transfers, or other records. ## Tools We recommend enabling human confirmation before tools run. Use caution when you run the Fintoc MCP server with other servers to avoid prompt injection attacks. To request more tools or share feedback, ask your agent to use the `submit_feedback` tool, or contact Fintoc support at [soporte@fintoc.com](mailto:soporte@fintoc.com). The server exposes the following [MCP tools](https://modelcontextprotocol.io/docs/concepts/tools): | Category | Tool | Description | | - | - | - | | Operations | `fintoc_tool_search` | Search the operations available through Fintoc MCP. | | Operations | `fintoc_tool_details` | Get the parameters and permissions for an operation. | | Operations | `fintoc_tool_read` | Read data from Fintoc. | | Operations | `fintoc_tool_write` | Write data in Fintoc. Some operations can move money. | | Resources | `fetch_resource` | Retrieve a Fintoc resource by its `id`. | | Other | `submit_feedback` | Report blockers or unexpected behavior to Fintoc. | The operation tools make supported Fintoc actions available through MCP without exposing one tool per action. This keeps the tool set compact as Fintoc adds more capabilities. ### Supported operations The Fintoc MCP server currently supports: * Payments: list and create customers; list payment intents, checkout sessions, and payment methods; list, create, and cancel refunds * Billing: create, finalize, and void invoices; list, create, and update subscriptions * Your Fintoc invoices: list the invoices Fintoc issues to your organization * Movements: list links, linked bank accounts, and movements * Payouts: list payouts and payout resources * Business Accounts: list accounts, account statements, entities, account numbers, and transfers; create account numbers * Webhooks: list, create, and update webhook endpoints * IP restrictions: add an allowed IP range ([Classless Inter-Domain Routing (CIDR) block](/guides/resources/security-controls)) to your organization * Team: list organization users and assignable roles; invite users with a [predefined role](/guides/home/dashboard/permission-roles) The operations available in a session depend on your Fintoc products and the scopes granted during authorization. ### Required scopes Each operation requires one scope. Use `fintoc_tool_details` to see the scope for a specific operation. | Operations | Required scope | | - | - | | List customers, list payment methods | `customer:view` | | Create customers | `customer:manage` | | List payment intents and checkout sessions | `payment:view` | | List refunds | `refund:view` | | Create and cancel refunds | `refund:manage` | | Create, finalize, and void invoices | `invoicing_invoice:manage` | | List subscriptions | `invoicing_subscription:view` | | Create and update subscriptions | `invoicing_subscription:manage` | | List your Fintoc invoices | `billing:view` | | List links | `link:view` | | List linked bank accounts and movements (Movements product) | `movement:view` | | List payouts and payout resources | `payout:view` | | List accounts and account statements for Business Accounts | `account:view` | | List entities | `entity:view` | | List account numbers | `account_number:view` | | Create account numbers | `account_number:manage` | | List transfers | `transfer:view` | | List webhook endpoints | `webhook_endpoint:view` | | Create and update webhook endpoints | `webhook_endpoint:manage` | | Add an allowed IP range | `allowed_cidr_block:manage` | | List organization users and assignable roles | `organization_user:view` | | Invite users | `organization_user:manage` | ### Troubleshooting: a required scope isn't on the consent screen If an operation fails because a scope is missing, check whether the scope appears on the consent screen. If it does not, your dashboard user lacks the matching permission or your organization lacks the product. For example, `list_links` works but `list_movements` fails with a missing `movement:view` scope. 1. Ask an Admin of your organization to grant you the required access level for the resource in the dashboard. For `movement:view`, that's Read access to **Movements** under Reconciliation. See [Permission roles](/guides/home/dashboard/permission-roles). 2. If the resource isn't available in your organization, contact Fintoc support to enable the product. 3. Reconnect your MCP client and grant the scope on the consent screen. **Actions the server does not expose** Some actions have no tool on purpose, so an agent cannot take them on your behalf: * Paying an invoice. Use [Pay an invoice](/api/payments-api/invoices/invoices-pay). * Canceling a subscription. Use [Cancel a subscription](/api/payments-api/subscriptions/subscriptions-cancel). * Detaching the payment method of a subscription. Use [Detach the payment method from a subscription](/api/payments-api/subscriptions/subscriptions-detach-payment-method). * Changing a user's role or removing a user from your organization. Use the dashboard. Refunds are the exception. A refund returns money to the customer who paid, and you can cancel it while it is still pending. ## Connect to the Fintoc Docs MCP server The docs server lets an agent answer questions about the Fintoc API by querying the documentation. Use it when you want code samples, endpoint lookups, or explanations without leaving your editor. > [tab] Cursor > > Add the following to your `~/.cursor/mcp.json` file. For configuration options, see the Cursor [documentation](https://cursor.com/docs). > > ```json theme={null} > { > "mcpServers": { > "fintoc-docs": { > "url": "https://docs.fintoc.com/mcp" > } > } > } > ``` > [tab] VS Code > > Add the following to your `~/.vscode/mcp.json`. For configuration options, see the VS Code [documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers). > > ```json theme={null} > { > "servers": { > "fintoc-docs": { > "type": "http", > "url": "https://docs.fintoc.com/mcp" > } > } > } > ``` > [tab] Claude Code > > Run the following command: > > ```bash theme={null} > claude mcp add --transport http fintoc-docs https://docs.fintoc.com/mcp > ``` > [tab] ChatGPT > > You can enable MCP servers on ChatGPT with a Pro, Plus, Business, Enterprise, or Education account. Follow the OpenAI [documentation](https://platform.openai.com/docs/guides/developer-mode) for instructions. Use the following parameters when setting up your custom connector: > > * The server URL is `https://docs.fintoc.com/mcp`. > * Use `OAuth` as the connection mechanism. > > The Fintoc Docs MCP server also works with OpenAI's Responses API when you build autonomous agents. > [tab] Other > > MCP is an open protocol supported by many clients. See your client's documentation for connection instructions. Use the server URL `https://docs.fintoc.com/mcp`. > > ```json theme={null} > { > "fintoc-docs": { > "url": "https://docs.fintoc.com/mcp" > } > } > ``` # Fintoc CLI keys Source: https://docs.fintoc.com/guides/resources/cli/fintoc-cli-keys-and-permissions Learn how the Fintoc CLI resolves API keys, where they're stored, and how to switch between them. This page explains how the Fintoc CLI resolves, stores, and switches API keys. When you run `fintoc login`, the CLI stores your secret key in `~/.fintoc/config.toml`. The file uses mode `0600`, so only the current operating system user can read it. You can also provide a key with `--api-key` or the `FINTOC_API_KEY` environment variable. ## Key resolution order The CLI resolves the API key in this order of precedence: 1. The inline `--api-key` flag. 2. The `FINTOC_API_KEY` environment variable. 3. The key stored in `~/.fintoc/config.toml` by `fintoc login`. The CLI uses the first available source. This precedence lets you keep a default `test` mode key in your configuration file and override the key for each command. Use an override to switch between Fintoc organizations or between `test` and `live` modes. ## View your active configuration ```bash theme={null} fintoc config show ``` This command prints a masked version of the active API key, the resolved environment, and the configuration file path. ## Switch keys To change the persisted key, log out and log back in: ```bash theme={null} fintoc logout fintoc login ``` To override the persisted key for a single command: ```bash theme={null} fintoc payment_intents list --api-key sk_test_a1b2c3d4e5f6g7h8i9j0 ``` ## Use the CLI in continuous integration For continuous integration and delivery pipelines, set `FINTOC_API_KEY` as a secret environment variable in your provider. For example, you can configure the variable in GitHub Actions or CircleCI. Avoid persisting credentials to disk: ```bash theme={null} export FINTOC_API_KEY=sk_test_a1b2c3d4e5f6g7h8i9j0 fintoc payment_intents list --json ``` This approach skips the interactive `fintoc login` flow and avoids writing the key to the configuration file. ## Compare `test` and `live` modes Each Fintoc API key is scoped to either `test` mode or `live` mode. The CLI infers the mode from the key prefix: * `sk_test_...` identifies a `test` mode key. A `test` mode key never moves real money: the CLI creates no real payments or refunds. * `sk_live_...` identifies a `live` mode key. Commands run with this key create real payments and refunds on your production organization. The CLI works in both `test` and `live` modes. Resource commands such as `fintoc payment_intents list` work with either key. Commands that simulate events, such as `fintoc trigger`, run only in `test` mode and return an error with a `live` key. By default, `fintoc login` authenticates in `test` mode. To authenticate in `live` mode, pass `--mode live`: ```bash theme={null} fintoc login --mode live ``` # Fintoc CLI Source: https://docs.fintoc.com/guides/resources/cli/index Use the command line to manage your Fintoc resources during development. Use the Fintoc command-line interface (CLI) to make API requests and listen to webhooks. > [card] [Install](/guides/resources/cli/install-the-fintoc-cli) > > Install the CLI on macOS or Linux. > [card] [Authenticate](/guides/resources/cli/fintoc-cli-keys-and-permissions) > > Manage API keys and switch between them. > [card] [Use the CLI](/guides/resources/cli/use-the-fintoc-cli) > > Make API requests and listen to webhooks. ## Requirements To install the CLI, you need: * Node.js 22 or later. * A Fintoc account, which you can create in the [Fintoc Dashboard](https://dashboard.fintoc.com/login). # Install the Fintoc CLI Source: https://docs.fintoc.com/guides/resources/cli/install-the-fintoc-cli Install the Fintoc CLI on macOS, Linux, or Windows to test webhooks, trigger events, and interact with the Fintoc API from your terminal. Install the Fintoc CLI to make API requests and listen to webhooks from the command line. You can use the CLI to: * Create, retrieve, update, or delete any of your Fintoc resources in `test` mode. * Receive webhooks at `localhost` without a public tunnel and without creating new webhook endpoints. ## Choose an installation method ### npm Fintoc publishes the CLI to npm for macOS, Linux, and Windows. The CLI requires Node.js 22 or later. On Windows, install with npm because Homebrew is not available. To install with npm, run: ```bash theme={null} npm install -g @fintoc/cli fintoc --version ``` `npm install -g @fintoc/cli` works in PowerShell and Command Prompt on Windows. ### Homebrew Homebrew is available on macOS and Linux. To install with Homebrew, run: ```bash theme={null} brew install fintoc-com/tap/fintoc fintoc --version ``` To update, run: ```bash theme={null} brew update && brew upgrade fintoc ``` ## Log in to the CLI Authenticate the CLI with a Fintoc API key. ```bash theme={null} fintoc login ``` This command opens an interactive flow. To skip the browser flow, pass the API key inline with the `--api-key` flag: ```bash theme={null} fintoc login --api-key sk_test_xxx ``` By default, `fintoc login` authenticates in `test` mode. Pass `--mode live` to log in to `live` mode instead. To avoid storing the API key, export the `FINTOC_API_KEY` environment variable. The CLI reads this variable automatically. See [Fintoc CLI keys](/guides/resources/cli/fintoc-cli-keys-and-permissions) for the full precedence order. ## Verify your setup `fintoc doctor` verifies your CLI setup. The command checks the resolved API key, the Node.js version, the config file path, and connectivity to `api.fintoc.com`. Use `fintoc doctor` to debug authentication or connectivity errors. ```bash theme={null} fintoc doctor ``` # Use the Fintoc CLI Source: https://docs.fintoc.com/guides/resources/cli/use-the-fintoc-cli Use the Fintoc CLI to make API requests, trigger test events, forward webhooks, and manage resources like charges, checkout sessions, and links from your shell. Use the Fintoc CLI to make API requests, trigger test events, and forward webhooks to your local server. ## Available resources Every command follows the pattern `fintoc [flags]`. The CLI supports these resources and actions: | Resource | Actions | | - | - | | `api_keys` | `list` | | `charges` | `create`, `get`, `list` | | `checkout_sessions` | `create`, `get`, `expire` | | `links` | `get`, `list`, `delete` | | `payment_intents` | `get`, `list` | | `subscriptions` | `get`, `list` | | `webhook_endpoints` | `create`, `get`, `list`, `delete` | | `v2 account_numbers` | `create`, `get`, `list`, `delete` | | `v2 account_verifications` | `create`, `get`, `list` | | `v2 accounts` | `get`, `list` | | `v2 movements` | `get`, `list` | | `v2 transfers` | `create`, `get`, `list` | ## Make an API request The general form is `fintoc [flags]`. Run `fintoc --help` to list available resources. Run `fintoc --help` to list the resource's actions. ```bash theme={null} fintoc payment_intents list fintoc charges create --amount 5000 --currency CLP --subscription-id sub_test_abc123 fintoc charges create --from-json payload.json ``` Use `--json` for machine-readable output: ```bash theme={null} fintoc payment_intents list --json ``` ```json theme={null} [ { "id": "pi_test_a1b2c3d4e5f6g7h8", "object": "payment_intent", "amount": 100000, "currency": "CLP", "status": "succeeded" } ] ``` > [!NOTE] > > `v2 transfers create` requires a JSON Web Signature (JWS) private key for signing. Provide it via the `--jws-private-key` flag or set `jws_private_key` in `~/.fintoc/config.toml`. To generate a key pair, see [Generate JWS keys](/guides/business-accounts/setup/setting-up-jws-keys). ```bash theme={null} fintoc v2 transfers create --amount 10000 --currency CLP \ --account-id acc_test_abc123 \ --counterparty-account-number 00000000 \ --counterparty-institution-id cl_banco_estado \ --jws-private-key ~/path/to/private_key.pem ``` ## Pass a JSON payload For `create` commands, pass a payload file with `--from-json`, or pipe one in with `-`: ```bash theme={null} fintoc charges create --from-json payload.json cat payload.json | fintoc charges create --from-json - ``` You can mix flags with `--from-json`. Flag values take precedence over JSON keys. The CLI merges nested objects but replaces entire arrays. ## Delete a resource Delete commands ask for confirmation before removing the resource. Pass `--yes` to skip the prompt in automated environments. ```bash theme={null} fintoc webhook_endpoints delete we_test_abc123 fintoc webhook_endpoints delete we_test_abc123 --yes ``` ## Trigger test events `fintoc trigger` generates a test event for your account. The event exercises your webhook handlers without producing real activity. ```bash theme={null} fintoc trigger payment_intent.succeeded fintoc trigger payment_intent.succeeded --override amount=5000 --override currency=CLP fintoc trigger payment_intent.succeeded --from-json overrides.json ``` `--override` accepts dot notation (`metadata.order_id=abc123`). You can repeat the flag. The same precedence rules as `--from-json` apply. `fintoc trigger` works only with `test` API keys. It accepts the event types listed in [Types of events](/api/main-resources/events-reference/types-of-events), including Business Accounts events: ```bash theme={null} fintoc trigger transfer.inbound.succeeded --override amount=20000 --override currency=MXN fintoc trigger transfer.outbound.failed ``` Fintoc ignores overrides for `id`, `object`, `mode`, `status`, `created_at`, and `updated_at`. To test a different status, trigger the matching event type instead. ## Listen to webhooks on localhost `fintoc webhooks listen` opens a WebSocket connection to Fintoc and forwards events to your local server. The CLI signs each forwarded request. You can use your existing signature verification without a public tunnel. ```bash theme={null} fintoc webhooks listen --forward-to http://localhost:3000/webhooks ``` Filter by event type: ```bash theme={null} fintoc webhooks listen --forward-to http://localhost:3000/webhooks --events payment_intent.succeeded,payment_intent.failed ``` # SDKs and integrations Source: https://docs.fintoc.com/guides/resources/libraries-and-integrations/index Official Fintoc SDKs for Python, Node, Ruby, vanilla JavaScript, and React Native, plus community libraries that wrap the Fintoc API. This page lists the official Fintoc SDKs and the community libraries that wrap the Fintoc API. ## Official SDKs Use an official SDK to call the Fintoc API with idiomatic code instead of building your own HTTP client. This section lists every official library. To contribute, open an issue or a pull request on the relevant repository. ### Server-side SDKs > [card] [Python](https://github.com/fintoc-com/fintoc-python) > > fintoc-python > [card] [Node](https://github.com/fintoc-com/fintoc-node) > > fintoc-node > [card] [Ruby](https://github.com/fintoc-com/fintoc-ruby) > > fintoc-ruby ### Frontend SDKs > [card] [Vanilla JavaScript](https://github.com/fintoc-com/fintoc-js) > > fintoc-js > [card] [React Native](https://github.com/fintoc-com/fintoc-react-native) > > fintoc-react-native ## Community libraries If Fintoc does not offer an official library for your language, the community may maintain one. If no official or community library exists for your language and you build one, contact Fintoc to have it added to this list. > [card] [Swift](https://github.com/sergiocampama/Fintoc) > > sergiocampama/Fintoc > [card] [Go](https://github.com/psotou/fintoc) > > psotou/fintoc ## Acknowledgments Thanks to the community members who created or maintain these libraries: * [Nebil Kawas](https://github.com/nebil) * [Daniel Leal](https://github.com/daleal) * [Juan Carlos Sardin](https://github.com/sardavend) * [Vicente Lubascher](https://github.com/velubascher) * [Sergio Campamá](https://github.com/sergiocampama) * [Pascual Soto](https://github.com/psotou) * [Nicolás Quiroz](https://github.com/naquiroz) * [María Luisa Claro](https://github.com/marialuisaclaro) # Connect your bank account to Zapier Source: https://docs.fintoc.com/guides/resources/libraries-and-integrations/libraries-and-integrations-zapier Connect your bank account to more than 2,000 apps through Zapier. By the end of this guide, you will have a Zap that triggers on every new movement in your connected bank account. The Zap then sends the movement to another application. The Fintoc integration with [Zapier](https://zapier.com) connects your bank account to more than 2,000 applications without writing code. For example, you can send bank movements to Google Sheets or connect your bank account to [QuickBooks](https://quickbooks.intuit.com/global/). > [!WARNING] > > **Historical movements** > > Zapier only shows movements created after you make the connection. You cannot access historical movements. ## Connect your Link to Zapier In Zapier's application list, search for Fintoc and select the `New Movement` trigger. The Fintoc integration is in beta. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/87d75a3-Captura_de_pantalla_2021-01-21_a_las_17.22.42.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=e32d3e984b696b64a1f5f3a82cf8c1a2) Select the `Link` you want to connect to Zapier. If you do not have a `Link`, create one in the [Fintoc Dashboard](https://app.fintoc.com). Save the `link_token` for the new `Link`. In Zapier, select **Connect a new account**. Enter your [secret key](/guides/home/api-keys) and the `link_token` for the `Link`. After you connect your `Link`, Zapier displays the accounts associated with the `Link`. Continue to the account selection step. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/c7de96e-Captura_de_pantalla_2021-01-21_a_las_17.28.25.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=daaa846c27a4172e884d759ee8b8f2d9) ## Select your bank account Zapier displays every bank account associated with the `Link`. Select the account you want to connect and continue. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/c355ffd-Captura_de_pantalla_2021-01-21_a_las_17.30.06.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=7c2d6754ea0d7c78231794bd8f8aa194) ## Test the integration Test the Zap by making a transaction on the connected account or waiting for the next movement to post. After Zapier receives a movement, Zapier adds the movement to the trigger's test data. The Zap then runs your downstream action, such as creating a spreadsheet row. If no movement appears, verify the secret key and `link_token` you entered. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/84ce3b3-Captura_de_pantalla_2021-01-21_a_las_17.32.41.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=97695c32281220b1b3f3e4521c103fe4) # Security controls Source: https://docs.fintoc.com/guides/resources/security-controls Six controls that protect integrations with the Fintoc API: API keys, request signing, IP allowlisting, webhook verification, idempotency, and audits. Fintoc applies six security controls across the public API. These controls restrict access to authorized parties, protect requests from tampering in transit, prevent duplicate operations, and let you audit API activity. *** ## 1. Authenticate all API requests with API keys Every request to the Fintoc API must include an API key. Fintoc API keys have these properties: * Each API key is unique per organization. * The Fintoc Dashboard shows the key only once, at creation time. * You must store the key securely. * If a key is lost or compromised, rotate or revoke it immediately from the Fintoc Dashboard. API keys identify the calling organization and prevent unauthorized access to the API. 📚 [Manage API keys](/guides/home/api-keys) *** ## 2. Sign all money movement requests with JWS Requests that move money, such as creating outbound transfers, require an additional security layer using a JSON Web Signature (JWS). The JWS key pair has two parts: * A private JWS key that you store securely and use to sign requests. * A public JWS key that you register in the Fintoc Dashboard so Fintoc can verify each signature. The JWS keys are static, but each signature is unique and time-bound. Each signature includes: * A `nonce`, which makes each signature single-use. * A `ts` timestamp, which limits how long the request is valid. The JWS signature: * Protects the integrity of the request payload. * Confirms the authenticity of the sender. * Prevents replay attacks. Fintoc automatically rejects requests that are unsigned, expired, duplicated, or modified. 📚 [Set up JWS keys](/guides/business-accounts/setup/setting-up-jws-keys) *** ## 3. Restrict API access with IP allowlisting (optional) You can configure an IP allowlist in the Fintoc Dashboard to control where API requests can originate from. When you enable IP allowlisting: * Fintoc accepts requests only from approved IP addresses. * Fintoc blocks requests from other locations, even if the API key is valid. This control reduces risk if credentials are leaked and enforces infrastructure-level access restrictions. 📚 [Configure IP restrictions](/guides/home/api-keys#configure-ip-restrictions) *** ## 4. Verify webhook signatures Fintoc signs all webhook events before sending them to your systems. Always verify webhook signatures before processing an event. Verifying the signature lets you: * Confirm that Fintoc sent the event. * Detect payload tampering. * Discard forged or replayed webhook requests. Verifying webhook signatures ensures that downstream systems react only to trusted events. 📚 [Validate webhook signatures](/guides/resources/webhooks-walkthrough/webhooks-validating) *** ## 5. Prevent duplicate operations with idempotency To avoid accidental duplicate operations, Fintoc supports idempotency keys for requests such as creating payouts. When you send an idempotency key: * Retried requests do not create duplicate operations. * You can retry requests after network timeouts without creating duplicate operations. When you retry a request with the same idempotency key, Fintoc returns the original result instead of creating a duplicate. 📚 [Use an idempotency key](/guides/business-accounts/outbound-transfers#use-an-idempotency-key) *** ## 6. Audit API usage All interactions with the Fintoc API are traceable and auditable. The audit trail includes: * API-key-based identification of the calling organization. * Timestamped requests for sensitive operations. * Logged API requests and resource state changes. These records help you: * Monitor and review API activity. * Support internal audits and compliance processes. * Investigate incidents or unexpected behavior. *** ## Controls summary The following table maps each control to the risk it mitigates: | Control | Risk mitigated | | - | - | | API key authentication | Unauthorized API access | | JWS-signed requests | Payload tampering, request forgery, replay attacks | | IP allowlisting | Credential leakage, unauthorized infrastructure access | | Webhook signature verification | Forged or manipulated webhook events | | Idempotent requests | Duplicate operations caused by retries or network failures | | Auditable API activity | Undetected misuse, limited traceability, audit gaps | Together, these controls cover authentication, request integrity, retry safety, and auditability across the Fintoc API. # Test mode Source: https://docs.fintoc.com/guides/resources/test-mode Use Fintoc test mode to simulate payments, webhooks, and bank connections with test API keys before switching your integration to live mode. Fintoc's `test` mode, also called the sandbox, lets you test the API without making payments or connecting a real account. The sandbox creates simulated objects without affecting real transactions or moving money. To use `test` mode, send your `test` [API keys](/guides/home/api-keys) when you call the API. You can find your `test` API keys in the [Dashboard](https://app.fintoc.com). API keys for `test` mode have the `sk_test_` and `pk_test_` prefixes. The documentation pages for each product list the `test` credentials, so you can test every flow your users might follow. You can use `test` mode for [Movements](/guides/movements/data-aggregation-test-your-integration), [Payment Initiation](/guides/payments/payment-initiation-test-your-integration), and [Business Accounts](/guides/business-accounts/setup/test-your-integration). ## Test mode versus live mode All Fintoc API requests occur in either `test` or `live` mode. API objects in one mode aren’t accessible from the other. The following table compares both modes: | Mode | When to use | Objects | How to use | | :- | :- | :- | :- | | `test` mode | Use `test` mode and its associated API keys as you build your integration. | API calls return simulated objects. For example, you can retrieve and use simulated `Link`, `Movement`, `CheckoutSession`, and `Subscription` objects. | Use test bank accounts. You can’t accept real payment methods or work with real accounts. | | `live` mode | Use `live` mode and its associated API keys when you’re ready to launch your integration and accept money or connect real accounts. | API calls return real objects. For example, you can retrieve and use real `Link`, `Movement`, `CheckoutSession`, and `Subscription` objects. | Use real bank accounts and work with customer accounts. You can accept real payment authorizations and charges, and connect real links. | The **Test mode** toggle in the Dashboard doesn’t affect your integration code. Your `test` and `live` API keys determine your code's behavior. ## Why the Dashboard shows different sections in test and live mode Every Fintoc product appears in `test` mode so you can explore the Dashboard. In `live` mode, a section you saw in `test` mode, such as **Tesorería**, may not appear for two reasons: * **The product isn’t enabled for your organization yet.** If a section is missing, contact your Sales or Customer Success representative, or use the chat. * **Your role doesn’t include permission to view that section.** Even when a product is enabled, you can see that section only if your role grants **View** access. If a teammate can see the section and you can’t, ask your Administrator to grant you access. See [Permission Roles](/guides/home/dashboard/permission-roles) for how access levels work. # Webhooks overview Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/index How Fintoc webhooks work: create an endpoint, test it, register it, and receive Event objects that keep your application in sync with Fintoc. This page explains how Fintoc webhooks work and how to set them up. Webhooks notify your server when an event occurs in Fintoc. Your application can respond to the event and stay synchronized with Fintoc. Fintoc uses webhooks to notify your application about events in your users' bank accounts. For example, Fintoc can no longer retrieve new movements after an account holder changes their bank password. Another event occurs when the movement for a protested check no longer exists in the bank. Fintoc also sends webhooks for events within Fintoc. For example, Fintoc sends an event when an account finishes syncing with the latest available data from the bank. To use Fintoc webhooks, follow these steps: 1. [Create](/guides/resources/webhooks-walkthrough/webhooks-creating-guide) a webhook endpoint on your server to receive webhooks. 2. [Test](/guides/resources/webhooks-walkthrough/webhooks-testing) the webhook endpoint with test events. 3. [Register](/guides/resources/webhooks-walkthrough/webhooks-activating) the webhook endpoint in Fintoc. Once your endpoint runs in `live` mode, [recover missed events](/guides/resources/webhooks-walkthrough/webhooks-recovering-events) to catch up on the events your endpoint did not process during an outage. A webhook endpoint is a route in your application that receives notifications from Fintoc. Assign the endpoint a URL that Fintoc can use to send notifications. Fintoc sends each notification as an [`Event`](/api/main-resources/events-reference/events-object) object. The object contains information about what happened. Use this information in your webhook endpoint to keep your application's state synchronized. For example, you may need to prompt an account holder to reconnect their bank account with Fintoc after changing their bank password. # Activate your webhook endpoint Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-activating Register your webhook endpoint with Fintoc through the API or the Dashboard, save the secret used to validate webhook signatures, and manage endpoints. [Write](/guides/resources/webhooks-walkthrough/webhooks-creating-guide) and [test](/guides/resources/webhooks-walkthrough/webhooks-testing) your webhook endpoint, then deploy the code to production. Register the endpoint with Fintoc to receive notifications about new events. ## Register your webhook endpoint You can register a webhook endpoint [through the API](/api/main-resources/webhook-endpoints/webhook-endpoints-list) or through the [Fintoc Dashboard](https://dashboard.fintoc.com/webhooks). Webhook endpoint URLs must use HTTPS. > [!NOTE] > > **Retrieving your webhook secret** > > Registering an endpoint generates a `secret` used to [validate webhook signatures](/guides/resources/webhooks-walkthrough/webhooks-validating). The API returns the `secret` only once in the create response. Subsequent API responses include `secret` as `null`. If you did not save the `secret`, you can view the `secret` under the webhook endpoint settings in the [Fintoc Dashboard](https://dashboard.fintoc.com/webhooks). ### Add an endpoint through the API Call [Create webhook endpoint](/api/main-resources/webhook-endpoints/webhook-endpoints-create) to add an endpoint through the API. ### Add an endpoint through the Dashboard Go to the `Webhooks` section of the Dashboard, then click the button to subscribe a webhook. The Dashboard opens a modal. Enter your webhook endpoint URL and select the events that Fintoc sends to the URL. Make sure you are in `live` mode. Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. ## Manage your webhook endpoints You can [disable or update](/api/main-resources/webhook-endpoints/webhook-endpoints-update) an existing webhook endpoint in your organization. You can also [delete the endpoint](/api/main-resources/webhook-endpoints/webhook-endpoints-delete). From the Dashboard, you can disable or delete webhook endpoints. Ask Luna Open Luna Open the dashboard and paste this prompt into the Luna chat. # Create your webhook endpoint Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-creating-guide Build a webhook endpoint to receive and process events from Fintoc. A webhook endpoint works like any other application endpoint, with additional delivery and retry considerations. Review [Webhook best practices](/guides/resources/webhooks-walkthrough/webhooks-good-practices) before implementing your endpoint. ## Key considerations When an event occurs, Fintoc sends a `POST` request with a JSON body to every registered webhook endpoint. Parse the JSON body to access the event details. Your webhook endpoint must parse the `POST` request and return a status code in the `2xx` range. ### Save the received event Every webhook event sent by Fintoc has a unique `id`. Save each event `id` in your application's database. Use the saved `id` to detect duplicate deliveries and process each event only once. ### Return a `2xx` status code before the timeout To confirm receipt of an event, respond with a `2xx` HTTP status code. Fintoc treats any other status code as a failed attempt. Respond with a `2xx` status code before Fintoc's delivery timeout. Run logic that does not need to complete before acknowledgment asynchronously so the handler returns before the timeout. ### Handle retries and failed deliveries Fintoc treats a delivery as a **failed attempt** if your endpoint responds with any status code outside the `2xx` range or if the request times out. When a delivery fails, Fintoc automatically retries it using **exponential backoff**, starting 3 seconds after the failed attempt. Fintoc makes **up to 17 retry attempts** for each event. If every attempt fails, Fintoc stops retrying that event. The following limitations apply: * Fintoc does **not** disable the webhook endpoint automatically or notify you when it stops retrying an event. * Fintoc does **not** support manual replay or a dead-letter mechanism to resend a failed event. Fintoc can deliver the **same event more than once**, so your endpoint must be idempotent. To handle duplicate events, see [Handle duplicate events](/guides/resources/webhooks-walkthrough/webhooks-good-practices#handle-duplicate-events). ### Test the webhook Fintoc sends webhook events only when the underlying action occurs. A handler bug can therefore go unnoticed until the endpoint receives production traffic. Test your endpoint when you create it, register it, or change how it receives events. For the step-by-step test procedure, including how to expose your local endpoint and send a test event, see [Test your webhook endpoint](/guides/resources/webhooks-walkthrough/webhooks-testing). ## Sample code **Webhook handler (Python)** ```python theme={null} import json from flask import Flask, jsonify, request app = Flask(__name__) @app.route('/webhook', methods=['POST']) def webhook(): payload = request.data try: event = json.loads(payload) except (json.JSONDecodeError, UnicodeDecodeError): return jsonify(received=False), 400 if not isinstance(event, dict) or 'type' not in event: return jsonify(received=False), 400 # Add idempotency with your app's ORM. # Handle the event if event['type'] == 'link.credentials_changed': link_id = event['data']['id'] # Then define and call a method to handle the credentials changed event. elif event['type'] == 'link.refresh_intent.succeeded': link_id = event['data']['refreshed_object_id'] # Then define and call a method to handle the link refreshed event. elif event['type'] == 'account.refresh_intent.succeeded': account_id = event['data']['refreshed_object_id'] # Then define and call a method to handle the account refreshed event. # ... handle other event types else: # Unexpected event type print('Unhandled event type {}'.format(event['type'])) return jsonify(received=True) ``` **Webhook handler (Node.js)** ```javascript theme={null} // This example uses Express to receive webhooks const app = require('express')(); // Use body-parser to retrieve the raw body as a buffer const bodyParser = require('body-parser'); app.post('/webhook', bodyParser.raw({ type: 'application/json' }), (request, response) => { let event; try { event = JSON.parse(request.body); } catch { return response.status(400).json({ received: false }); } if (!event || typeof event !== 'object' || typeof event.type !== 'string') { return response.status(400).json({ received: false }); } // Add idempotency with your app's ORM. // Handle the event switch (event.type) { case 'link.credentials_changed': { const linkId = event.data.id; // Define and call a method to handle the credentials changed event. break; } case 'link.refresh_intent.succeeded': { const linkId = event.data.refreshed_object_id; // Define and call a method to handle the link refreshed event. break; } case 'account.refresh_intent.succeeded': { const accountId = event.data.refreshed_object_id; // Define and call a method to handle the account refreshed event. break; } // ... handle other event types default: // Unexpected event type console.log(`Unhandled event type ${event.type}`); } // Return a response to acknowledge receipt of the event response.json({ received: true }); }); app.listen(8000, () => console.log('Running on port 8000')); ``` # Webhook best practices Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-good-practices Filter events, handle duplicate deliveries idempotently, recover missed events from the Events API, and verify webhook signatures and Fintoc source IPs. This page covers practices that keep your webhook endpoint secure and your Fintoc integration reliable. You learn how to filter events, handle duplicate deliveries, recover the events your endpoint missed, and verify that events come from Fintoc. ## Choose event types Configure your endpoint to listen only to the events your application needs. Ignoring the rest avoids extra load on your server. ## Handle duplicate events Fintoc can send the same event more than once, such as after a delivery retry. Make your endpoint idempotent so repeated events cause no duplicate work. Store each event's `id` after processing the event. Discard events with an `id` you have already stored. ## Recover missed events Your endpoint can miss an event, such as when your server is down or your handler fails after Fintoc records the delivery. [List events](/api/main-resources/events-reference/events-list) returns the events Fintoc generated for your organization, so you can reprocess them without waiting for a redelivery. Filter by `type`, by `resource_id`, or by the `since` and `until` time range to find the events you missed. Each event carries in `data` the same payload Fintoc sent to your endpoint. To inspect a single event, [get the event](/api/main-resources/events-reference/events-get) with the `id` you received. ## Security Securing your endpoints protects your customers' information. Use HTTPS to protect your endpoint and verify each event's origin. ### Receive events with an HTTPS server Your webhook endpoint must serve HTTPS with a valid TLS certificate. Fintoc does not send events to endpoints without a valid certificate. ### Verify that events come from Fintoc [Verify webhook signatures](/guides/resources/webhooks-walkthrough/webhooks-validating) to confirm events come from Fintoc. Also verify that events originate from one of these IP addresses: ```text theme={null} 35.231.182.34 136.109.248.140 ``` # Recover missed events Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-recovering-events List the events Fintoc generated during the window your webhook endpoint missed, filter by type, resource, or time, and reprocess them through your handler. By the end of this guide, your application can rebuild the state it lost while your webhook endpoint was missing events. Your endpoint misses events when your server is down, when your handler fails after Fintoc records the delivery, or when a deploy drops requests. Fintoc stores every event it generates for your organization, so you can fetch the window you lost and process it yourself. ## Find the window you missed Establish two moments: the last event your application processed, and the time your endpoint started responding again. If you store each event `id` as the [best practices](/guides/resources/webhooks-walkthrough/webhooks-good-practices) page recommends, read the first moment from your own records. Otherwise use the start and the end of the incident. A window wider than the outage is safe when your handler is idempotent, because an event you already processed causes no further work. ## List the events in that window Call [List events](/api/main-resources/events-reference/events-list) with the window as `since` and `until`. Both accept a calendar date such as `2026-01-15` or an ISO 8601 datetime such as `2026-01-15T09:00:00Z`. Your API key decides the mode: a `test` key returns `test` events and a `live` key returns `live` events. ```bash Server theme={null} curl --request GET \ --url 'https://api.fintoc.com/v2/events?since=2026-01-15T09:00:00Z&until=2026-01-15T11:30:00Z&limit=100' \ --header 'Authorization: YOUR_API_KEY' ``` ```json Response theme={null} [ { "id": "evt_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "event", "created_at": "2026-01-15T10:30:00.000Z", "data": { "id": "tr_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "transfer", "amount": 5000, "currency": "CLP", "status": "succeeded" }, "mode": "live", "type": "transfer.outbound.succeeded" } ] ``` Each event carries in `data` the same payload Fintoc posted to your endpoint, so your handler needs no changes to accept it. Narrow the window further when you know what you lost: * `type` filters the response to one event type, such as `transfer.outbound.succeeded`. * `resource_id` filters the response to events about one resource, such as a transfer or a payment intent. ## Page through the results `limit` returns up to 300 events per page and defaults to 30. While more events remain, the response carries a `Link` header with the URL of the next page and `rel="next"`. Follow that URL, or send `starting_after` with the `id` of the last event you received. ```bash Server theme={null} curl --request GET \ --url 'https://api.fintoc.com/v2/events?since=2026-01-15T09:00:00Z&until=2026-01-15T11:30:00Z&limit=100&starting_after=evt_0ujsswThIGTUYm2K8FjOOfXtY1K' \ --header 'Authorization: YOUR_API_KEY' ``` ```json Response theme={null} [ { "id": "evt_2b7QpLmNvR4sT8dWxYzC3fGhJ5K", "object": "event", "created_at": "2026-01-15T09:47:12.884Z", "data": { "id": "tr_9xKmPq2RtVn5WbY7cD4fH8jL3sN", "object": "transfer", "amount": 250000, "currency": "CLP", "status": "succeeded" }, "mode": "live", "type": "transfer.outbound.succeeded" } ] ``` Events come back most recent first, so each page walks further back in time. The last page arrives without a `Link` header. ## Reprocess the events Pass each event to the handler that already processes live webhooks. Reusing the handler keeps both paths in agreement about how an event updates your application. ```javascript Node theme={null} const handleEvent = require('./handleEvent'); const reprocess = async (pages) => { const events = pages.flat().reverse(); for (const event of events) { await handleEvent(event); } }; ``` ```python Python theme={null} from handle_event import handle_event def reprocess(pages): events = [event for page in pages for event in page] for event in reversed(events): handle_event(event) ``` Collect all pages before you process them, then reverse the full list. The API returns each page with the most recent event first, and pagination moves backward in time. ## Test the recovery Run the recovery in `test` mode before you depend on it: 1. Stop your webhook endpoint and [send test events](/guides/resources/webhooks-walkthrough/webhooks-testing) from the dashboard. 2. List those events with your `test` API key and the window you just created. 3. Start your endpoint again and run the recovery over the response. Your application ends in the same state as if it had received the events live. # Test your webhook endpoint Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-testing Test your webhook endpoints before registering them in `live` mode. > [!NOTE] > > **Test endpoints locally** > > Use a tool such as [`localtunnel`](https://localtunnel.me) to test endpoints during local development. Localtunnel exposes a local port to the internet and returns a public URL. Register this URL as your endpoint. ## Test your webhooks through the dashboard You can test your webhook endpoints from the [Fintoc Dashboard](https://dashboard.fintoc.com/dashboard) in three steps: 1. In the dashboard's webhooks section, register a webhook endpoint in `test` mode. 2. Select the webhook endpoint to open its detail drawer. 3. Click the send-test icon for each subscribed event to send a test webhook. The dashboard sends the test event to your webhook endpoint and displays the event details. Test events carry fake data that you cannot use to query the Fintoc API. For example, a test `account.refresh_intent.succeeded` event has the following JSON payload: ```json theme={null} { "id": "evt_1zgnKZmDC2A59vrX", "type": "account.refresh_intent.succeeded", "mode": "test", "created_at": "2021-07-07T15:15:09.802Z", "data": { "object": "refresh_intent", "refreshed_object": "account", "refreshed_object_id": "acc_00000000", "status": "succeeded", "public_error": null, "created_at": "2021-06-28T00:00:00.000Z", "type": "only_last", "new_movements": 5 }, "object": "event" } ``` The `refreshed_object_id` value, `acc_00000000`, identifies a fake account. The [get account endpoint](/api/movements-api/accounts/accounts-get) cannot return details for this account. > [!NOTE] > > **Live mode webhooks** > > You cannot test `live` mode webhooks through the dashboard. Fintoc sends `live` mode events only under specific conditions, such as when a connected account updates with its latest bank movements. # Validate webhook signatures Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/webhooks-validating Validate the Fintoc-Signature header on every webhook event using HMAC SHA-256 to confirm it came from Fintoc, with code samples for Node and Python. By the end of this guide, you can verify that every webhook event came from Fintoc by checking the `Fintoc-Signature` header. Fintoc signs every event sent to your webhook endpoints. The `Fintoc-Signature` header lets you verify that Fintoc, not a third party, sent each event. Fintoc generates a secret when you register a [webhook endpoint](/api/main-resources/webhook-endpoints/webhook-endpoints-create). You need this secret to validate the Fintoc signature of every event. ## Verify that Fintoc sent the event Each event sent by Fintoc includes the `Fintoc-Signature` header. The header contains a Unix timestamp in `t` and a signature in `v1`. For example: ```text theme={null} t=1620870928,v1=4df951e02db34a3f333bccad26d207993e9b14d78ac77cec026091991f567f6d ``` Each signature is a hash-based message authentication code. Fintoc uses SHA-256 to generate the signature from the raw request body and timestamp. The signature uses your [webhook endpoint](/api/main-resources/webhook-endpoints/webhook-endpoints-object) secret. ## Validate the signature with the Fintoc SDKs If you use Node or Python, verify webhook signatures with the [Fintoc Node SDK](https://github.com/fintoc-com/fintoc-node) or [Fintoc Python SDK](https://github.com/fintoc-com/fintoc-python). ```javascript Node theme={null} const { WebhookSignature, WebhookSignatureError } = require('fintoc'); // Use the secret returned when you created the endpoint const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; // Rest of your code here // ... // express.raw keeps req.body as the raw Buffer, which the signature covers. app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const payload = req.body; // Get the signature header const signature = req.headers['fintoc-signature']; try { // Verify the webhook signature WebhookSignature.verifyHeader( payload, signature, WEBHOOK_SECRET ); // If verification passes, process the webhook const event = JSON.parse(payload.toString()); // Rest of your code... // Acknowledge receipt of the event res.status(200).json({ received: true }); } catch (error) { if (error instanceof WebhookSignatureError) { console.error('Webhook signature verification failed'); res.status(400).json({ error: 'Invalid signature', message: error.message }); } else { res.status(500).json({ error: 'Webhook handler failed' }); } } }); ``` ```python Python theme={null} import os from fintoc.webhook import WebhookSignature from fintoc.errors import WebhookSignatureError WEBHOOK_SECRET = os.getenv('FINTOC_WEBHOOK_SECRET') # Rest of your code # ... @app.route('/webhook', methods=['POST']) def handle_webhook(): # Get the signature header signature = request.headers.get('Fintoc-Signature') # Get the raw request payload payload = request.get_data().decode('utf-8') # Verify the webhook signature try: WebhookSignature.verify_header( payload=payload, header=signature, secret=WEBHOOK_SECRET ) except WebhookSignatureError as e: print('Invalid signature!') return str(e), 400 # Acknowledge receipt of the event return '', 200 ``` For a complete implementation, see the [Python webhook example](https://github.com/fintoc-com/fintoc-python/blob/master/examples/webhook.py). ## Validate the signature with your own code If you want to write your own implementation or use a different programming language, follow these steps: ### Extract the timestamp and the signature Split the `Fintoc-Signature` header at each `,` character. Then, split each array element at the `=` character to obtain a key-value pair. Get the corresponding value for each key. ```python theme={null} # Use the Flask request. header_value = request.headers.get('Fintoc-Signature') timestamp, event_signature = [x.split('=')[1] for x in header_value.split(',')] ``` ### Rebuild the signed message The signed message consists of the timestamp, a `.` character, and the raw request body. Rebuild the message with the timestamp from the `Fintoc-Signature` header. ```python theme={null} import json # Use the Flask request. message = f"{timestamp}.{request.get_data().decode('utf-8')}" ``` Use the raw, unparsed request body. Libraries can represent parsed JSON differently. For example, `message` should look like this: ```python theme={null} '1626102791.{"id":"evt_DyzYBwdC07ao5MqG","type":"link.credentials_changed","mode":"test","created_at":"2021-07-12T15:11:09.875Z","data":{"id":"link_00000000","mode":"test","active":true,"object":"link","status":"active","accounts":null,"username":"111111111","holder_id":"111111111","created_at":"2021-06-24T00:00:00.000Z","link_token":null,"holder_type":"individual","institution":{"id":"cl_banco_bbva","name":"Banco BBVA","country":"cl"}},"object":"event"}' ``` ### Generate the signature Generate the signature with SHA-256 and the secret returned when you created the webhook endpoint. ```python theme={null} import hmac from hashlib import sha256 # The secret returned when you created the webhook endpoint YOUR_WEBHOOK_SECRET = 'YOUR_WEBHOOK_SECRET' encoded_secret = YOUR_WEBHOOK_SECRET.encode('utf-8') encoded_message = message.encode('utf-8') hmac_object = hmac.new(encoded_secret, msg=encoded_message, digestmod=sha256) signature = hmac_object.hexdigest() ``` ### Compare the signatures Compare the signature from the `Fintoc-Signature` header with the signature you generated. If both signatures match, the event came from Fintoc. ```python theme={null} import hmac valid_signature = hmac.compare_digest(signature, event_signature) ``` ## Prevent a replay attack To prevent a replay attack, define an acceptable age for events. When you receive an event, compare the timestamp from the `Fintoc-Signature` header with the current time. Use five minutes as the default tolerance. Accept events within this range, and discard events outside it. ## Test the integration Confirm that signature validation works before you rely on it in production. Trigger a test event for your webhook endpoint from the Fintoc Dashboard, then check how your handler responds: * With a valid signature, your handler validates the header and processes the event. * With an invalid signature, such as a modified `v1` value or the wrong secret, your handler rejects the event and returns `400 Bad Request`. # Widget Source: https://docs.fintoc.com/guides/resources/widget/index The Fintoc Widget lets your users securely link bank accounts in your app or website, with drop-in flows for web, mobile webviews, and native platforms. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/459dd472b3eda33de057e702587588d61db12d9687f19e4a14ba81c9c74de9bf-Screenshot_2025-07-10_at_10.02.54_AM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=3a6191a61862272bf228e791a644fee4) The Fintoc Widget lets your users connect their bank accounts to Fintoc. The Widget handles credential validation, multi-factor authentication, and errors for each financial institution Fintoc supports. You can use the Widget in web and mobile applications. To integrate the Widget, see [Web integration](/guides/resources/widget/web-integration) or [WebView integration](/guides/resources/widget/webview). > [!NOTE] > > If you use Fintoc to receive payments, see the [Widget guide for API version `2023-11-15`](/v2023-11-15/guides/resources/widget/index) for integration instructions. # Integrate the Widget on the web Source: https://docs.fintoc.com/guides/resources/widget/web-integration Integrate the Fintoc Widget into your web app or website so customers can link their bank account or complete a payment without leaving your site. Embed the Fintoc Widget in a web application with an HTML script tag or an ES module. This page also covers Widget methods, configuration parameters, and callbacks. ## Plain HTML integration To integrate the Widget, include the Fintoc script in your HTML page. Include the script on each page where you use the Widget. ```html Client theme={null} ``` > [!NOTE] > > **window\.onload** > > The browser raises an error if you call a Fintoc function before the `script` loads. Use the native `window.onload` event to wait for the script. ## ES module integration You can also use the `@fintoc/fintoc-js` library as an ES module through `npm`. ```bash Client theme={null} npm install @fintoc/fintoc-js ``` The library exports the asynchronous `getFintoc` function. This function returns the `Fintoc` object. ```javascript Client theme={null} import { getFintoc } from '@fintoc/fintoc-js'; // See the parameter table below for the full list of options const options = { product: 'payments', publicKey: 'YOUR_PUBLIC_KEY', sessionToken: 'YOUR_SESSION_TOKEN', }; const main = async () => { const Fintoc = await getFintoc(); const widget = Fintoc.create(options); widget.open(); }; main(); ``` ## Methods of the Widget object After you create a Widget instance, use its `open`, `hide`, and `destroy` methods to control the instance: | Method | Description | | :- | :- | | `widget.open()` | Opens the Widget. | | `widget.hide()` | Closes the Widget without destroying the Widget instance. The Widget remains hidden until you call `widget.open()` again. | | `widget.destroy()` | Removes the Widget instance from your application. To reopen the Widget, create another Widget instance with `Fintoc.create()`. | > [!NOTE] > > **How to use the `widget.destroy()` method** > > Calling `Fintoc.create(args)` embeds an `iframe` in your application. In a single-page application, you may need to remove the `iframe`. Call `widget.destroy()` to remove the `iframe`. To reopen the Widget, create a new instance with `Fintoc.create(args)`. ## Configure the Widget Each product requires different Widget configuration parameters. Loading the Fintoc `script` gives your application access to the `Fintoc` object. The `getFintoc` function from `@fintoc/fintoc-js` returns the same object. Use `Fintoc.create()` to create a Widget instance for your product. > [!NOTE] > > **Open the Widget** > > Call `widget.open()` to open the Widget. ### Payment initiation ```javascript Client theme={null} const widget = Fintoc.create({ product, publicKey, sessionToken, onSuccess, onExit, onEvent, }); ``` ### Movements ```javascript Client theme={null} const widget = Fintoc.create({ publicKey, widgetToken, onSuccess, onExit, onEvent, }); ``` Create a [Link Intent](/api/movements-api/linkintents/link-intents-create) from your backend and pass the Link Intent's `widget_token` as `widgetToken`. Use the same flow to reconnect an existing `Link`. You don't need to send the existing `link_token` to the Widget. See [Reconnect a Link](/guides/movements/guides/guides-reconnect-link). ### Direct debit ```javascript Client theme={null} const widget = Fintoc.create({ holderType, product, publicKey, country, institutionId, widgetToken, onSuccess, onExit, onEvent, }); ``` Configure the Widget with these parameters: | Parameter | Type | Description | | - | - | - | | `publicKey` | `string` | Identifier for your web application or web page within Fintoc. Fintoc assigns each `Link` created with the key to the key's owner. Sandbox keys start with `pk_test_`, and production keys start with `pk_live_`. | | `holderType` | `string` | Type of account to connect to Fintoc. One of `business` or `individual`. Not required for Payment Initiation. | | `product` | `string` | Product and type of `Link` to create. One of `movements`, `subscriptions`, `invoices`, or `payments`. | | `country` | `string` | Two-letter ISO 3166-1 alpha-2 country code. One of `cl` (Chile) or `mx` (Mexico). Defaults to `cl`. Not required for Payment Initiation. | | `appearance` | `object` | Widget color scheme. Contains a `theme` field set to `light` or `dark`. Defaults to `light`. For example, `appearance: { theme: 'dark' }`. | | `institutionId` | `string` | Identifier of [a financial institution](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). If included, Fintoc preselects that institution. For example, `cl_banco_estado` opens the Widget with Banco Estado selected. Confirm availability with the [list institutions endpoint](/api/main-resources/institutions/institutions-list) before preselecting an institution. | | `username` | `string` or `object` | Value that pre-fills the `username` field when making a payment. See the [`username` object attributes](#username-and-holderid-objects). A string sets `editable` to its default value of `true`. | | `holderId` | `string` or `object` | Value that pre-fills `holderId` when connecting a `Link` for `movements`. See the [`holderId` object attributes](#username-and-holderid-objects). A string sets `editable` to its default value of `true`. Only `movements` uses this parameter. | | `sessionToken` | `string` | Token your backend creates with a [Checkout Session](/api/payments-api/checkout-sessions/checkout-sessions-create). The Widget uses `sessionToken` to load and configure the payment flow. Only `payments` uses this parameter. | | `webhookUrl` | `string` | URL that receives a request after Fintoc creates a `Link`. The request includes the `Link` object's `link_token`. Only `movements` and `invoices` use this parameter. | | `widgetToken` | `string` | Token your backend creates to initialize and configure the Widget. For `movements`, use the `widget_token` of a [Link Intent](/api/movements-api/linkintents/link-intents-create). For `subscriptions`, use the `widget_token` your backend creates for the subscription. | | `onSuccess` | `function` | Callback Fintoc calls after the flow finishes successfully. | | `onExit` | `function` | Callback Fintoc calls after your customer closes the Widget before completing the flow. | | `onEvent` | `function` | Callback Fintoc calls each time your customer takes a tracked action in the Widget. | > [!CAUTION] > > **Use the Widget callbacks and events correctly** > > Never use the `onSuccess`, `onExit`, or `onEvent` callbacks to read the state of the resource being created. Use these callbacks only to drive your frontend flow while you wait for backend confirmation. Confirm the resource through webhooks or by exchanging a confirmation token. You can also use frontend events to generate Widget usage metrics. Never rely on frontend events alone to determine whether resource creation succeeded or failed. > [!NOTE] > > **Dark mode for the Widget appearance** > > Send `appearance` to set the Widget color scheme to `light` or `dark`. ## `username` and `holderId` objects To pre-fill `username` or `holderId` and override the defaults, send an object with these attributes: ```javascript Client theme={null} const username = { value: '11.111.111-1', editable: true, }; const holderId = { value: '11.111.111-1', editable: true, }; ``` > [!NOTE] > > **Pre-filling increases payment conversion** > > In Fintoc's internal testing, pre-filling the username raised payment conversion by 3%. The `username` and `holderId` objects support these attributes: | Attribute | Type | Description | | - | - | - | | `value` | `string` | Value to pre-fill in the Widget. For `payments`, enter the Chilean tax ID (RUT) in Chile or the phone number in Mexico. For `movements`, enter the business RUT for the account you connect. | | `editable` | `boolean` | Whether the field is editable in the Widget. Defaults to `true`. | # Integrate the Widget as a WebView Source: https://docs.fintoc.com/guides/resources/widget/webview Embed the Fintoc Widget in your iOS or Android app with a native WebView configured through URL query parameters, handle WebView redirections, and test it. Embed the Fintoc Widget inside your iOS or Android app with a native WebView, configured through URL query parameters. ## Integration To integrate the Widget as a WebView on iOS and Android, load the following URL: ```text theme={null} https://webview.fintoc.com/widget.html ``` Pass the Widget configuration in the query string instead of in client-side JavaScript. > [!NOTE] > > **Using React Native?** > > To integrate the WebView in a React Native app, use the [`@fintoc/fintoc-react-native`](https://github.com/fintoc-com/fintoc-react-native) library. ## How it works Configure the Fintoc WebView with query parameters for the product you want to use: ```text theme={null} https://webview.fintoc.com/widget.html ?public_key=YOUR_PUBLIC_KEY &holder_type=individual &product=payments &country=cl &session_token=YOUR_SESSION_TOKEN ``` | Parameter | Type | Description | | - | - | - | | `public_key` | `string` | Identifier for your application within Fintoc. Fintoc assigns each `Link` created with the key to the organization or user that owns the key. The key also determines the environment. Sandbox keys start with `pk_test_`, and production keys start with `pk_live_`. | | `holder_type` | `string` | Type of account to connect to Fintoc. One of `business` or `individual`. Not required when `product` is `payments` (Payment Initiation). | | `product` | `string` | Product and type of `Link` to create. One of `movements`, `subscriptions`, `invoices`, or `payments`. | | `country` | `string` | Lowercase ISO 3166-1 alpha-2 code of the country to connect to. One of `cl` or `mx`. Defaults to `cl`. Not required when `product` is `payments` (Payment Initiation). | | `webhook_url` | `string` | URL that receives a request after Fintoc creates a `Link`. The request includes the `Link` object's `link_token`. Only the `movements` and `invoices` products use this parameter. | | `session_token` | `string` | Token your backend creates with a [Checkout Session](/api/payments-api/checkout-sessions/checkout-sessions-create). The Widget uses `session_token` to load and configure the payment flow. Only the `payments` product uses this parameter. | | `widget_token` | `string` | Token your backend creates to initialize and configure the Widget. For the `movements` product, use the `widget_token` of a [Link Intent](/api/movements-api/linkintents/link-intents-create). For the `subscriptions` product, use the `widget_token` your backend creates for the subscription. | To connect or reconnect a `Link` for the `movements` product, create a Link Intent from your backend and pass the Link Intent's `widget_token`. You don't need to send the existing `link_token` to the WebView. See [Reconnect a Link](/guides/movements/guides/guides-reconnect-link). You can construct the query string separately before appending it to the WebView URL: ```text theme={null} public_key=YOUR_PUBLIC_KEY&holder_type=individual&product=movements&country=cl&widget_token=YOUR_WIDGET_TOKEN ``` ## Usage example The following snippets show the WebView set up on Android and iOS: ```kotlin theme={null} override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) supportActionBar?.hide() val widgetInitializationUrl = generateWidgetInitializationUrl() // Modify WebView settings. Some settings may not be applicable // or necessary for your integration. val fintocWebview = findViewById(R.id.webview) val webSettings = fintocWebview.settings webSettings.javaScriptEnabled = true webSettings.javaScriptCanOpenWindowsAutomatically = true webSettings.domStorageEnabled = true webSettings.cacheMode = WebSettings.LOAD_NO_CACHE webSettings.useWideViewPort = true fintocWebview.loadUrl(widgetInitializationUrl.toString()) } private fun generateWidgetInitializationUrl(): Uri { val builder = Uri.parse("https://webview.fintoc.com/widget.html") .buildUpon() .appendQueryParameter("holder_type", "individual") .appendQueryParameter("product", "payments") .appendQueryParameter("public_key", "YOUR_PUBLIC_KEY") .appendQueryParameter("session_token", "YOUR_SESSION_TOKEN") return builder.build() } ``` ```swift theme={null} import UIKit import WebKit class ViewController: UIViewController, WKNavigationDelegate, UIScrollViewDelegate, WKUIDelegate { private var webView: WKWebView! override func loadView() { let webConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self view = webView } override func viewDidLoad() { super.viewDidLoad() webView.navigationDelegate = self webView.allowsBackForwardNavigationGestures = false webView.scrollView.bounces = false webView.isMultipleTouchEnabled = false webView.configuration.preferences.javaScriptCanOpenWindowsAutomatically = true // Disable zoom. webView.scrollView.delegate = self webView.scrollView.minimumZoomScale = 1.0 webView.scrollView.maximumZoomScale = 1.0 let url = generateInitializationURL() webView.load(URLRequest(url: url)) } override var prefersStatusBarHidden: Bool { return true } @objc(scrollViewWillBeginZooming:withView:) func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { scrollView.pinchGestureRecognizer?.isEnabled = false } func webView( _ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures ) -> WKWebView? { guard navigationAction.targetFrame == nil, let url = navigationAction.request.url else { return nil } UIApplication.shared.open(url) return nil } func generateInitializationURL() -> URL { let params = [ "holder_type": "individual", "product": "payments", "public_key": "YOUR_PUBLIC_KEY", "session_token": "YOUR_SESSION_TOKEN", ] var components = URLComponents() components.scheme = "https" components.host = "webview.fintoc.com" components.path = "/widget.html" let queryItems = params.map { URLQueryItem(name: $0, value: $1) } components.queryItems = queryItems return components.url! } func webView( _ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping ((WKNavigationActionPolicy) -> Void) ) { guard let url = navigationAction.request.url else { decisionHandler(.allow) return } let linkScheme = "fintocwidget" let actionScheme = url.scheme let actionType = url.host ?? "" if actionScheme == linkScheme { switch actionType { case "succeeded": print("Succeeded") case "exit": print("Exited") case "event": print("Widget event detected: \(url)") default: print("Another widget action detected: \(actionType)") } decisionHandler(.cancel) return } else { decisionHandler(.allow) } } } ``` The Swift example includes a `webView` method that handles link clicks inside the WebView. In the example, links open in Safari, but you can customize this behavior. For example, links can open inside the same app. This matters because customers using [Payment Initiation](/guides/payments/overview-payment-initiation) can click a link to download the transaction voucher after they finish the payment flow. Allow these links to open so the customer can download the voucher. ## WebView redirections After you integrate the WebView, you can interact with its events using redirects: | Method | Redirect URL | Description | | :- | :- | :- | | `onSuccess` | `fintocwidget://succeeded` | Fires after the flow finishes successfully. | | `onExit` | `fintocwidget://exit` | Fires after your customer closes the Widget before finishing. | | `onEvent` | `fintocwidget://event/{event_name}?queryparam={value}` | Fires for every event available on the Widget. For more information about these events, see [Widget events](/guides/resources/widget/widget-events). | > [!WARNING] > > **Handle `onEvent` in a WebView** > > The WebView enables `onEvent` by default. Handle the `fintocwidget://event/{event_name}` redirect so your app receives Widget events. To use these methods on Android and iOS, use the following snippets: ```kotlin theme={null} webview.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { val parsedUri = url?.let(Uri::parse) ?: return false if (parsedUri.scheme == "fintocwidget") { val action = parsedUri.host if (action == "succeeded") { // onSuccess } if (action == "exit") { // onExit } if (action == "event") { // onEvent } return true } return false } } ``` ```java theme={null} webview.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { Uri parsedUri = Uri.parse(url); if ("fintocwidget".equals(parsedUri.getScheme())) { String action = parsedUri.getHost(); if ("succeeded".equals(action)) { // onSuccess } if ("exit".equals(action)) { // onExit } if ("event".equals(action)) { // onEvent } return true; } return false; } }); ``` ```swift theme={null} func webView( _ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping ((WKNavigationActionPolicy) -> Void) ) { guard let url = navigationAction.request.url else { decisionHandler(.allow) return } let linkScheme = "fintocwidget" let actionScheme = url.scheme let actionType = url.host ?? "" if actionScheme == linkScheme { switch actionType { case "succeeded": // onSuccess break case "exit": // onExit break case "event": // onEvent break default: print("Widget action detected: \(actionType)") } decisionHandler(.cancel) return } else { decisionHandler(.allow) } } ``` > [!WARNING] > > **Add the `fintocwidget` URL scheme on iOS** > > Before integrating the Fintoc Widget with your iOS app, register `fintocwidget` as a URL scheme in the app's `Info.plist` file. This configuration allows your app to handle Widget redirects. ```xml theme={null} CFBundleURLTypes CFBundleURLSchemes fintocwidget CFBundleURLName your.bundle.id ``` ## Test the integration Load the WebView with a `pk_test_` public key to run against the sandbox environment. Complete the flow with Fintoc's [test credentials](/guides/resources/test-mode), then confirm your app receives the `fintocwidget://succeeded` redirect. # Listen to Widget events Source: https://docs.fintoc.com/guides/resources/widget/widget-events This page lists the Widget events and metadata available through `onEvent`. The Widget calls `onEvent` for each event. Define the callback as follows: ```javascript onEvent definition example theme={null} function onEvent(eventName, metadata) { // use eventName and metadata } ``` `eventName` identifies the event that triggered the callback. `metadata` contains information about the emitted event. Check each `metadata` attribute for `null` before using it. The following `metadata` attribute is documented: | Attribute | Description | | :- | :- | | `timestamp` | Unix timestamp in milliseconds indicating when the Widget emitted the event. | > [!WARNING] > > The `metadata` object can include undocumented fields. Ignore fields that your integration does not recognize. ## List of events The Widget emits the following events, including events for Cobro Digital (CoDi) payments: | Event name | Description | | :- | :- | | `opened` | The Widget emits this event when your user opens the Widget. | | `on_terms_and_conditions` | The Widget emits this event when your user visits the terms and conditions. | | `codi_helper` | The Widget emits this event when your user visits the CoDi Helper Guide. | | `on_available_institutions` | The Widget emits this event when your user opens the financial institution selection view. | | `on_request_bank` | The Widget emits this event when your user opens the view to request a new bank. | | `on_authentication_form` | The Widget emits this event when your user opens the financial institution authentication view. | | `codi_username_required` | The Widget emits this event when your user must enter their mobile phone number to receive a CoDi payment request. | | `payment_in_progress` | The Widget emits this event when your user must select the payment provider. | | `creating_link` | The Widget emits this event when the financial institution verifies the credentials and Fintoc connects the account. | | `link_created` | The Widget emits this event when the financial institution approves the credentials and Fintoc creates a `Link`. | | `selecting_account` | The Widget emits this event when your user opens the view to select an account. | | `payment_intent_confirmation_required` | The Widget emits this event when your user must authorize the payment. | | `app_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor through an app. | | `creating_subscription` | The Widget emits this event when your user starts creating a subscription. | | `payment_direct_transfer` | The Widget emits this event when your user views the direct transfer screen. | | `device_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor through a physical device. | | `card_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor through a coordinate card. | | `sms_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor by text message. | | `email_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor by email. | | `captcha_authentication_required` | The Widget emits this event when the financial institution requires a second authentication factor through a captcha. | | `validating_second_factor` | The Widget emits this event when the financial institution validates the second authentication factor your user entered. | | `subscription_created` | The Widget emits this event when Fintoc creates a subscription. | | `subscription_aborted` | The Widget emits this event when a constraint prevents Fintoc from completing the subscription. For example, your user may have already completed the same subscription. | | `payment_created` | The Widget emits this event when a payment succeeds. | | `payment_error` | The Widget emits this event when a payment fails. | | `payment_selecting_auth` | The Widget emits this event when your user selects a method for second-factor authentication. | | `validating_payment` | The Widget emits this event when Fintoc validates the payment. | | `closed` | The Widget emits this event when your user closes the Widget. | | `on_error` | The Widget emits this event when an error occurs in the Widget flow. | # Chile institution codes Source: https://docs.fintoc.com/api/fintoc-api/chile-institution-codes Fintoc institution IDs for Chilean banks and wallets, like `cl_banco_bci` and `cl_banco_santander`, to use when you specify a Chilean institution. Use these Fintoc institution IDs when you specify a Chilean institution: | Institution name | Fintoc institution ID | | :- | :- | | Banco BCI | `cl_banco_bci` | | Banco BICE | `cl_banco_bice` | | Banco BTG Pactual | `cl_banco_btg_pactual` | | Banco Consorcio | `cl_banco_consorcio` | | Banco de Chile - Edwards - Citi | `cl_banco_de_chile` | | Banco Estado | `cl_banco_estado` | | Banco Falabella | `cl_banco_falabella` | | Banco Internacional | `cl_banco_internacional` | | Banco Itaú | `cl_banco_itau` | | Banco Ripley | `cl_banco_ripley` | | Banco Santander | `cl_banco_santander` | | Banco Security | `cl_banco_security` | | BBVA | `cl_banco_bbva` | | Coopeuch - Dale | `cl_banco_coopeuch` | | Copec Pay | `cl_copec_pay` | | Fintoc | `cl_fintoc` | | HSBC | `cl_banco_hsbc` | | Mach | `cl_mach` | | Mercado Pago | `cl_mercado_pago` | | Prepago Los Heroes | `cl_prepago_los_heroes` | | Scotiabank | `cl_banco_scotiabank` | | Tapp | `cl_tapp_caja_los_andes` | | Tenpo Bank | `cl_tenpo_bank` | | Tenpo Prepago | `cl_tenpo` | # Error object Source: https://docs.fintoc.com/api/fintoc-api/errors/errors-object ## The Error object An `Error` represents a failed API request, describing what went wrong. It appears in the response body, nested under the `error` key, whenever a request does not succeed. ```json Error Object theme={null} { "error": { "code": "missing_parameter", "doc_url": "https://fintoc.com/docs#invalid-request-error", "message": "Missing required param: link_token", "param": "link_token", "type": "invalid_request_error" } } ``` | Attribute | Type | Description | | :- | :- | :- | | `code` | `string` | The particular error that occurred. The API error codes follow the [standard HTTP error conventions for status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status#client_error_responses). | | `doc_url` | `string` | The URL of the documentation associated with the error code. | | `message` | `string` | Friendly message detailing the error. This field can change its text content for the same `code` value in time, so it shouldn't be used programmatically. | | `param` | `string` | If the error is related to a parameter, this attribute indicates that parameter. It can be `null`. | | `type` | `string` | The type of the error. It may be `api_error`, `authentication_error`, `link_error`, `institution_error`, `invalid_request_error`, `new_contact_error` or `amount_error`. The last two are only if you [pre-validate payments](/guides/payments/direct-payments/check-payment-eligibility-direct-payments). | # Idempotent requests Source: https://docs.fintoc.com/api/fintoc-api/idempotent-requests How to safely retry POST requests to the Fintoc API using the Idempotency-Key header to avoid creating duplicate charges, payment intents, or transfers. The Fintoc API supports idempotent requests. You can retry an idempotent request without performing the same operation twice. Use idempotency for resource creation requests that you might retry after a network error. Examples include [charges](/api/direct-debit-legacy/charges/charge-object), [payment intents](/api/payments-api/payment-intents/payment-intents-object), and [transfers](/api/business-accounts-api/transfers/transfers-create). If a connection error occurs after you submit an idempotent request, you can retry the request without creating a second object. To make an idempotent request, include the `Idempotency-Key: ` header. An idempotency key is a unique value that your client generates. Fintoc uses this key to recognize retries of the same request. Use UUID version 4 values or random strings with enough entropy to avoid collisions. Idempotency keys can contain up to 255 characters. Fintoc saves the status code and response body from the first request for each idempotency key, whether the request succeeds or fails. Subsequent requests with the same key return the saved result, including `4xx` and `5xx` errors. Replayed responses include the `Idempotent-Replayed: true` header. > [!NOTE] > > **Authentication needed** > > Fintoc does not save an idempotent result when authentication fails because the request does not reach the API endpoint. For each retry, the idempotency layer compares the request parameters with the original request parameters. If the parameters differ, Fintoc returns a `400 Bad Request` error with the code `invalid_idempotent_request`. If you send a request while an earlier request with the same key is still in progress, Fintoc does not process it a second time. Fintoc waits up to about 1 second for the first result and returns it. If the first request has not finished by then, Fintoc returns a `503 Service Unavailable` error with the code `idempotency_unavailable`. Fintoc does not save this `503` response. Retry later with the same key to get the result of the first request. ## Retry a transfer safely A `5xx` response or a timeout can still mean Fintoc created the transfer. Because Fintoc replays a saved `5xx` response, retrying with the same key returns the same error and does not tell you whether the transfer exists. To avoid sending a payment twice: 1. Store your own identifier for each payment in the transfer's `metadata`, and send one `Idempotency-Key` per payment. 2. If the request times out or the connection drops before you get a response, retry with the same key. You get either the saved result or the result of a new attempt. 3. If you get a `5xx` response, [list transfers](/api/business-accounts-api/transfers/transfers-list) with `account_id`, `direction=outbound`, and `since` set to just before your request. Look for a transfer with your `metadata` identifier. 4. If you find the transfer, track it through its status and webhooks. If you don't, create the transfer with a new `Idempotency-Key`. Fintoc can remove idempotency keys automatically once they are at least 24 hours old. If you reuse a key after Fintoc removes the original result, the API processes the request as new. All `POST` requests accept idempotency keys. Sending idempotency keys in `GET` and `DELETE` requests has no effect because `GET` and `DELETE` requests are idempotent by definition. The following examples create a charge with an idempotency key. You can retry the request without creating a duplicate charge. ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/charges" \ --header 'Authorization: sk_test_0000000000000000' \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: 31a0dd22-38e4-4392-81e1-aa3a2018b48d' \ --data-raw '{ "subscription_id": "sub_000000", "amount": 1000, "currency": "clp", "metadata": { "customer": "123456" } }' ``` ```javascript theme={null} // First install our Node SDK (https://github.com/fintoc-com/fintoc-node) // $ npm install fintoc const { Fintoc } = require('fintoc'); const fintoc = Fintoc('your_api_key') await fintoc.charges.create({ idempotency_key: '31a0dd22-38e4-4392-81e1-aa3a2018b48d', subscription_id: 'sub_000000', amount: 1000, currency: 'clp', metadata: { customer: '123456' }, }); ``` ```python theme={null} # First install our Python SDK (https://github.com/fintoc-com/fintoc-python) # $ pip install fintoc from fintoc import Fintoc client = Fintoc("your_api_key") client.charges.create( idempotency_key="31a0dd22-38e4-4392-81e1-aa3a2018b48d", subscription_id="sub_000000", amount=1000, currency="clp", metadata={"customer": "123456"}, ) ``` # Metadata Source: https://docs.fintoc.com/api/fintoc-api/metadata Attach `metadata` key-value pairs to Fintoc objects like `Charge`, `CheckoutSession`, `PaymentIntent`, `Transfer`, and `AccountNumber`, with limits. Some Fintoc objects support the `metadata` parameter. These objects currently include [Charges](/api/direct-debit-legacy/charges/charge-object), [Checkout Sessions](/api/payments-api/checkout-sessions/checkout-session-object), [Payment Links](/api/payments-api/payment-links/payment-link-object), [Payment Intents](/api/payments-api/payment-intents/payment-intents-object), [Transfers](/api/business-accounts-api/transfers/transfer-object), and [Account Numbers](/api/business-accounts-api/account-numbers/account-number-object). Use `metadata` to store arbitrary structured data about the Fintoc objects you interact with. This data can help you map Fintoc objects to records in your system. For example, you can store a customer's full name and the corresponding identifier from your system on a Fintoc payment intent. Fintoc does not use or modify `metadata`. > [!NOTE] > > **Limitations** > > `metadata` supports up to 50 keys. Key names can contain up to 40 characters, and values can contain up to 500 characters. Each value must be a `string`, `boolean`, or `number`. # Pagination Source: https://docs.fintoc.com/api/fintoc-api/pagination How pagination works in the Fintoc API, including Link header format, offset pagination for v1 endpoints, and cursor pagination for v2 endpoints. By default, Fintoc returns 30 elements per paginated response, such as responses from [List movements](/api/movements-api/movements/movements-list). The API includes pagination details in the [`Link` header](https://tools.ietf.org/html/rfc5988), following the [RFC 8288 standard](https://tools.ietf.org/html/rfc8288). The `Link` header is unrelated to Fintoc `Link` objects. For each paginated request, the API returns the pagination information using the `Link` header. This header contains one or more URLs that direct to different pages. ## Pagination v1 Use `per_page` to set the number of results per page and `page` to request a specific page. For [List movements](/api/movements-api/movements/movements-list), `per_page` defaults to `30`, and the maximum is `300`. To retrieve more than `300` movements, request the remaining pages with `page`. Endpoints in the `/v1` namespace, such as [List links](/api/movements-api/links/links-list), use offset pagination. The `Link` header in this namespace lets you navigate to the next, previous, first, and last page: ```text Link Header theme={null} Link: ; rel="first", ; rel="next" ``` The possible `rel` values are: | Name | Description | | :- | :- | | `next` | Link that leads to the **next page** of the resource | | `last` | Link that leads to the **last page** of the resource | | `first` | Link that leads to the **first page** of the resource | | `prev` | Link that leads to the **previous page** of the resource | ## Pagination v2 Endpoints in the `/v2` namespace, such as [List Transfers](/api/business-accounts-api/transfers/transfers-list), use cursor-based pagination. In this namespace, the `Link` header only allows navigation to the next page in the list: ```text Link Header theme={null} Link: ; rel="next" ``` The possible `rel` values are: | Name | Description | | :- | :- | | `next` | Link that leads to the **next page** of the resource | If `Link` is empty, it means there are no more pages. ## Automatic pagination The [Node SDK](https://github.com/fintoc-com/fintoc-node) and [Python SDK](https://github.com/fintoc-com/fintoc-python) support automatic pagination. This feature allows you to iterate through large lists of resources without having to manually perform the requests to fetch subsequent pages: ```javascript Node theme={null} import { Fintoc } from 'fintoc'; const client = new Fintoc('your_api_key'); const paymentIntents = await client.paymentIntents.list(); for await (const paymentIntent of paymentIntents) { // Do something with the paymentIntent } ``` ```python Python theme={null} from fintoc import Fintoc client = Fintoc("your_api_key") payment_intents = client.payment_intents.all() for payment_intent in payment_intents: print(payment_intent) # Do something with the payment intent ``` ## Other libraries If you use other languages or don't want to use our SDK, the following libraries parse the `Link` header so that you don't have to: | Language | Library | | :- | :- | | Python | [`requests`](https://requests.readthedocs.io/en/v3.0.0/user/advanced/#link-headers) | | Ruby | [`Nitlink`](https://github.com/alexpeattie/nitlink) | | JavaScript | [`parse-link-header`](https://github.com/thlorenz/parse-link-header) | # Get an event Source: https://docs.fintoc.com/api/main-resources/events-reference/events-get reference/main-api.json GET /v2/events/{id} Returns a single event by its ID. The event's `data` is the same payload Fintoc sends to your webhook endpoints. Events are scoped to the mode of the API key you authenticate with, so an event from the other mode returns a `404 Not Found` error. # List events Source: https://docs.fintoc.com/api/main-resources/events-reference/events-list reference/main-api.json GET /v2/events Lists events for your organization in the mode of the API key you use, most recent first. Each event's `data` contains the same payload Fintoc sends to your webhook endpoints. Use this endpoint to reprocess events your integration missed without waiting for a redelivery. # Types of events Source: https://docs.fintoc.com/api/main-resources/events-reference/types-of-events Find each webhook event type, its product, and the resource included in its payload. Fintoc sends a webhook event whenever a resource in your account changes. Event names follow the pattern `resource.event`, and the event's `data` field carries the affected resource. For the envelope that wraps every event, see the [Event object](/api/main-resources/events-reference/events-object). To build an endpoint that receives events, follow the [webhooks guide](/guides/resources/webhooks-walkthrough), which covers [signature verification](/guides/resources/webhooks-walkthrough/webhooks-validating) and the [retry schedule](/guides/resources/webhooks-walkthrough/webhooks-creating-guide). > [!WARNING] > > You cannot subscribe to the `link.created` event with a webhook endpoint. To receive the event, pass your backend URL when you [configure the widget](/guides/resources/widget/web-integration). Use the Product column to choose events for the product you are integrating. Some events apply to more than one product. > [!NOTE] > > For Business Accounts transfers, subscribe to `transfer.inbound.*` or `transfer.outbound.*`. The `checkout_session.*`, `payment_intent.*`, and `payout.*` events belong to Payments. A `Payout` settles funds collected through Payments to your bank account; it does not represent an outbound Business Accounts transfer. Fintoc sends the following event types today and adds new ones over time, so ignore any type your integration does not recognize: | Event type | Product | `data.object` | Description | | - | - | - | - | | `account.refresh_intent.succeeded` | Movements | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when Fintoc updates an `Account` with the latest movements available from the bank. | | `account.refresh_intent.failed` | Movements | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when Fintoc cannot update the movements of an `Account`. Available only on Refresh On Demand plans. | | `account.refresh_intent.rejected` | Movements | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when Fintoc cannot update the movements of an `Account` because the `Link` credentials are invalid. Available only on Refresh On Demand plans. | | `account.refresh_intent.movements_removed` | Movements | No `object` field | Triggers when the bank behind a `Link` deletes movements, carrying `account_id` and `movements_removed` with the ids of the deleted movements. Activate these notifications from your [dashboard](https://dashboard.fintoc.com/webhook-endpoints). | | `account.refresh_intent.movements_modified` | Movements | No `object` field | Triggers when the bank behind a `Link` modifies movements, carrying `account_id` and `movements_changed` with the full [`movement`](/api/movements-api/movements/movements-object) objects that changed. Activate these notifications from your [dashboard](https://dashboard.fintoc.com/webhook-endpoints). | | `account_number.deleted` | Business Accounts | [`account_number`](/api/business-accounts-api/account-numbers/account-number-object) | 🇲🇽 Triggers when an account number is deleted, either at your request or because Fintoc purged it as stale. | | `account_verification.succeeded` | Business Accounts | [`account_verification`](/api/business-accounts-api/account-verification/account-verification-object) | Triggers when Fintoc retrieves the holder information of the target account. | | `account_verification.failed` | Business Accounts | [`account_verification`](/api/business-accounts-api/account-verification/account-verification-object) | Triggers when Fintoc cannot retrieve the holder information of the target account. | | `charge.succeeded` | Direct Debit (Legacy) | [`charge`](/api/direct-debit-legacy/charges/charge-object) | Triggers when the bank confirms a `Charge` succeeded. | | `charge.failed` | Direct Debit (Legacy) | [`charge`](/api/direct-debit-legacy/charges/charge-object) | Triggers when a `Charge` fails, for example because of insufficient funds, an amount above the allowed limit, or a disabled authorization. | | `checkout_session.finished` | Payments | [`checkout_session`](/api/payments-api/checkout-sessions/checkout-session-object) | Triggers when a customer completes the payment flow. The payload carries the `CheckoutSession`, including the final status of the payment. | | `checkout_session.expired` | Payments | [`checkout_session`](/api/payments-api/checkout-sessions/checkout-session-object) | Triggers when a customer leaves the payment flow before finishing. | | `dispute.waiting_documentation` | Payments | [`dispute`](/api/payments-api/disputes/dispute-object) | Triggers when your customer contests a card payment with their issuer. Submit your evidence before `documentation_upload_deadline`, or you lose the dispute by default. | | `dispute.in_review` | Payments | [`dispute`](/api/payments-api/disputes/dispute-object) | Triggers when you submit the dispute for review and the issuer starts evaluating your evidence. | | `dispute.won` | Payments | [`dispute`](/api/payments-api/disputes/dispute-object) | Triggers when the issuer resolves the dispute in your favor and the funds stay with you. | | `dispute.lost` | Payments | [`dispute`](/api/payments-api/disputes/dispute-object) | Triggers when the issuer resolves the dispute in your customer's favor and the funds return to them. | | `dispute.expired` | Payments | [`dispute`](/api/payments-api/disputes/dispute-object) | Triggers when `documentation_upload_deadline` passes with no evidence submitted. You lose the dispute. | | `entity.onboarding.approved` | Business Accounts, Payments | [`onboarding`](#entity-onboarding-payload) | Triggers when an [`Entity`](/api/business-accounts-api/entities/entity-object) passes Know Your Customer review. An approved `account_holder` onboarding creates the `Entity`'s main `Account`; an approved `settlement_recipient` onboarding lets the `Entity` receive split payments. | | `entity.onboarding.rejected` | Business Accounts, Payments | [`onboarding`](#entity-onboarding-payload) | Triggers when an [`Entity`](/api/business-accounts-api/entities/entity-object) fails Know Your Customer review. What you can do next depends on the onboarding `type`. See [Retry after a rejection](#retry-after-a-rejection). | | `invoice.created` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when Fintoc creates an invoice. | | `invoice.finalized` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when Fintoc finalizes an invoice and the invoice becomes ready to pay. | | `invoice.finalization_failed` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when Fintoc can't finalize an invoice because its `split` doesn't add up to its `total`. The invoice stays in `draft` with `status` `inconsistent`. See [Split mismatches at finalization](/guides/payments/accept-recurring-payments/split-on-recurring-payments#split-mismatches-at-finalization). | | `invoice.paid` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers on every transition to `paid`, whether Fintoc collected the invoice or you marked it as paid outside Fintoc. | | `invoice.marked_uncollectible` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an `open` invoice moves to `uncollectible`, for example when you [mark it as uncollectible](/api/payments-api/invoices/invoices-mark-uncollectible). | | `invoice.payment_created` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when a payment for an invoice starts, either from an automatic charge or from your customer using the `hosted_invoice_url`. | | `invoice.payment_succeeded` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice payment attempt succeeds. | | `invoice.payment_failed` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice payment attempt fails. | | `invoice.upcoming` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers before a subscription's next billing cycle, as a preview of the invoice Fintoc is about to create. See [Upcoming invoice previews](#upcoming-invoice-previews). | | `invoice.voided` | Payments | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice becomes void and Fintoc disables its `hosted_invoice_url`. | | `link.created` | Movements, Fiscal | [`link`](/api/movements-api/links/link-object) | Triggers when Fintoc creates a `Link`. | | `link.credentials_changed` | Movements, Fiscal | [`link`](/api/movements-api/links/link-object) | Triggers when the credentials of a `Link` change and you need to reconnect the `Link`. | | `link.refresh_intent.succeeded` | Fiscal | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when Fintoc finishes updating electronic tax documents or tax statements for a fiscal `Link`. | | `link.refresh_intent.failed` | Fiscal | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when Fintoc cannot finish updating electronic tax documents for a fiscal `Link`. | | `payment_intent.succeeded` | Payments | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a `PaymentIntent` finishes successfully. | | `payment_intent.rejected` | Payments | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a customer rejects a `PaymentIntent`. | | `payment_intent.expired` | Payments | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a customer does not complete a `PaymentIntent`. | | `payment_intent.failed` | Payments | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a `PaymentIntent` fails. | | `payment_intent.pending` | Payments | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when the final status of a `PaymentIntent` is not available yet. Fintoc sends a second webhook once that status resolves. | | `payment_method.activated` | Payments | [`payment_method`](/api/payments-api/payment-methods/payment-method-object) | Triggers when the bank confirms the mandate and the payment method becomes chargeable. | | `payment_method.canceled` | Payments | [`payment_method`](/api/payments-api/payment-methods/payment-method-object) | Triggers when a payment method stops being chargeable. Stop creating charges against that payment method. | | `payout.created` | Payments | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when Fintoc creates a `Payout` and starts processing it. | | `payout.succeeded` | Payments | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when Fintoc transfers a `Payout` to your bank account. | | `payout.canceled` | Payments | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when Fintoc cancels a `Payout`. Fintoc does not send a canceled `Payout` to your bank account. | | `payout.returned` | Payments | [`payout`](/api/payments-api/payouts/payout-object) | 🇲🇽 Triggers when your bank returns a previously successful `Payout`. Fintoc includes the resources from that payout in the next one. | | `refund.in_progress` | Payments | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when a `Refund` starts processing. | | `refund.succeeded` | Payments | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when Fintoc processes a `Refund` successfully. | | `refund.failed` | Payments | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when a `Refund` fails. | | `refund.returned` | Payments | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when the recipient's bank returns the transfer of a `succeeded` `Refund`. | | `subscription.payment_method_updated` | Payments | [`subscription`](/api/payments-api/subscriptions/subscription-object) | Triggers when Fintoc attaches a new payment method to the subscription through a `CheckoutSession` with `flow: setup` or with `PATCH /v2/subscriptions/{id}`. For a new `pac`, the bank may still be activating the mandate, so check the payment method's `pac.status` to confirm it is chargeable. | | `subscription.payment_method_update_failed` | Payments | [`subscription`](/api/payments-api/subscriptions/subscription-object) | Triggers when the bank rejects activation of a new payment method mandate. The subscription keeps the failed payment method with no automatic rollback, and your open invoices stay collectible through their `hosted_invoice_url`. | | `subscription_intent.succeeded` | Direct Debit (Legacy) | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when a `SubscriptionIntent` succeeds and your customer's account is enrolled. | | `subscription_intent.failed` | Direct Debit (Legacy) | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when a `SubscriptionIntent` fails because of a bank or Fintoc error. | | `subscription_intent.rejected` | Direct Debit (Legacy) | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when your customer rejects a `SubscriptionIntent`, including a failed second factor. | | `transfer.outbound.succeeded` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | Triggers when an outbound `Transfer` settles. | | `transfer.outbound.partially_succeeded` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇨🇱 Triggers when only part of an outbound `Transfer` settles. | | `transfer.outbound.returned` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇲🇽 Triggers when Banco de México or the counterparty institution returns an outbound `Transfer`. | | `transfer.outbound.failed` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | Triggers when an outbound `Transfer` cannot reach its destination account because of a processing error or because Banco de México or the counterparty institution rejects the transfer before settlement. | | `transfer.outbound.reversed` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇨🇱 Triggers when an outbound `Transfer` that settled is reversed. | | `transfer.inbound.succeeded` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | Triggers when your account receives an inbound `Transfer`. | | `transfer.inbound.returned` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | Triggers when the recipient returns an inbound `Transfer`. | | `transfer.inbound.rejected` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇨🇱 Triggers when an inbound `Transfer` is rejected before reaching your account. | | `transfer.inbound.reversed` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇨🇱 Triggers when an inbound `Transfer` your account already received is reversed and the funds leave your account. | | `transfer.inbound.return_failed` | Business Accounts | [`transfer`](/api/business-accounts-api/transfers/transfer-object) | 🇲🇽 Triggers when a return you requested for an inbound `Transfer` cannot be completed. The `Transfer` goes back to `succeeded` and the funds stay in your account. | | `transfer_batch.in_progress` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when you approve a `TransferBatch` from the Dashboard and Fintoc starts sending its transfers. | | `transfer_batch.rejected` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when you reject a `TransferBatch` from the Dashboard. Fintoc sends none of its transfers. | | `transfer_batch.expired` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when nobody approves a `TransferBatch` within two weeks. Fintoc sends none of its transfers. | | `transfer_batch.succeeded` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when every transfer in a `TransferBatch` succeeds. | | `transfer_batch.partially_succeeded` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when a `TransferBatch` finishes with some successful transfers and some failed transfers. | | `transfer_batch.failed` | Business Accounts | [`transfer_batch`](/api/business-accounts-api/transfer-batches/transfer-batch-object) | Triggers when a `TransferBatch` finishes with no successful transfers. | ## Invoice payment events An invoice reaches `paid` in two ways, and the events differ. When Fintoc collects the invoice, you receive `invoice.payment_succeeded` and then `invoice.paid`. When you mark the invoice as paid because your customer paid you outside Fintoc, you receive `invoice.paid` alone. Read `external_payment` in the payload to tell the two apart. The value is `false` when the money went through Fintoc and `true` when it did not. ## Upcoming invoice previews Fintoc sends `invoice.upcoming` ahead of each billing cycle so you can notify your customer before you charge them. Contact Fintoc to set how many days of notice you receive. The payload previews an invoice that does not exist yet, so two fields behave differently from every other `invoice.*` event: * The invoice carries no `id`, because Fintoc has not created it. * The event's `resource_id` holds the subscription, not the invoice. ## Entity onboarding payload The `entity.onboarding.approved` and `entity.onboarding.rejected` events carry the full [`Onboarding`](/api/business-accounts-api/onboardings/onboarding-object) object, so you can read the reviewed step data in `data`, the uploaded `documents`, and the declared `legal_representatives` and `shareholders` without calling the API again. The payload omits `submittable`, because a reviewed onboarding can no longer be submitted. For backward compatibility, the payload also keeps two fields that the `Onboarding` object does not have: * `object_name`: Always `onboarding_process`. * `entity`: A summary of the [`Entity`](/api/business-accounts-api/entities/entity-object) with its `id`, `holder_id`, `holder_name`, and `nationality`. Read `type` to tell the two kinds of onboarding apart. The keys inside `data`, and the slots in `documents`, depend on `type` and on the `Entity`'s country. ### Account holder An approved `account_holder` onboarding lets the `Entity` own `Account` objects at Fintoc. The example shows an approved Mexican `account_holder` onboarding: ```json theme={null} { "object": "onboarding", "object_name": "onboarding_process", "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "entity": { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "holder_id": "AAA010101AAA", "holder_name": "Test Entity 1", "nationality": "mx" }, "type": "account_holder", "source": "api", "status": "approved", "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": "2026-01-16T09:00:00Z", "data": { "company_information": { "business_activity": "Servicios financieros", "business_address": "Av. Insurgentes 456, CDMX", "fiscal_address": "Av. Reforma 123, CDMX", "phone": "+521111111111", "settlement_account": "646969000000000000" }, "transactional_profile": { "monthly_amount_range": "1_500000", "monthly_operations_range": "1_15000", "resource_origins": ["trusts", "investments"] } }, "legal_representatives": [ { "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_legal_representative", "first_name": "Test Customer 1", "last_name": "Customer", "email": "rep@example.com", "nationality": "mx", "identification_number": "AAAA010101HDFAAA01", "position": "Director General", "documents": [ { "id": "onbdoc_5erFzkDoxfDL0c2cLe0Xq4iQ", "slot_key": "identification", "status": "uploaded", "filename": "identification.pdf", "uploaded_at": "2026-01-15T14:30:00Z" } ] } ], "shareholders": [ { "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_shareholder", "type": "natural_person", "name": "Test Customer 2", "last_name": "Customer", "holder_id": "AAAA010101AAA", "percentage": 60, "parent_id": null, "document": { "id": "onbdoc_6fsGblEpygEM1d3dMf1Yr5jR", "slot_key": "identification", "status": "uploaded", "filename": "identification.pdf", "uploaded_at": "2026-01-15T14:30:00Z" } } ], "documents": [ { "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", "slot_key": "tax_registration_certificate", "status": "uploaded", "filename": "tax_registration_certificate.pdf", "uploaded_at": "2026-01-15T14:30:00Z" } ] } ``` The example is abridged: it shows one entry per array. See the [`Onboarding` object](/api/business-accounts-api/onboardings/onboarding-object) for every field in `data`, `legal_representatives`, `shareholders`, and `documents`. ### Settlement recipient A `settlement_recipient` onboarding lets the `Entity` receive [split payments](/guides/payments/accept-a-payment/accept-split-payments). `data.company_information.settlement_account` holds the bank account where Fintoc pays the `Entity`'s share. A Chilean `settlement_recipient` onboarding opens no document slots, so `documents` and each legal representative's `documents` are empty. The example shows an approved Chilean `settlement_recipient` onboarding for a company: ```json theme={null} { "object": "onboarding", "object_name": "onboarding_process", "id": "onbprc_9kQ2mZpLtR4vXnBc7HdJeKfLgMh", "entity_id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "entity": { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "holder_id": "000000001", "holder_name": "Test Merchant 1 SpA", "nationality": "cl" }, "type": "settlement_recipient", "source": "api", "status": "approved", "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": "2026-01-16T09:00:00Z", "data": { "company_information": { "activities_start_date": "2018-05-02", "business_activity": "Servicios de arquitectura", "business_address": "Av. Apoquindo 100, Santiago, Region Metropolitana, 7550000, Chile", "phone": "+56 9 1111 1111", "settlement_account": { "account_number": "123456789", "account_type": "checking_account", "institution_id": "cl_banco_de_chile" } } }, "legal_representatives": [ { "id": "onblr_7gtHcmFqzhFN2e4eNg2Zs6kS", "object": "onboarding_legal_representative", "first_name": "Test", "last_name": "Customer 1", "email": "jared@piedpiper.com", "nationality": "cl", "identification_number": "000000002", "position": "Representante legal", "phone": null, "documents": [] } ], "shareholders": [], "documents": [] } ``` For an `Entity` that onboards as a natural person, Fintoc ignores `legal_representatives`, `transactional_profile`, and `shareholders`. The payload carries empty `legal_representatives` and `shareholders` arrays, and `data` holds only `company_information`. ### Retry after a rejection What you can do after `entity.onboarding.rejected` depends on the onboarding `type`: * `account_holder`: You cannot retry through the API. An `Entity` holds one `account_holder` onboarding per mode, so creating another one returns `409 Conflict` with the code `conflicted_request`, even after a rejection. Contact Fintoc support to review the case. Fintoc can review a rejected onboarding again and approve it. You then receive `entity.onboarding.approved` with the same onboarding `id`, so let your handler accept an approval that arrives after a rejection. * `settlement_recipient`: Create a new onboarding for the same `Entity` with the corrected data. A `rejected` or `approved` onboarding does not block a new one. While another `settlement_recipient` onboarding for the `Entity` is still `pending`, `in_progress`, or `submitted`, creating a new one returns `409 Conflict`. # Institutions Source: https://docs.fintoc.com/api/main-resources/institutions/index > [!TIP] > > Only for Chile 🇨🇱 > You should use this API only if you are using Payment Initiation, Direct Debit, or Movements product in Chile Fintoc connects to several financial institutions. Use the institutions endpoint to get each institution and its available products. # Institutions object Source: https://docs.fintoc.com/api/main-resources/institutions/institutions-object ## The Institutions object An `Institution` represents a financial institution that Fintoc supports, either a Bank or a Fiscal Authority. It is returned when you list the institutions available for a given country and product. ```json Institutions Object theme={null} [ { "id": "cl_banco_santander", "object_name": "institution", "country": "cl", "name": "Banco Santander", "products": [ { "holder_type": "individual", "name": "payments" }, { "holder_type": "individual", "name": "subscription" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "business", "name": "movements" } ], "type": "bank" }, { "id": "cl_banco_internacional", "object_name": "institution", "country": "cl", "name": "Banco Internacional", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_estado", "object_name": "institution", "country": "cl", "name": "Banco Estado", "products": [ { "holder_type": "individual", "name": "subscription" }, { "holder_type": "individual", "name": "payments" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "business", "name": "movements" } ], "type": "bank" }, { "id": "cl_banco_scotiabank", "object_name": "institution", "country": "cl", "name": "Banco Scotiabank", "products": [ { "holder_type": "business", "name": "movements" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "individual", "name": "subscription" }, { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_bci", "object_name": "institution", "country": "cl", "name": "Banco BCI", "products": [ { "holder_type": "individual", "name": "subscription" }, { "holder_type": "individual", "name": "payments" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "business", "name": "movements" } ], "type": "bank" }, { "id": "cl_banco_bice", "object_name": "institution", "country": "cl", "name": "Banco BICE", "products": [ { "holder_type": "business", "name": "movements" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_hsbc", "object_name": "institution", "country": "cl", "name": "HSBC", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_itau", "object_name": "institution", "country": "cl", "name": "Banco Itaú", "products": [ { "holder_type": "individual", "name": "payments" }, { "holder_type": "business", "name": "movements" }, { "holder_type": "individual", "name": "movements" }, { "holder_type": "individual", "name": "subscription" } ], "type": "bank" }, { "id": "cl_banco_security", "object_name": "institution", "country": "cl", "name": "Banco Security", "products": [ { "holder_type": "business", "name": "payouts" }, { "holder_type": "business", "name": "movements" }, { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_falabella", "object_name": "institution", "country": "cl", "name": "Banco Falabella", "products": [ { "holder_type": "individual", "name": "payments" }, { "holder_type": "individual", "name": "subscription" } ], "type": "bank" }, { "id": "cl_banco_ripley", "object_name": "institution", "country": "cl", "name": "Banco Ripley", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_consorcio", "object_name": "institution", "country": "cl", "name": "Banco Consorcio", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_bbva", "object_name": "institution", "country": "cl", "name": "Banco BBVA", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_coopeuch", "object_name": "institution", "country": "cl", "name": "Coopeuch / Dale", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_prepago_los_heroes", "object_name": "institution", "country": "cl", "name": "Prepago Los Héroes", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_tenpo", "object_name": "institution", "country": "cl", "name": "Tenpo", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_copec_pay", "object_name": "institution", "country": "cl", "name": "Copec Pay", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_mercado_pago", "object_name": "institution", "country": "cl", "name": "Mercado Pago", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_banco_de_chile", "object_name": "institution", "country": "cl", "name": "Banco de Chile", "products": [ { "holder_type": "individual", "name": "movements" }, { "holder_type": "business", "name": "movements" }, { "holder_type": "individual", "name": "subscription" }, { "holder_type": "individual", "name": "payments" } ], "type": "bank" }, { "id": "cl_tapp_caja_los_andes", "object_name": "institution", "country": "cl", "name": "TAPP Caja los Andes", "products": [ { "holder_type": "individual", "name": "payments" } ], "type": "bank" } ] ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the financial institution. It starts with the country code of the institution. For example `cl_banco_santander`. | | `object_name` | `string` | Identifier for the type of object. Always `institution`. This resource returns `object_name` instead of the `object` key used by other API resources. | | `country` | `string` | Identifier for the country of the institution. Available countries are `cl` and `mx`. | | `name` | `string` | Corresponds to the official name of the institution. | | `products` | `array` of `objects` | Corresponds to the available products of the institution. Each product has a key `name`, which corresponds to the name of the product (`payments`, `movements`, `subscription`, `tax_returns`, `income`, `charges`). It also has the key `holder_type`, which indicates the type of accounts available (`individual`, `business`). | | `type` | `string` | Corresponds to the type of financial institutions. Available types are `bank` and `fiscal_authority`. | # Get a webhook endpoint Source: https://docs.fintoc.com/api/main-resources/webhook-endpoints/webhook-endpoints-get reference/main-api.json GET /v1/webhook_endpoints/{id} Retrieves a webhook endpoint by its `id`. Only endpoints matching the `live` or `test` mode of the API key are visible; deleted endpoints return a `404 Not Found` error. `secret` is always `null` outside creation. # List webhook endpoints Source: https://docs.fintoc.com/api/main-resources/webhook-endpoints/webhook-endpoints-list reference/main-api.json GET /v1/webhook_endpoints Lists the webhook endpoints of your organization for the `live` or `test` mode of the API key used. Deleted endpoints are not returned, and `secret` is always `null` outside creation. # Webhook endpoint object Source: https://docs.fintoc.com/api/main-resources/webhook-endpoints/webhook-endpoints-object ## The Webhook Endpoint object A `WebhookEndpoint` represents a URL that you register to receive `Event` notifications. The object stores its subscribed event types and the secret you use to validate webhook signatures. When you configure webhooks, Fintoc sends subscribed events to the endpoint's `url` in `live` or `test` mode. ```json Webhook Endpoint Object theme={null} { "id": "we_M6yrvOepCe3Rqp8B", "object": "webhook_endpoint", "created_at": "2021-05-17T17:04:10.284Z", "description": "Webhook endpoint for payment events.", "enabled_events": ["link.created", "link.credentials_changed"], "mode": "live", "secret": "...", "status": "enabled", "url": "https://my.webhook.endpoint/fintoc" } ``` The `WebhookEndpoint` object has the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the `WebhookEndpoint`. | | `object` | `string` | Type of the object. Always `webhook_endpoint`. | | `created_at` | `string` | ISO 8601 datetime in UTC when Fintoc created the `WebhookEndpoint`. | | `description` | `string` | Optional description of the `WebhookEndpoint`'s purpose. | | `enabled_events` | `Array[string]` | [Event types](/api/main-resources/events-reference/types-of-events) that Fintoc sends to the `WebhookEndpoint`. | | `mode` | `string` | Mode in which the `WebhookEndpoint` operates. One of `live` or `test`. | | `secret` | `string` | Token Fintoc uses to generate the [webhook signatures](/guides/resources/webhooks-walkthrough/webhooks-validating). Use this token to validate that Fintoc sent the webhook. Fintoc returns this field only when you create the webhook endpoint; later requests return `null`. | | `status` | `string` | Current state of the `WebhookEndpoint`. One of `enabled` (active) or `disabled` (inactive). | | `url` | `string` | URL to which Fintoc sends subscribed events. | # Checkout session object Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/checkout-session-object ## The Checkout Session object The `CheckoutSession` object represents the payment flow your customer completes to pay you. You create one to start a payment, a subscription, or a payment method setup, and Fintoc returns the `CheckoutSession` object. It holds the amount, currency, payment method configuration, and the redirect URLs your customer uses to complete the session. The session tracks its `status` through `created`, `in_progress`, `finished`, and `expired`. ```json Checkout Session Object theme={null} { "id": "cs_li5531onlFDi235", "object": "checkout_session", "amount": 350000, "business_profile": null, "cancel_url": "https://merchant.com/cancel", "created_at": "2026-01-13T18:48:25Z", "currency": "CLP", "customer": { "id": "cus_8anq0lFDi2359An", "object": "customer", "address": null, "created_at": "2026-01-13T18:40:00Z", "email": "name@example.com", "metadata": {}, "mode": "test", "name": "Test Customer 1", "phone": null, "tax_id": { "type": "cl_rut", "value": "111111111" } }, "customer_email": "name@example.com", "expires_at": "2026-01-14T18:48:25Z", "flow": "payment", "line_items": null, "metadata": {}, "mode": "test", "payment_method": null, "payment_method_options": { "bank_transfer": { "recipient_account": { "holder_id": "111111111", "institution_id": "cl_banco_de_chile", "number": "0000000000", "type": "checking_account" } } }, "payment_method_types": [ "bank_transfer" ], "payment_resource": { "payment_intent": { "id": "pi_BO381oEATXonG6bj", "object": "payment_intent", "amount": 350000, "business_profile": null, "created_at": "2026-01-13T18:48:31Z", "currency": "CLP", "customer": null, "customer_email": "name@example.com", "error_reason": null, "expires_at": "2026-01-14T18:48:25Z", "metadata": {}, "mode": "test", "next_action": null, "payment_method": null, "payment_type": "bank_transfer", "payment_type_options": {}, "recipient_account": null, "reference_id": null, "sender_account": { "holder_id": "111111111", "institution_id": "cl_banco_falabella", "number": "0000000000", "type": "checking_account" }, "status": "succeeded", "subscription": null, "transaction_date": "2026-01-13T18:50:25Z", "widget_token": null } }, "redirect_url": "https://checkout.fintoc.com/payment?checkout_session=cs_li5531onlFDi235", "save_payment_method": null, "session_token": null, "setup_intent": null, "status": "finished", "subscription": null, "success_url": "https://merchant.com/success", "ui_mode": "hosted" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the checkout session. | | `object` | `string` | Type of the object. Always `checkout_session`. | | `amount` | `integer` or `null` | Amount the session charges your customer, in the smallest unit of `currency`. `CLP` has no decimals, so `5000` means 5000 pesos; `MXN` uses *centavos*, so `5000` means 50.00 pesos. `null` for `setup` flow sessions, which do not charge your customer. | | `business_profile` | `object` or `null` | Business on whose behalf you collect the payment, for payment aggregators. `null` when the session has no business profile. See the Business profile object table below. | | `cancel_url` | `string` or `null` | URL Fintoc redirects your customer to when the payment is not completed. `null` when the session was created without redirect URLs. | | `created_at` | `string` | ISO 8601 timestamp of when the session was created. | | `currency` | `string` | Three-letter ISO 4217 currency code, in uppercase. One of `CLP` or `MXN`. | | `customer` | `object` or `null` | Customer the session belongs to. `null` when the session has no customer. See the Customer object table below. | | `customer_email` | `string` or `null` | Email of your customer, used to send the payment receipt. `null` when not provided. | | `expires_at` | `string` | ISO 8601 timestamp of when the session expires. After this time your customer can no longer pay the session. | | `flow` | `string` | Flow the session runs. One of `payment` (one-time payment), `subscription` (recurring subscription), or `setup` (save a payment method for future payments). | | `line_items` | `array` or `null` | Items the session charges for. `null` when the session was created without line items. | | `metadata` | `object` | Set of key-value pairs you attached to the session. | | `mode` | `string` | Mode of the object. `live` uses real institution data; `test` uses fake data for integration testing. | | `payment_method` | `string` or `null` | `id` of the saved payment method that pays the session. `null` when the session is not paid with a saved payment method. | | `payment_method_options` | `object` | Configuration of the session's payment methods, keyed by payment method type. Each key matches one of `payment_method_types`. For `bank_transfer` and `pac`, set a `recipient_account`, a `sender_account`, or both, described below. For `card`, set `types` in `payment` flow sessions or `kinds` (`credit`, `debit`) in `setup` and `subscription` flow sessions. For `mx_direct_debit` in `setup` sessions, set `max_amount` in MXN cents and `interval` (`week`, `month`, or `year`). If omitted, `max_amount` defaults to `1000000` and `interval` defaults to `month`. Subscription sessions derive mandate terms from `line_items`. | | `payment_method_types` | `array` | Payment method types your customer can use to pay the session. Values are `bank_transfer` (one-time bank transfer), `installments` (pay in installments), `card` (credit or debit card), `cash` (cash payment at convenience stores), `pac` (automatic recurring bank debit), and `mx_direct_debit` (Mexican direct debit for `setup` and `subscription` sessions in `test` mode with `MXN` currency). `cash` is available only for `payment` flow sessions in `MXN`. See [Direct debit in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico). | | `payment_resource` | `object` or `null` | Payment generated by the session. `null` until your customer starts a payment attempt. Holds a `payment_intent`; see the [Payment Intent object](/api/payments-api/payment-intents/payment-intents-object). | | `redirect_url` | `string` or `null` | URL of the Fintoc-hosted checkout page where your customer completes the payment. `null` for sessions paid through the Fintoc widget. | | `save_payment_method` | `string` or `null` | Whether the session lets your customer save their payment method. One of `enabled` or `disabled`. Only returned for `payment` flow sessions; `null` when not configured. | | `session_token` | `string` or `null` | Token used to initialize the Fintoc widget to pay the session. `null` for `subscription` and `setup` flows and for payments completed outside the widget. | | `setup_intent` | `string` or `null` | `id` of the setup intent created by `setup` and `subscription` flow sessions. `null` for other flows and until Fintoc attempts a setup. See the [Setup Intent object](/api/payments-api/setup-intents/setup-intent-object) for the setup intent's status and error fields. | | `status` | `string` | Lifecycle status of the session. One of `created` (your customer has not started paying), `in_progress` (Fintoc is processing the payment), `finished` (the session succeeded), or `expired`. | | `subscription` | `string` or `null` | Identifier for the subscription associated with the session. For a `subscription` flow, the value is the subscription the session starts, or `null` until Fintoc creates the subscription. For a `setup` flow created with `subscription`, the value is the existing subscription whose payment method the session updates; otherwise, `null`. | | `success_url` | `string` or `null` | URL Fintoc redirects your customer to after a successful payment. `null` when the session was created without redirect URLs. | | `ui_mode` | `string` | User interface the checkout uses. One of `hosted` (Fintoc-hosted page) or `embedded` (embedded buttons such as [Apple Pay](/guides/payments/accept-a-payment/accept-a-one-click-payment-with-apple-pay)). | ## Customer object The customer the session belongs to, when you attach one on creation. | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the customer. | | `object` | `string` | Type of the object. Always `customer`. | | `address` | `object` or `null` | Address of the customer. `null` when not provided. See the Address object table below. | | `created_at` | `string` | ISO 8601 timestamp of when the customer was created. | | `email` | `string` or `null` | Email of the customer. `null` when not provided. | | `metadata` | `object` | Set of key-value pairs attached to the customer. | | `mode` | `string` | Mode of the object. `live` uses real institution data; `test` uses fake data for integration testing. | | `name` | `string` or `null` | Name of the customer. `null` when not provided. | | `phone` | `string` or `null` | Phone number of the customer. `null` when not provided. | | `tax_id` | `object` or `null` | Tax identifier of the customer. `null` when not provided. See the Tax ID object table below. | ## Address object | Attribute | Type | Description | | :- | :- | :- | | `city` | `string` | City of the address. | | `country` | `string` | Country of the address, as a two-letter ISO 3166-1 code. | | `line1` | `string` | First line of the address. | | `line2` | `string` | Second line of the address. | | `postal_code` | `string` | Postal code of the address. | | `state` | `string` | State or region of the address. | ## Tax ID object | Attribute | Type | Description | | :- | :- | :- | | `type` | `string` | Type of the tax identifier, for example `cl_rut`. | | `value` | `string` | Value of the tax identifier. | ## Payment method options Use `payment_method_options` to configure payment methods in the session. For `bank_transfer`, set a `recipient_account` and, optionally, a `sender_account`. For `pac`, set a `sender_account`. For `card`, the [Create checkout session](/api/payments-api/checkout-sessions/checkout-sessions-create) endpoint defines `types` for `payment` flow sessions and `kinds` (`credit`, `debit`) for `setup` and `subscription` flow sessions. | Attribute | Type | Description | | :- | :- | :- | | `recipient_account` | `object` | Account that receives the payment. See the Recipient account object table below. If you collect through Fintoc, omit it for better stability. | | `sender_account` | `object` | Account your customer pays from. See the Sender account object table below. In final payment notifications it may be `null` if your customer abandoned the payment before choosing one. | ## Recipient account object The Recipient account object describes the bank account that receives the funds, returned in the `recipient_account` field. | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Tax ID of the account holder. In Chile, a Chilean tax ID (RUT = Chilean tax ID); in Mexico, a Mexican tax ID (RFC = Mexican tax ID) or a Mexican personal ID (CURP). | | `institution_id` | `string` | Identifier of the account's institution. See [Chile institution codes](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). | | `number` | `string` | Account number, without hyphens or leading zeros. | | `type` | `string` | Type of the account. One of `checking_account` or `sight_account`. | ## Sender account object The Sender account object describes the customer's bank account that the funds are paid from, returned in the `sender_account` field. | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Tax ID of the account holder. In Chile, a Chilean tax ID (RUT); in Mexico, a Mexican tax ID (RFC) or a Mexican personal ID (CURP). Without a `holder_id`, Fintoc skips new contact validations. | | `institution_id` | `string` | Identifier of the account's institution. See [Chile institution codes](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). | | `number` | `string` | Account number, without hyphens or leading zeros. | | `type` | `string` | Type of the account. One of `checking_account` or `sight_account`. | ## Business profile object The Business profile object identifies the enrolled merchant receiving the payment, returned in the `business_profile` field of the Checkout Session. | Attribute | Type | Description | | :- | :- | :- | | `category` | `string` | Six-character merchant category code (MCC) of the business. In Chile, it corresponds to an [SII activity code](https://www.sii.cl/ayudas/ayudas_por_servicios/1956-codigos-1959.html). | | `name` | `string` | Name of the business. If set, it appears as the recipient on the successful payment screen. | | `tax_id` | `string` | Chilean tax ID (RUT) of the business. | # Create a checkout session Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/checkout-sessions-create reference/main-api.json POST /v2/checkout_sessions Creates a checkout session in the `live` or `test` mode of the API key used. The `flow` determines what the session does: `payment` collects a one-time payment, `subscription` starts a recurring subscription, and `setup` saves a payment method for future payments. Required fields depend on the flow. After creating the session, redirect your customer to the session's `redirect_url` or initialize the Fintoc widget with the session's `session_token`. # Expire a checkout session Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/checkout-sessions-expire reference/main-api.json POST /v2/checkout_sessions/{id}/expire Expires the checkout session with the given `id` before your customer completes the payment. You can only expire a session while its `status` is `created`. Expiring a session also expires any pending payment of the session and triggers a `checkout_session.expired` webhook event. Returns the session with its `status` set to `expired`. # Get a checkout session Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/checkout-sessions-get reference/main-api.json GET /v2/checkout_sessions/{id} Retrieves the checkout session with the given `id` for the `live` or `test` mode of the API key used. Use this endpoint to check the current `status` of the session and, once your customer finishes the payment, the resulting `payment_resource`. # List checkout sessions Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/checkout-sessions-list reference/main-api.json GET /v2/checkout_sessions Lists the checkout sessions of your organization for the `live` or `test` mode of the API key used. The API returns sessions sorted by creation date, with the most recently created sessions first. Use `limit`, `starting_after`, and `ending_before` to paginate through the list. The `Link` response header contains the URL of the next page. # Checkout sessions Source: https://docs.fintoc.com/api/payments-api/checkout-sessions/index This page explains how checkout sessions support one-time payments. A checkout session represents the payment flow your customer follows to complete a payment. You create a checkout session, then redirect your customer to the Fintoc-hosted page or render the embedded widget. Fintoc tracks the checkout session through completion and exposes the resulting payment in `payment_resource`. Use these endpoints to create and list checkout sessions, get a checkout session's current state, or expire a checkout session before your customer completes the payment. # The Customer object Source: https://docs.fintoc.com/api/payments-api/customers/customer-object The `Customer` object represents a payer you can reuse across payments. The object stores contact and tax details such as `name`, `email`, `phone`, `address`, and `tax_id`. Fintoc returns the `Customer` object in Customers API responses and in objects that reference a customer, such as `CheckoutSession` and `PaymentIntent`. ```json theme={null} { "id": "cus_4xKp2BanKWYnR7m", "object": "customer", "address": { "city": "Santiago", "country": "cl", "line1": "Av. Providencia 1234", "line2": "Oficina 501", "postal_code": "7500000", "state": "RM" }, "created_at": "2026-03-26T20:15:30Z", "email": "acme@example.com", "metadata": {}, "mode": "live", "name": "Acme Corp", "phone": "+56911111111", "tax_id": { "type": "cl_rut", "value": "111111111" } } ``` The `Customer` object has the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier, prefixed with `cus_`. | | `object` | `string` | Object type. Always `customer`. | | `address` | `object` or `null` | Postal address of the customer. See the nested `address.*` fields. | | `address.city` | `string` | City of the customer. | | `address.country` | `string` | Two-letter country code (ISO 3166-1 alpha-2). Normalized to lowercase. | | `address.line1` | `string` | Primary address line of the customer. | | `address.line2` | `string` | Secondary address line of the customer, for example apartment or suite. | | `address.postal_code` | `string` | Postal or ZIP code of the customer. | | `address.state` | `string` | State or region of the customer. | | `created_at` | `string` | ISO 8601 datetime in UTC indicating when the customer was created. | | `email` | `string` | Email address of the customer, formatted per RFC 5322. Normalized to lowercase. At least one of `email` or `tax_id` is required. | | `metadata` | `object` | Set of key-value pairs for storing additional information. | | `mode` | `string` | Environment in which the customer was created. One of `live` or `test`. | | `name` | `string` or `null` | Full name of a person or the legal name of a business. | | `phone` | `string` or `null` | Phone number of the customer in E.164 format, for example `+56911111111`. | | `tax_id` | `object` or `null` | Tax identifier of the customer: a Chilean tax ID (RUT), a Mexican tax ID (RFC), or a custom identifier. At least one of `tax_id` or `email` is required. | | `tax_id.type` | `string` | Type of tax identifier. Required when `tax_id` is provided. One of `cl_rut` (Chilean RUT), `mx_rfc` (Mexican RFC), or `custom` (any other identifier). Fintoc does not validate the format of `custom` values. | | `tax_id.value` | `string` | Tax identifier, normalized. Fintoc stores RUTs without dots or hyphens, RFCs in uppercase, and `custom` values without leading or trailing spaces. | # Create a customer Source: https://docs.fintoc.com/api/payments-api/customers/customers-create reference/main-api.json POST /v2/customers Creates a customer in the `live` or `test` mode of the API key used. Send at least one of `email` or `tax_id`; every other field is optional. If you send `tax_id`, both its `type` and `value` are required. Fintoc normalizes values before storing them. It lowercases `email` and `address.country`, removes dots and hyphens from Chilean tax IDs (RUTs), uppercases Mexican tax IDs (RFCs), and removes leading and trailing spaces from custom identifiers. # Get a customer Source: https://docs.fintoc.com/api/payments-api/customers/customers-get reference/main-api.json GET /v2/customers/{id} Retrieves the customer with the given `id`. Only customers created in the `live` or `test` mode of the API key used are visible. Requesting a customer from the other mode returns a `404 Not Found` error. # List customers Source: https://docs.fintoc.com/api/payments-api/customers/customers-list reference/main-api.json GET /v2/customers Lists the customers of your organization for the `live` or `test` mode of the API key used. Customers are returned sorted by creation date, with the most recently created customers appearing first. Use `limit` together with the `starting_after` and `ending_before` cursors to paginate the results. The `Link` response header contains the URL of the next page when more results are available. # The Dispute Document object Source: https://docs.fintoc.com/api/payments-api/disputes/dispute-document-object The `DisputeDocument` object represents a file you upload as evidence for a dispute. Fintoc returns the `DisputeDocument` object when you upload a document and in the `documents` array of the `Dispute` object. The object has the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the dispute document. Prefixed with `cbd_`. | | `object` | `string` | Type of the object. Always `dispute_document`. | | `content_type` | `string \| null` | Media type of the uploaded file, for example `application/pdf`. `null` when Fintoc cannot determine the type. | | `created_at` | `string` | ISO 8601 datetime in UTC when the document was uploaded. | | `dispute_id` | `string` | Identifier of the dispute this document belongs to. | | `filename` | `string` | Name of the uploaded file. | | `size` | `integer` | Size of the uploaded file in bytes. | ```json Dispute Document Object theme={null} { "id": "cbd_8anBm9YpVwXzKqL2", "object": "dispute_document", "content_type": "application/pdf", "created_at": "2024-01-16T17:04:10.284Z", "dispute_id": "cb_8anBm9YpVwXzKqL2", "filename": "evidence.pdf", "size": 102400 } ``` # The Dispute object Source: https://docs.fintoc.com/api/payments-api/disputes/dispute-object The `Dispute` object represents a payment your customer has contested with their card issuer or bank, also known as a chargeback. The `payment_method_type` field indicates whether the disputed payment is a `card` payment or a `mx_direct_debit` (Mexican direct debit) payment. Fintoc returns this object in Disputes API responses and in dispute webhook events. The `status` field indicates whether the dispute is `waiting_documentation`, `in_review`, `won`, `lost`, `expired`, or `canceled`. | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the dispute. Prefixed with `cb_`. | | `object` | `string` | Type of the object. Always `dispute`. | | `amount` | `integer` | Disputed amount, in the currency's smallest unit. CLP has no decimals, so `7005` means 7005 CLP; MXN and USD have cents, so `7005` means 70.05. | | `created_at` | `string` | ISO 8601 datetime in UTC when the dispute was created. | | `currency` | `string` | ISO 4217 currency code of the disputed amount. | | `documentation_upload_deadline` | `string` or `null` | ISO 8601 datetime in UTC for the documentation submission deadline before the dispute is lost by default. The field is `null` when no documentation is required. | | `documents` | `array` | Array of [`DisputeDocument`](/api/payments-api/disputes/dispute-document-object) objects uploaded as evidence for the dispute. | | `mode` | `string` | One of `live` or `test`. | | `payment_method_type` | `string` | Payment method used for the disputed payment. One of `card` or `mx_direct_debit` (Mexican direct debit). | | `resource_id` | `string` | Identifier of the disputed resource. | | `resource_type` | `string` | Type of the disputed resource. Always `payment_intent`. | | `status` | `string` | Current status of the dispute. One of `waiting_documentation`, `in_review`, `lost`, `expired`, `won`, or `canceled`. `canceled` means Fintoc voided the dispute. | | `updated_at` | `string` | ISO 8601 datetime in UTC when the dispute was last updated. | ```json Dispute Object theme={null} { "id": "cb_8anBm9YpVwXzKqL2", "object": "dispute", "amount": 7005, "created_at": "2024-01-15T17:04:10.284Z", "currency": "CLP", "documentation_upload_deadline": "2024-01-22T17:04:10.284Z", "documents": [ { "id": "cbd_8anBm9YpVwXzKqL2", "object": "dispute_document", "content_type": "application/pdf", "created_at": "2024-01-16T17:04:10.284Z", "dispute_id": "cb_8anBm9YpVwXzKqL2", "filename": "evidence.pdf", "size": 102400 } ], "mode": "live", "payment_method_type": "card", "resource_id": "pi_8anBm9YpVwXzKqL2", "resource_type": "payment_intent", "status": "waiting_documentation", "updated_at": "2024-01-16T17:04:10.284Z" } ``` # Upload a dispute document Source: https://docs.fintoc.com/api/payments-api/disputes/disputes-documents-create reference/main-api.json POST /v1/disputes/{dispute_id}/documents Uploads a document as evidence for a dispute. Send the file as `multipart/form-data`. The file must be a PDF, JPEG, or PNG and smaller than 10 MB. You can upload documents only while the dispute is in `waiting_documentation` and within its documentation upload deadline. The dispute must match the `live` or `test` mode of the API key used. # Get a dispute Source: https://docs.fintoc.com/api/payments-api/disputes/disputes-get reference/main-api.json GET /v1/disputes/{id} Retrieves a dispute by its `id`. Only disputes matching the `live` or `test` mode of the API key are visible; any other dispute returns a `404 Not Found` error without leaking its existence. # List disputes Source: https://docs.fintoc.com/api/payments-api/disputes/disputes-list reference/main-api.json GET /v1/disputes Lists the disputes of your organization for the `live` or `test` mode of the API key used. Returns the most recent disputes first. Use the `status`, `resource_id`, `since`, and `until` query parameters to filter the list. # Submit a dispute for review Source: https://docs.fintoc.com/api/payments-api/disputes/disputes-submit-for-review reference/main-api.json POST /v1/disputes/{id}/submit_for_review Submits the uploaded documentation of a dispute for review. The dispute must be in `waiting_documentation`, have at least one document, and be within its documentation upload deadline. On success the dispute moves to `in_review` and Fintoc's operations team is notified. # Disputes Source: https://docs.fintoc.com/api/payments-api/disputes/index Disputes let you review disputed payments, upload evidence, and submit that evidence to Fintoc for review. # The Invoice Line Item object Source: https://docs.fintoc.com/api/payments-api/invoice-line-items/invoice-line-item-object Reference for the Invoice Line Item object, which represents a single charge on an Invoice with its amount, quantity, and billing period. ## The Invoice Line Item object An `InvoiceLineItem` represents a single charge on an invoice, including its amount, quantity, and billing period. It appears in the `lines` array of an `Invoice`, where each item contributes to the invoice total. ```json Invoice Line Item Object theme={null} { "id": "il_348nasdfsdf", "object": "line_item", "amount": 15000, "currency": "CLP", "period_end": "2025-09-01T00:00:00Z", "period_start": "2025-08-01T00:00:00Z", "quantity": 1 } ``` | Attribute | Type | Description | | - | - | - | | `id` | string | Unique identifier for the line item. | | `object` | string | Type of the object. Always `line_item`. | | `amount` | integer | Amount in the smallest currency unit, for example `1000` for \$10.00 MXN, or `1000` for \$1000 CLP, since CLP has no minor unit. | | `currency` | string | [Three-letter ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). Only `CLP` is supported. | | `period_end` | string | ISO 8601 datetime in UTC for the end of the billing period. | | `period_start` | string | ISO 8601 datetime in UTC for the start of the billing period. | | `quantity` | integer | Quantity of items. | # Update an invoice line item Source: https://docs.fintoc.com/api/payments-api/invoice-line-items/invoice-lines-update reference/main-api.json PATCH /v2/invoices/{invoice_id}/lines/{id} Updates a line item of a draft invoice and recalculates the invoice total. All body fields are optional; send only the fields you want to change. The invoice must be in `draft` status and any new currency must match the invoice currency. # Update an invoice line item Source: https://docs.fintoc.com/api/payments-api/invoices/invoice-lines-update reference/main-api.json PATCH /v2/invoices/{invoice_id}/lines/{id} Updates a line item of a draft invoice and recalculates the invoice total. All body fields are optional; send only the fields you want to change. The invoice must be in `draft` status and any new currency must match the invoice currency. # The Invoice object Source: https://docs.fintoc.com/api/payments-api/invoices/invoice-object Reference for the Invoice object in Fintoc: line items, payment attempts, collection method, and the status that tracks your customer's debt. An invoice represents an amount your customer owes. You create an invoice explicitly, or Fintoc generates one automatically from a subscription. Each invoice lists its line items, tracks its payment attempts, and reflects the status of the customer's debt. ```json theme={null} { "id": "inv_456789abcdef", "object": "invoice", "attempt_count": 1, "collection_method": "charge_automatically", "created_at": "2025-08-01T12:00:00Z", "currency": "CLP", "customer": "cus_asdlfknmuy", "default_payment_method": "pm_9asdfkjn23", "external_payment": false, "hosted_invoice_url": "https://acme.billing.fintoc.com/invoices/inv_456789abcdef", "lines": [ { "id": "il_348nasdfsdf", "object": "line_item", "amount": 15000, "currency": "CLP", "period_end": "2025-09-01T00:00:00Z", "period_start": "2025-08-01T00:00:00Z", "quantity": 1 } ], "metadata": {}, "mode": "live", "next_payment_attempt_at": null, "payments": [ { "amount": 15000, "currency": "CLP", "payment_intent": "pi_duinkasdfb", "status": "succeeded" } ], "reason": null, "status": "paid", "subscription": "sub_123489rnas", "total": 15000 } ``` The invoice contains the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the invoice. | | `object` | `string` | Type of the object. Always `invoice`. | | `attempt_count` | `integer` | Number of payment attempts Fintoc has made on the invoice. `0` until the first attempt. Fintoc stops retrying after 5 attempts. | | `collection_method` | `string` | How Fintoc collects the invoice. One of `charge_automatically` or `send_invoice`. | | `created_at` | `string` | ISO 8601 datetime in UTC when the invoice was created. | | `currency` | `string` | [Three-letter ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). Fintoc supports only `CLP`. | | `customer` | `string` | ID of the customer this invoice bills. | | `default_payment_method` | `string` or `null` | ID of the payment method Fintoc charges when `collection_method` is `charge_automatically`. `null` if the invoice has no payment method. | | `external_payment` | `boolean` | If `true`, you marked the invoice as paid because your customer paid it outside Fintoc. | | `hosted_invoice_url` | `string` or `null` | URL for the Fintoc-hosted page where your customer can view and pay the invoice. The value is `null` until the invoice is `open`. | | `lines` | `array` | Line items on the invoice. See the Line Item object below. | | `metadata` | `object` or `null` | Set of [key-value](/api/fintoc-api/metadata) pairs you can attach to the invoice. Use `metadata` to store additional structured information about the invoice. `null` if the invoice has no metadata. | | `mode` | `string` | API key mode. One of `live` or `test`. | | `next_payment_attempt_at` | `string` or `null` | ISO 8601 datetime in UTC of the next automatic charge Fintoc has scheduled. `null` when Fintoc has no charge scheduled, including invoices whose `collection_method` is `send_invoice`. | | `payments` | `array` | Payment attempts made against the invoice. See the Invoice Payment object below. | | `reason` | `string` or `null` | Why the invoice reports `inconsistent`. `split_amount_mismatch` means the `split` doesn't add up to `total`, so Fintoc can't finalize the invoice. See [Split mismatches at finalization](/guides/payments/accept-recurring-payments/split-on-recurring-payments#split-mismatches-at-finalization). The value is `null` for every other status. | | `status` | `string` | Current state of the invoice. One of `draft`, `open`, `paid`, `void`, `uncollectible`, or `inconsistent`. A `draft` invoice whose `split` doesn't add up to `total` reports `inconsistent` until you update `split` or `lines`. | | `subscription` | `string` or `null` | ID of the subscription that generated this invoice. `null` for invoices you create directly. | | `total` | `integer` | Total amount due, in the smallest currency unit. For example, `15000` for \$15,000 CLP, since CLP has no minor unit. | > [!WARNING] > > Marking an invoice as paid outside Fintoc is irreversible. Once `external_payment` turns `true`, > you cannot set it back to `false`. An invoice with `collection_method` set to `send_invoice` stays `open` until you or your customer pays the invoice. You choose how: send the payment link, charge the invoice on demand, or collect the money outside Fintoc and mark the invoice as paid. Unpaid invoices accumulate, one per billing period, and each invoice is paid separately. ## Nested object: Line Item Each object in `lines` contains the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the line item. | | `object` | `string` | Type of the object. Always `line_item`. | | `amount` | `integer` | Amount for this line item, in the smallest currency unit. For example, `15000` for \$15,000 CLP, since CLP has no minor unit. | | `currency` | `string` | [Three-letter ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). Fintoc supports only `CLP`. | | `period_end` | `string` | ISO 8601 datetime in UTC when the billing period ends. | | `period_start` | `string` | ISO 8601 datetime in UTC when the billing period starts. | | `quantity` | `integer` | Number of units for this line item. | ## Nested object: Invoice Payment Each object in `payments` contains the following attributes: | Attribute | Type | Description | | - | - | - | | `amount` | `integer` | Payment amount, in the smallest currency unit. For example, `15000` for \$15,000 CLP, since CLP has no minor unit. | | `currency` | `string` | [Three-letter ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). Fintoc supports only `CLP`. | | `payment_intent` | `string` | ID of the `PaymentIntent` that processed this payment attempt. | | `status` | `string` | Current state of the payment attempt. One of `pending`, `succeeded`, or `failed`. | # Add invoice lines Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-add-lines reference/main-api.json POST /v2/invoices/{id}/add_lines Appends one or more line items to a draft invoice and recalculates the invoice total. The invoice must be in `draft` status and every line item must use the invoice currency. If any line item is invalid, the whole request fails and no line item is added. # Create an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-create reference/main-api.json POST /v2/invoices Creates a one-off invoice for a customer, in the `live` or `test` mode of the API key used. The invoice is not tied to a subscription and starts in `draft` status. Fintoc does not charge the invoice until you finalize it. The `total` is the sum of the `lines`, which must all share the same `currency`. The `collection_method` decides how Fintoc collects the invoice once you finalize it. With `charge_automatically`, the default, Fintoc charges `default_payment_method`, so the payment method is required. With `send_invoice`, Fintoc leaves the invoice open for you to collect, and `default_payment_method` is optional. # Finalize an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-finalize reference/main-api.json POST /v2/invoices/{id}/finalize Finalizes a `draft` invoice, moving its `status` to `open`. This is how you advance an invoice for collection: Fintoc never finalizes invoices automatically. When the invoice has a `default_payment_method` and its `collection_method` is `charge_automatically`, Fintoc charges the invoice right after finalizing. Finalizing an invoice that is already `open`, or a zero-amount invoice that Fintoc already marked as `paid`, returns the invoice unchanged. You cannot finalize a `paid` invoice with a positive `total` or a `void` invoice. > [!NOTE] > > **Subscription invoices finalize automatically** > > For invoices you create with [Create an invoice](/api/payments-api/invoices/invoices-create), Fintoc does not finalize the invoice automatically. The invoice stays `draft` until you call this endpoint. > > That rule does not apply to invoices issued by a subscription. Fintoc creates each subscription invoice in `draft` and finalizes it after 1 hour, moving it to `open` and charging it. The exception is a subscription's first invoice, which Fintoc finalizes immediately. See [Manage invoices](/guides/payments/accept-recurring-payments/manage-invoices). > > Call this endpoint on a subscription invoice only to collect the invoice before the one-hour draft window ends. # Get an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-get reference/main-api.json GET /v2/invoices/{id} Retrieves an invoice by its `id`. Only invoices of your organization that match the `live` or `test` mode of the API key are visible. # List invoices Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-list reference/main-api.json GET /v2/invoices Lists the invoices of your organization for the `live` or `test` mode of the API key used, sorted by creation date with the most recent first. Use `subscription` to narrow the list to the invoices generated by a single subscription, and the cursor parameters to paginate through the results. # Mark invoice uncollectible Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-mark-uncollectible reference/main-api.json POST /v2/invoices/{id}/mark_uncollectible Marks an invoice as `uncollectible` when you no longer expect payment. The invoice must be `open` with no payment in progress. The invoice must belong to your organization and the `live` or `test` mode of your API key. Fintoc emits an `invoice.marked_uncollectible` webhook event. Returns the updated `Invoice` object with `status` set to `uncollectible`. Returns `409 Conflict` if the invoice is not `open`, including when already `uncollectible`. Returns `422 Unprocessable Entity` if an `open` invoice has a payment in progress. # Pay an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-pay reference/main-api.json POST /v2/invoices/{id}/pay Settles an `open` invoice, in the `live` or `test` mode of the API key used. By default Fintoc charges the invoice: pass `payment_method` to charge a specific method, or omit it to use the invoice's `default_payment_method`. The method must belong to the invoice's customer and be active. Use this to collect an invoice on demand, or to retry collection after a failed attempt with a different method. The charge is asynchronous: the invoice stays `open` with a `pending` payment until the charge resolves. Pass `external_payment` instead to mark the invoice paid because you collected it outside Fintoc. Fintoc moves the invoice to `paid` right away and creates no payment. Fintoc does not verify the amount you collected, and settling an invoice is not reversible. # Remove invoice lines Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-remove-lines reference/main-api.json POST /v2/invoices/{id}/remove_lines Removes one or more line items from a draft invoice and recalculates the invoice total. Pass the `id` of every line item to remove. If any `id` does not belong to a line item of the invoice, the whole request fails and no line item is removed. The invoice must be in `draft` status. # Update an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-update reference/main-api.json PATCH /v2/invoices/{id} Updates the `metadata` or the `split` of the invoice with the given `id`. You can change `metadata` at any point in the invoice's lifecycle, including after it is paid or voided. When `metadata` is provided, it replaces the entire existing metadata object. If you omit it, the invoice keeps its current metadata. You can change `split` only while the invoice is in `draft` status. Changing `split` replaces the current rules as a whole, including the rules the invoice inherited from its subscription. The invoice must belong to your organization and to the `live` or `test` mode of the API key used. # Void an invoice Source: https://docs.fintoc.com/api/payments-api/invoices/invoices-void reference/main-api.json POST /v2/invoices/{id}/void Voids an invoice, setting its `status` to `void` so it can no longer be paid. You can void an invoice while it is in `draft` or `open` status. Voiding an invoice that is already `void` returns it unchanged. You cannot void an invoice that has already been paid, or one with a payment in progress. # Payment intent error reason Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intent-error-reason Every `error_reason` value Fintoc sets on a failed Payment Intent, covering bank transfers, card payments, direct debit, and bank transfer widget screens. Payment Intents can fail for a variety of reasons. The reason a given Payment Intent failed is available in a [Payment Intent Object](/api/payments-api/payment-intents/payment-intents-object)'s `error_reason` attribute. Below is a list of all the types of `error_reason` Fintoc currently sends. Fintoc may add more at any time, so when developing and maintaining your code, don't assume that only these types exist. ## Bank transfers Bank transfer `error_reason` values use these descriptions: | Error reason | Description | Country | | - | - | - | | `bank_account_locked` | The bank blocked the transfers service for this account. | 🇨🇱 | | `bank_connection_error` | Fintoc had a problem connecting with the selected bank. | 🇨🇱 | | `bank_not_available` | The selected bank is temporarily unavailable. | 🇨🇱 | | `amount_limit_reached` | The payment reached the maximum amount available to transfer. | 🇨🇱 | | `insufficient_funds` | The account doesn’t have enough money to execute the payment. | 🇨🇱 | | `login_credentials_locked` | The bank indicated that the user's credentials are locked. | 🇨🇱 | | `login_invalid_credentials` | The bank indicated that the user's credentials are invalid. | 🇨🇱 | | `maximum_amount_error` | The amount exceeds the maximum amount allowed for that bank. | 🇨🇱 | | `mfa_authorization_timeout` | The user did not authorize the transfer with their multifactor method. | 🇨🇱 | | `mfa_invalid_authorization` | The bank indicated that the multifactor authorization was invalid. | 🇨🇱 | | `mfa_locked` | The multifactor authentication method is locked. | 🇨🇱 | | `mfa_unavailable` | The multifactor authentication method is unavailable. | 🇨🇱 | | `new_contact_amount_limit_reached` | The amount exceeds the maximum amount permitted for new contacts. | 🇨🇱 | | `new_contact_transfer_number_limit_reached` | The payment reached the maximum number of transfers allowed for new contacts. | 🇨🇱 | | `recipient_account_not_allowed` | The bank indicated that the recipient account is not allowed to receive transfers. | 🇨🇱 | | `unresolved_final_status` | The bank can’t provide a definite answer on whether this payment was completed or not. This reason only appears for pending payments that Fintoc could not validate after 10 days. | 🇨🇱 | | `widget_closed` | The user closed the widget before completing the payment. | 🇨🇱/🇲🇽 | | `user_left` | The user abandoned the payment process before selecting an account or entering their bank account's credentials. | 🇨🇱/🇲🇽 | | `new_payment_intent_in_progress` | The user started a new payment intent before completing the previous one, so the original payment intent was cancelled. | 🇲🇽 | ## Card payments Card payment `error_reason` values use these descriptions: | Error reason | Description | Country | | - | - | - | | `authentication_failed` | 3D Secure card authentication failed. | 🇨🇱/🇲🇽 | | `card_declined` | The card issuer declined the transaction. | 🇨🇱/🇲🇽 | | `insufficient_funds` | The card has insufficient funds or exceeds a spending limit. | 🇨🇱/🇲🇽 | | `invalid_amount` | The card processor did not accept the payment amount, for example because of a currency conversion overflow. Ask your customer to try another payment method. | 🇨🇱/🇲🇽 | | `invalid_card` | The card is not supported or its data could not be validated. | 🇨🇱/🇲🇽 | | `invalid_card_credentials` | The card number, expiration date, or security code is incorrect. | 🇨🇱/🇲🇽 | ## Direct debit Direct debit `error_reason` values use these descriptions when a Payment Intent's `payment_type` is `pac` (Pago Automático de Cuentas in Chile) or `mx_direct_debit` (domiciliación in Mexico): | Error reason | Description | Country | | - | - | - | | `insufficient_funds` | The account doesn’t have enough money to cover the charge. | 🇨🇱/🇲🇽 | | `amount_limit_reached` | The charge exceeds or doesn’t match the amount allowed for the mandate or the account. | 🇨🇱/🇲🇽 | | `bank_account_locked` | The bank blocked the account, so it can’t be charged. | 🇨🇱/🇲🇽 | | `payment_method_account_not_found` | The account linked to the mandate doesn’t exist, is closed, or isn’t valid. | 🇨🇱/🇲🇽 | | `bank_account_not_chargeable` | The account type or currency doesn’t accept direct debit charges. | 🇲🇽 | | `mandate_revoked` | Your customer or their bank canceled the mandate, your customer asked their bank to stop charging the mandate, or the bank doesn’t have the mandate registered. | 🇨🇱/🇲🇽 | | `mandate_not_active` | The mandate wasn’t active when the charge was processed, for example because your customer’s consent wasn’t confirmed. | 🇲🇽 | | `charge_canceled_by_provider` | Fintoc’s direct debit processor canceled the charge, for example after a risk or document check. | 🇲🇽 | | `bank_not_available` | Your customer’s bank doesn’t participate in direct debit or isn’t valid. | 🇲🇽 | | `bank_connection_error` | The bank or the interbank network rejected or couldn’t process the charge. | 🇲🇽 | | `internal_error` | The charge failed for a reason Fintoc can’t classify. | 🇨🇱 | ## Bank transfer widget screens The following widget screens are examples for specific cases. Fintoc shows a different screen depending on the error reason, so the actual screen your customer sees might differ from these examples. ### `bank_account_locked` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-bank_account_locked.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=e7e8addf3959b907969fb388dd22abc0) ### `bank_connection_error` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-bank_connection_error.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=467828f3170d769b7ec05d9e695844fa) ### `bank_not_available` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-bank_not_available.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=d7f394c5b2dbc56feff48af00498e9bb) ### `amount_limit_reached` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-amount_limit_reached.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=56e130d6d7ad93a26fd606c0f92c9e4b) ### `insufficient_funds` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-insufficient_funds.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=21e806e7ee9075f87823446633566c84) ### `login_credentials_locked` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-login_credentials_locked.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=958ab9ea0d681ac63d9c8d805bbc399e) ### `login_invalid_credentials` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-login_invalid_credentials.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=9f4f8632721a6cb5491362e4cc24301a) ### `maximum_amount_error` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-maximum_amount_error.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=83312f0d10660e357dd918bba9511cab) ### `mfa_authorization_timeout` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-mfa_authorization_timeout.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=56011721e6f4ae54e9318de88d3d3073) ### `mfa_invalid_authorization` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-mfa_invalid_authorization1.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=fcc71befb12ed80c7e5951108402368e) ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-mfa_invalid_authorization2.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=f8f26598e63daca244bdde1c4fa0f337) ### `mfa_locked` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-mfa_locked.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=e2cdc556439ac6ed0d7ffa7530549ee4) ### `mfa_unavailable` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-mfa_unavailable.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=52ed37e57a470845074df592140ef3e6) ### `new_contact_amount_limit_reached` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-new_contact_amount_limit_reached.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=f36ff431158784c7bb95690431c20a06) ### `new_contact_transfer_number_limit_reached` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-new_contact_transfer_number_limit_reached.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=8ceaade5e1dc0c2bb4ecce9f9cb4dbcd) ### `recipient_account_not_allowed` ![](https://mintcdn.com/fintoc-49b8bee8/K-2lktsiIl0lfAbM/images/payment-intent-error-recipient_account_not_allowed.png?fit=max\&auto=format\&n=K-2lktsiIl0lfAbM\&q=85\&s=1b5ac5ad57668abda44cef30e4d4cf4f) # Check payment eligibility Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intents-check-eligibility reference/main-api.json POST /v2/payment_intents/check_eligibility Checks whether a payment for the given amount and sender account passes the transfer limits that banks and Fintoc enforce, without creating a payment intent. Only available for CLP payments. Available for organizations on API version `2026-02-01` or later. # Create a payment intent Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intents-create reference/main-api.json POST /v2/payment_intents Creates a payment intent that charges a previously saved payment method, in the `live` or `test` mode of the API key used. Unlike `POST /v1/payment_intents`, which starts a customer-present flow completed through the Fintoc widget, this endpoint charges the `payment_method` directly, with no customer interaction and no widget token. This endpoint does not accept v1-only parameters such as `recipient_account`, `customer_email`, `payment_type`, or `expires_at`. The charge starts in the `created` status; Fintoc processes the charge asynchronously, so subscribe to webhooks to track the charge's progress. Available for organizations on API version `2026-02-01` or later. # Get a payment intent Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intents-get reference/main-api.json GET /v2/payment_intents/{id} Retrieves the payment intent with the given `id`. The payment intent must belong to your organization and match the `live` or `test` mode of the API key used. Available for organizations on API version `2026-02-01` or later. # List payment intents Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intents-list reference/main-api.json GET /v2/payment_intents Returns the payment intents of your organization, in the `live` or `test` mode of the API key used, sorted by creation date with the most recent first. Unlike `GET /v1/payment_intents`, which uses page-based pagination (`page` and `per_page`), this endpoint uses cursor-based pagination. Use `limit` to set the page size and the `starting_after` or `ending_before` cursors to move between pages. The `Link` response header contains the URL of the next page. To narrow the results to a date range, use the `since` and `until` filters on the creation date. Available for organizations on API version `2026-02-01` or later. # The Payment Intent object Source: https://docs.fintoc.com/api/payments-api/payment-intents/payment-intents-object Attributes of the `PaymentIntent` object, a single payment from your customer, and the nested Recipient Account, Sender Account, and Business Profile objects. The `PaymentIntent` object represents a single payment from your customer to your account. The `payment_type` field identifies the payment method, such as `bank_transfer`, `card`, `installment`, or `cash`. The object appears when you create a payment, as the `payment_resource` of a `CheckoutSession` after your customer pays, and in payment webhook events. The `status` field tracks the payment from creation to completion. The following table describes the `PaymentIntent` attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the Payment Intent. | | `object` | `string` | Type of the object. Always `payment_intent`. | | `amount` | `integer` | Amount to pay, in the smallest unit of `currency`. Must be greater than `0`. `CLP` has no minor unit, so `5000` means `$5000 CLP`. For `MXN`, `5000` means `$50.00 MXN`. | | `business_profile` | `object` or `null` | Business that receives the payment when you collect it on behalf of a sub-merchant. `null` when not provided. See the [Business Profile object](#the-business-profile-object-within-the-payment-intent-object) below. | | `created_at` | `string` | ISO 8601 timestamp of when the Payment Intent was created, in UTC. | | `currency` | `string` | Three-letter ISO 4217 currency code, in uppercase. One of `CLP` or `MXN`. | | `customer` | `object` or `null` | [`Customer`](/api/payments-api/customers/customer-object) associated with the Payment Intent. `null` when no customer is attached. | | `customer_email` | `string` or `null` | Your customer's email address, used for refund notifications. `null` when not provided. Fintoc does not send refund emails without `customer_email`. | | `error_reason` | `string` or `null` | Error code explaining why the Payment Intent failed. `null` when the payment has not failed. See [Payment Intent Error Reason](/api/payments-api/payment-intents/payment-intent-error-reason) for the list of error reasons. | | `expires_at` | `string` or `null` | ISO 8601 timestamp of when the Payment Intent expires, in UTC. `null` when the Payment Intent does not expire. | | `invoices` | `array` of `strings` | Unique identifiers of the [invoices](/api/payments-api/invoices/invoice-object) the Payment Intent pays. Empty when the Payment Intent pays no invoice. | | `metadata` | `object` | Set of [key-value](/api/fintoc-api/metadata) pairs you can attach to the Payment Intent. Use these pairs to store additional structured information. | | `mode` | `string` | Environment that produced the object. `live` uses real institution data; `test` uses fake data for integration testing. | | `next_action` | `object` or `null` | Action your customer must complete for the payment to continue, such as confirmation in a banking app. The `type` key identifies the action. `null` when no action is pending. | | `payment_method` | `string` or `null` | Unique identifier of the saved payment method that paid the Payment Intent. `null` when no saved payment method paid the Payment Intent. | | `payment_type` | `string` | Payment method that produced this Payment Intent. One of `bank_transfer`, `cash`, `card`, `installment`, `pac` (automatic recurring bank debit in Chile), or `mx_direct_debit` (direct debit in Mexico). A provider-specific external redirect identifier, such as `banco_estado`, is also possible. | | `payment_type_options` | `object` | Additional options specific to `payment_type`. Empty object when `payment_type` has no extra options. | | `recipient_account` | `object` or `null` | Account that receives the payment. `null` when `payment_type` is not `bank_transfer`. See [The Recipient Account object and the Sender Account object](#the-recipient-account-object-and-the-sender-account-object-within-the-payment-intent-object) below. | | `reference_id` | `string` or `null` | Operation number from the bank of the sender account. `null` while the bank is confirming the payment or when your customer abandons the payment before receiving an operation number. | | `sender_account` | `object` or `null` | Account that sends the payment. `null` when `payment_type` is not `bank_transfer`. Also `null` when your customer abandons the payment before choosing a sender account. See [The Recipient Account object and the Sender Account object](#the-recipient-account-object-and-the-sender-account-object-within-the-payment-intent-object) below. | | `status` | `string` | Payment status. Possible values are `created` (not started), `in_progress` (processing), `succeeded` (completed), and `failed` (not completed). The status can also be `pending` (awaiting confirmation), `requires_action` (awaiting the action in `next_action`), `expired` (expired before completion), or `rejected` (rejected). | | `transaction_date` | `string` or `null` | ISO 8601 timestamp of when the bank authorized the transaction, in UTC. `null` when your customer abandoned the payment before transferring. | | `widget_token` | `string` or `null` | Temporary token used to configure the widget. The API returns this token only when you create the Payment Intent; the value is `null` afterward. | The following example shows a `PaymentIntent` object: ```json Payment Intent Object theme={null} { "id": "pi_BO381oEATXonG6bj", "object": "payment_intent", "amount": 1000, "business_profile": { "category": "009613", "name": "Test Business 1", "tax_id": "000000000" }, "created_at": "2021-10-15T15:23:11.474Z", "currency": "CLP", "customer": null, "customer_email": "customer@example.com", "error_reason": null, "expires_at": null, "invoices": [], "metadata": {}, "mode": "live", "next_action": null, "payment_method": null, "payment_type": "bank_transfer", "payment_type_options": {}, "recipient_account": { "holder_id": "000000001", "institution_id": "cl_banco_de_chile", "number": "000000", "type": "checking_account" }, "reference_id": "90123712", "sender_account": { "holder_id": "000000002", "institution_id": "cl_banco_estado", "number": "000000", "type": "checking_account" }, "status": "created", "transaction_date": "2021-10-15T15:24:15.474Z", "widget_token": "pi_BO381oEATXonG6bj_sec_a4xK32BanKWYn" } ``` ## The Recipient Account object and the Sender Account object (within the Payment Intent object) These objects describe the bank accounts on each side of a transfer. The `recipient_account` field contains the account that receives the funds. The `sender_account` field contains your customer's account. These fields apply only when `payment_type` is `bank_transfer`; otherwise, both fields are `null`. The following table describes both account objects: | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Account owner's tax ID. In Chile, this value is a Chilean tax ID (RUT). In Mexico, this value is a Mexican tax ID (RFC) or Unique Population Registry Code (CURP). | | `institution_id` | `string` | Institution `id` for the account. See [Payment initiation countries and institutions](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions) for available institutions and their `id` values. | | `number` | `string` | Account number. Does not include hyphens or prefixed zeros. | | `type` | `string` | Classification of the bank account. One of `checking_account` or `sight_account`. | ## The Business Profile object (within the Payment Intent object) The `business_profile` field describes the business that receives the payment when you collect it on behalf of a sub-merchant. The following table describes the `business_profile` attributes: | Attribute | Type | Description | | :- | :- | :- | | `category` | `string` | Category identifier for the sub-merchant. In Chile, this value is a six-character [tax activity code](https://www.sii.cl/ayudas/ayudas_por_servicios/1956-codigos-1959.html). | | `name` | `string` | Enrolled merchant's name. Fintoc shows this value as the "Recipient" on the succeeded payment screen when you provide a name. | | `tax_id` | `string` | Enrolled merchant's tax ID. In Chile, it is a Chilean tax ID (RUT). In Mexico, it is a Mexican tax ID (RFC) or Unique Population Registry Code (CURP). | # Add logic to Account Numbers Source: https://docs.fintoc.com/guides/business-accounts/inbound-transfers/add-logic-to-clabes Disable a Fintoc Account Number so it stops accepting inbound transfers, and set minimum and maximum amount limits on Mexican Account Numbers. Assign an Account Number to a user's payments, or create a single-use Account Number for a payment order. Use this guide to disable an Account Number and to set minimum and maximum amount limits. These controls let Fintoc reject unwanted inbound transfers. The two controls differ in where they apply: * **Disabling an Account Number** works in Chile and Mexico. * **Amount limits** apply to Mexican Account Numbers, which use the standardized Mexican bank account number (CLABE) format. ## Disable an Account Number When you disable an Account Number, Fintoc rejects every inbound transfer to that Account Number and returns the transfer to the sender. Disable an Account Number when it should no longer receive payments. ### Example use cases * Your company assigns one Account Number per user. When a user completes offboarding from your app, disable the user's Account Number. Fintoc then returns payments sent to that Account Number. * Your company assigns one Account Number per order. After a customer pays, disable the order's Account Number to avoid accepting a duplicate payment. If the customer pays twice, Fintoc returns the second payment. ### Disable an Account Number with the API Send a `PATCH` request with `status` set to `disabled`. The API returns the updated Account Number: ```bash cURL theme={null} curl --request PATCH \ --url https://api.fintoc.com/v2/account_numbers/acno_test_a1b2c3d4e5f6 \ --header 'Authorization: sk_test_jKaHdEa3mfmP0D105H' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "status": "disabled" } ' ``` ```javascript Node theme={null} const accountNumber = await fintoc.v2.accountNumbers.update( "acno_test_a1b2c3d4e5f6", { status: "disabled" } ); ``` ```python Python theme={null} account_number = client.v2.account_numbers.update( "acno_test_a1b2c3d4e5f6", status="disabled" ) ``` ```json Response theme={null} { "id": "acno_test_a1b2c3d4e5f6", "object": "account_number", "account_id": "acc_test_b2c3d4e5f6g7", "created_at": "2026-06-22T12:00:00.000Z", "deleted_at": null, "description": "My payins", "is_root": false, "last_transfer_at": null, "metadata": {}, "mode": "test", "number": "000000000000000000", "options": null, "status": "disabled", "updated_at": "2026-06-22T12:00:00.000Z" } ``` ## Set inbound transfer amount limits Amount limits are available for Mexican Account Numbers. You can restrict which inbound transfers an Account Number accepts. If a transfer does not meet your criteria, Fintoc rejects the transfer. Rejected transfers do not appear on your account statements or incur fees. Set `min_amount` and `max_amount` in the smallest currency unit. For example, `30000` represents 300.00 MXN. Fintoc supports three kinds of amount limits: | Limit | Description | | :- | :- | | Minimum amount | Set `min_amount` to reject any transfer with an amount lower than this value. | | Maximum amount | Set `max_amount` to reject any transfer with an amount higher than this value. | | Exact amount | Set both `min_amount` and `max_amount` to the same value to reject any transfer that does not match that specific amount. | ### Set limits with the API Create the Account Number with `options`. The API returns the new Account Number with the amount limits under `options`: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/account_numbers \ --header 'Authorization: sk_test_jKaHdEa3mfmP0D105H' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_id": "acc_test_b2c3d4e5f6g7", "options": { "min_amount": 30000, "max_amount": 40000 } } ' ``` ```javascript Node theme={null} const accountNumber = await fintoc.v2.accountNumbers.create({ account_id: "acc_test_b2c3d4e5f6g7", options: { min_amount: 30000, max_amount: 40000, }, }); ``` ```python Python theme={null} account_number = client.v2.account_numbers.create( account_id="acc_test_b2c3d4e5f6g7", options={ "min_amount": 30000, "max_amount": 40000, }, ) ``` ```json Response theme={null} { "id": "acno_test_a1b2c3d4e5f6", "object": "account_number", "account_id": "acc_test_b2c3d4e5f6g7", "created_at": "2026-06-22T12:00:00.000Z", "deleted_at": null, "description": "My payins", "is_root": false, "last_transfer_at": null, "metadata": {}, "mode": "test", "number": "000000000000000000", "options": { "max_amount": 40000, "min_amount": 30000 }, "status": "enabled", "updated_at": "2026-06-22T12:00:00.000Z" } ``` ## Test the integration Confirm the disabled status and amount-limit behavior in `test` mode before going live. Use a `test` secret API key (`sk_test_...`) and a test Account Number. To test a disabled Account Number, disable the Account Number with the request above. Then simulate an inbound transfer to the disabled Account Number's `number`. Fintoc rejects the transfer and returns it to the sender. The transfer does not appear on your account statement or incur a fee. To test amount limits, create an Account Number with `min_amount` set to `30000` and `max_amount` set to `40000`. Then simulate two inbound transfers: * A transfer of `35000` (350.00 MXN) falls within the limits, so Fintoc accepts the transfer. * A transfer of `20000` (200.00 MXN) falls below `min_amount`, so Fintoc rejects the transfer and returns it to the sender. Use the [Simulate receiving a transfer](/api/business-accounts-api/simulation/transfers-simulate-receive) endpoint to simulate inbound transfers in `test` mode. # Receive transfers Source: https://docs.fintoc.com/guides/business-accounts/inbound-transfers/index Receive real-time inbound transfers with Fintoc Account Numbers to automatically track and reconcile incoming payments against orders, invoices, or users. Complete the [Business Accounts setup guide](/guides/business-accounts/setup) first. Then follow these steps to receive inbound transfers in Chile or Mexico: 1. Use your secret key to create an Account Number. 2. Create a webhook endpoint to handle inbound transfer events. 3. Receive a transfer at the Account Number and handle the webhook notification. The following diagram shows how Fintoc interacts with you and the counterparty that sends the inbound transfer. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/bfbff3c18083033f40b375c994f212d521f733b6f8ead999e479c8a2604ac88c-image.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=5e6b057bacb1157147a60297c8cb0f9f) ## Step 1: Create an Account Number An Account Number is the string of digits a sender uses to pay you. Fintoc generates the digits for you in both countries: * In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). Senders reach it over the Sistema de Pagos Electrónicos Interbancarios rail. * In Chile, an Account Number is a bank account number on your Cuenta con Provisión de Fondos (CPF). Senders reach it over the Centro de Compensación Automatizado rail and select Fintoc as the destination institution. Assign the Account Number to a customer or order to reconcile your incoming payments. Assign one Account Number per customer. A transfer to that Account Number then identifies the customer who sent the transfer. To learn more, see the Account Number [data model](/guides/business-accounts/overview/account-number-data-model). ### Attach arbitrary key-value data to your Account Number When you create an Account Number, attach arbitrary key-value data to the [`metadata`](/api/fintoc-api/metadata) object. Use `metadata` to store a unique identifier, such as your internal customer ID. Fintoc includes the `metadata` object with each inbound transfer so you can reconcile the transfer against your internal records. ### Example Using your test secret key and your account ID, create an `AccountNumber` from your backend, attaching an internal customer ID `id_cliente`: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/account_numbers \ --header 'Authorization: sk_test_9c8d8CeyBTx1VcJzuDgpm4H' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_id": "acc_Lq7dP901xZgA2B", "metadata": { "id_cliente": "12343212" } } ' ``` ```javascript Node theme={null} const accountNumber = await fintoc.v2.accountNumbers.create({ account_id: 'acc_Lq7dP901xZgA2B', metadata: { id_cliente: '12343212', }, }); ``` ```python Python theme={null} account_number = client.v2.account_numbers.create( account_id="acc_Lq7dP901xZgA2B", metadata={"id_cliente": "12343212"} ) ``` ```json Response theme={null} { "id": "acno_Kasf91034gj1AD", "object": "account_number", "description": "My payins", "number": "111111111111111111", "account_id": "acc_Lq7dP901xZgA2B", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } } ``` > [!NOTE] > > **Inbound amount limits are available in Mexico only** > > `options.min_amount` and `options.max_amount` reject transfers outside a range. Fintoc applies these limits to Mexican Account Numbers. See [Add logic to Account Numbers](/guides/business-accounts/inbound-transfers/add-logic-to-clabes). ## Step 2: Create a webhook endpoint to handle inbound transfer events Fintoc sends a `transfer.inbound.succeeded` event whenever you receive an inbound transfer. Follow the [webhook guide](/guides/resources/webhooks-walkthrough) to create an endpoint that receives these events and runs actions. Subscribe your endpoint to all inbound transfer events so you can update your records when a transfer changes after it arrives: | Event | Description | | - | - | | `transfer.inbound.succeeded` | Sent when your account receives an inbound transfer. | | `transfer.inbound.returned` | Sent when you [return an inbound transfer](/guides/business-accounts/inbound-transfers/returning-an-inbound-transfer) to its sender. | | `transfer.inbound.return_failed` | 🇲🇽 Sent when a return you requested cannot be completed. The transfer goes back to `succeeded` and the funds stay in your account. | | `transfer.inbound.rejected` | 🇨🇱 Sent when an inbound transfer is rejected before reaching your account. | | `transfer.inbound.reversed` | 🇨🇱 Sent when an inbound transfer your account already received is reversed and the funds leave your account. | The event carries the same structure in both countries. The `counterparty` block and the fields the local rail fills in differ: ```json Mexico theme={null} { "id": "evt_a4xK32BanKWYn", "type": "transfer.inbound.succeeded", "object": "event", "data": { "id": "tr_jKaHD105H", "object": "transfer", "direction": "inbound", "status": "succeeded", "amount": 2864, "currency": "MXN", "mode": "test", "post_date": "2020-04-17T00:00:00.000Z", "transaction_date": "2020-04-17T05:12:41.462Z", "comment": "Electricity bill", "reference_id": "130824", "receipt_url": "https://www.banxico.org.mx/cep/", "tracking_key": "s2123423423324334", "return_reason": null, "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Lq7dP901xZgA2B", "description": "My payins", "number": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "account_number": "000000000000000000", "account_type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } }, "created_at": "2020-04-22T21:10:19.254Z", "mode": "test" } ``` ```json Chile theme={null} { "id": "evt_a4xK32BanKWYn", "type": "transfer.inbound.succeeded", "object": "event", "data": { "id": "tr_jKaHD105H", "object": "transfer", "direction": "inbound", "status": "succeeded", "amount": 2864, "currency": "CLP", "mode": "test", "post_date": "2020-04-17T00:00:00.000Z", "transaction_date": "2020-04-17T05:12:41.462Z", "comment": "Electricity bill", "reference_id": null, "receipt_url": null, "tracking_key": null, "return_reason": null, "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Lq7dP901xZgA2B", "description": "My payins", "number": "000000001", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "000000000", "account_type": "checking_account", "institution": { "id": "cl_banco_santander", "name": "Banco Santander", "country": "cl" } } }, "created_at": "2020-04-22T21:10:19.254Z", "mode": "test" } ``` In Mexico, the Sistema de Pagos Electrónicos Interbancarios fills in `reference_id`, `tracking_key`, and a `receipt_url` that points to the Comprobante Electrónico de Pago. In Chile, those three fields are `null`, and `counterparty.holder_id` carries the sender's Chilean tax ID (RUT). ## Step 3: Receive a transfer at the Account Number After you create an Account Number and add a webhook endpoint, you can receive transfers and reconcile your payments. ### Test the integration In `test` mode, use the `/v2/simulate/receive_transfer` endpoint to simulate an inbound transfer. The simulated transfer behaves like a real transfer sent to the same Account Number. Pass your test secret key and the `account_number_id` you created. Also pass an `amount` in the smallest currency unit and an uppercase ISO 4217 `currency` code: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/simulate/receive_transfer \ --header 'Authorization: sk_test_9c8d8CeyBTx1VcJzuDgpm4H' \ -d account_number_id=acno_Kasf91034gj1AD \ -d amount=2864 \ -d currency=MXN ``` ```javascript Node theme={null} const transfer = await fintoc.v2.simulate.receiveTransfer({ account_number_id: 'acno_Kasf91034gj1AD', amount: 2864, currency: 'MXN', }); ``` ```python Python theme={null} transfer = client.v2.simulate.receive_transfer( account_number_id="acno_Kasf91034gj1AD", amount=2864, currency="MXN", ) ``` ```json Response theme={null} { "id": "tr_jKaHD105H", "object": "transfer", "direction": "inbound", "status": "succeeded", "amount": 2864, "currency": "MXN", "mode": "test", "post_date": "2020-04-17T00:00:00.000Z", "transaction_date": "2020-04-17T05:12:41.462Z", "comment": "Electricity bill", "reference_id": "130824", "receipt_url": "https://www.banxico.org.mx/cep/", "tracking_key": "s2123423423324334", "return_reason": null, "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Lq7dP901xZgA2B", "description": "My payins", "number": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "account_number": "000000000000000000", "account_type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } } ``` To simulate a Chilean inbound transfer, set `currency` to `CLP` and describe the sender with these optional parameters: | Parameter | Description | | :- | :- | | `counterparty_account_number` | Bank account number of the simulated sender. Defaults to a Fintoc test counterparty. | | `counterparty_account_type` | Type of the simulated sender account. One of `checking_account` or `sight_account`. | | `counterparty_holder_id` | Chilean tax ID (RUT) of the simulated sender. | | `counterparty_holder_name` | Name of the simulated sender account holder. | | `counterparty_institution_id` | Institution of the simulated sender, such as `cl_banco_santander`. See [Chilean institution codes](/api/fintoc-api/chile-institution-codes). | The endpoint settles the transfer and delivers a `transfer.inbound.succeeded` event to your webhook endpoint. The event contains the payload shown in Step 2. Receiving the `transfer.inbound.succeeded` event confirms your integration is working. For the full set of test values, see [Test your integration](/guides/business-accounts/setup/test-your-integration). # Manage your Account Numbers Source: https://docs.fintoc.com/guides/business-accounts/inbound-transfers/manage-your-clabes Identify and delete inactive Fintoc Account Numbers in Mexico so your organization keeps room in its quota as your integration grows. > [!NOTE] > > **Deleting an Account Number is available in Mexico only** > > You can disable an Account Number in Chile and Mexico. See [Add logic to Account Numbers](/guides/business-accounts/inbound-transfers/add-logic-to-clabes). Identify and delete inactive Account Numbers to free quota as your integration grows. ## Check your Account Number usage Your organization has a quota of 1,000,000 Account Numbers by default. In Mexico, an Account Number is a standardized Mexican bank account number (CLABE). Every active Account Number occupies one slot, whether it receives payments or not. Deleting an Account Number frees its slot immediately. ## Find inactive Account Numbers Every Account Number tracks the timestamp of its last inbound transfer in the `last_transfer_at` field. An Account Number that has never received a transfer has `last_transfer_at` set to `null`. Use the `no_transfers_since` filter on `GET /v2/account_numbers` to find Account Numbers with no transfer activity since a given date. The filter returns Account Numbers that have never received a transfer or received their last transfer before the given date. ```bash cURL theme={null} curl --request GET \ --url 'https://api.fintoc.com/v2/account_numbers?no_transfers_since=2025-12-01' \ --header 'Authorization: sk_test_jKaHdEa3mfmP0D105H' \ --header 'accept: application/json' ``` ```javascript Node theme={null} const accountNumbers = await fintoc.v2.accountNumbers.list({ no_transfers_since: "2025-12-01", }); ``` ```python Python theme={null} account_numbers = client.v2.account_numbers.list( no_transfers_since="2025-12-01" ) ``` ```json Response theme={null} [ { "id": "acno_test_a1b2c3d4e5f6", "object": "account_number", "number": "000000000000000000", "is_root": false, "last_transfer_at": null } ] ``` ## Delete an Account Number Permanently delete an Account Number you no longer need with `DELETE /v2/account_numbers/{id}`. Unlike disabling an Account Number, deletion cannot be undone. Deleting an Account Number starts a cooldown period during which no organization can use or reassign the Account Number. After the cooldown period, Fintoc may reassign the Account Number to a different organization when that organization creates a new Account Number. You cannot delete root Account Numbers (`is_root: true`) or blocked Account Numbers. ```bash cURL theme={null} curl --request DELETE \ --url https://api.fintoc.com/v2/account_numbers/acno_test_a1b2c3d4e5f6 \ --header 'Authorization: sk_test_jKaHdEa3mfmP0D105H' \ --header 'accept: application/json' ``` ```javascript Node theme={null} await fintoc.v2.accountNumbers.delete("acno_test_a1b2c3d4e5f6"); ``` ```python Python theme={null} client.v2.account_numbers.delete("acno_test_a1b2c3d4e5f6") ``` ```json Response theme={null} { "id": "acno_test_a1b2c3d4e5f6", "object": "account_number", "number": "000000000000000000", "is_root": false, "status": "deleted" } ``` ### What happens after deletion Deleting an Account Number triggers four changes: 1. Fintoc rejects inbound transfers. Fintoc returns payments sent to the deleted Account Number to the sender over Mexico's Sistema de Pagos Electrónicos Interbancarios (SPEI) rail. 2. Deletion frees quota. Your organization's Account Number count decreases, so you can create new Account Numbers. 3. Fintoc recycles the Account Number. After a cooldown period, Fintoc adds the Account Number to a pool and may reassign the Account Number to any account, including accounts that belong to other organizations. 4. Fintoc sends the `account_number.deleted` event to your configured webhook endpoints. ### Disable vs delete Both actions stop inbound transfers, but they differ in whether you can reverse them and whether they free the Account Number and its quota: | Behavior | Disable | Delete | | - | - | - | | **Reversible** | Yes | No | | **Inbound transfers** | Rejected | Rejected | | **Frees Account Number for reuse** | No, Account Number stays reserved | Yes | | **Frees Account Number quota** | No | Yes | To temporarily stop receiving transfers on an Account Number, [disable the Account Number](/guides/business-accounts/inbound-transfers/add-logic-to-clabes) instead. ## Test the integration Confirm the full flow in `test` mode before deleting any Account Number in `live` mode: 1. Create a test Account Number, or choose an existing one with `last_transfer_at` set to `null`. 2. Send the `DELETE /v2/account_numbers/{id}` request with your `sk_test_` key and confirm the response returns the Account Number with `"status": "deleted"`. 3. Confirm the `account_number.deleted` event arrives at your configured webhook endpoint. # Return a transfer Source: https://docs.fintoc.com/guides/business-accounts/inbound-transfers/returning-an-inbound-transfer Automatically return an inbound transfer to the sender when it doesn't match your business rules, using the Fintoc Business Accounts API and webhook events. > [!NOTE] > > **Available in Mexico and Chile** By the end of this guide, you can return an inbound transfer and handle the webhook events that report the result. Use the [return transfer endpoint](/api/business-accounts-api/transfers/transfers-return) up to 90 days after the original inbound transfer. Base the return on your business logic. For example, return a transfer when you expect a specific amount but receive a different one. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/e981759580e31e9b1bd63de2c1d7b25900ca1eab7dd8c749518d1024c7526241-image.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=75842010be852d338adab065c90b86f3) ## Trigger the return Call the [return transfer endpoint](/api/business-accounts-api/transfers/transfers-return) with the `transfer_id` and [`Fintoc-JWS-Signature`](/guides/business-accounts/setup/setting-up-jws-keys) header. The header contains a JSON Web Signature (JWS) for the request: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/transfers/return \ --header 'Authorization: sk_test_9c8d8CeyBTx1VcJzuDgpm4H-bywJCeSx' \ --header 'Fintoc-JWS-Signature: CNMaYaDGU3ZhFV1ve6p3sAdYXhEklej8DVIAMqIWCkpNmT6Jp7iigcndXwH5q3WQFHiswgIQU5-_-4rV3jKGptCROmEyWPW8_elhYH1apzAyjOjyZ55ygv37xKHzIFhixzAwmXlAv4pfD4lVelYWVNOSN7REA0QJeCy2vKdqZ5cjqCXQ1lkQUlzOE7dpuNoAkhAhAJJ8HaamFKy7Gl7uwmqbIr-dVYv21d_9O7mO26n0gy3zWXD2nJDxU5Mzl2pZd8-sFvUr9Kmp_YkeRMh4bSe0fr1Uc_YgkjpmYUyu7kaxRWTbAdJ3GwqWFMUDiyfhHdzvZPZyU4VkWreimoydMA' \ --header 'Idempotency-Key: 1ebfd86c-a75b-4606-872f-9f1cdd9724ca' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "transfer_id": "tr_2wlt3xRBaEstTGPezqIGXy6JUU8" } ' ``` ```javascript Node theme={null} const transfer = await fintoc.v2.transfers.return({ transfer_id: "tr_2wlt3xRBaEstTGPezqIGXy6JUU8", }); ``` ```python Python theme={null} transfer = client.v2.transfers.return_( transfer_id="tr_2wlt3xRBaEstTGPezqIGXy6JUU8" ) ``` ```json Response theme={null} { "id": "tr_2wlt3xRBaEstTGPezqIGXy6JUU8", "object": "transfer", "direction": "inbound", "status": "return_pending", "amount": 100000, "currency": "MXN", "mode": "test", "post_date": "2020-04-17T00:00:00.000Z", "transaction_date": "2020-04-17T05:12:41.462Z", "comment": "Electricity bill", "reference_id": "130824", "receipt_url": "https://api.fintoc.com/v2/transfers/tr_2wlt3xRBaEstTGPezqIGXy6JUU8/receipt", "tracking_key": "s2123423423324334", "return_reason": null, "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Lq7dP901xZgA2B", "description": "My payins", "number": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "account_number": "000000000000000000", "account_type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } } ``` You can only return a transfer in the `succeeded` status. If the transfer has another status, Fintoc responds with a `409 Conflict` status and the `invalid_transfer_status` error code. ### Returns in Chile In Chile, you can return an inbound transfer as soon as it reaches the `succeeded` status if the sender's account is also at Fintoc. If the transfer comes from another bank, wait 90 seconds after the transfer reaches `succeeded` before you return it. If you call the endpoint earlier, Fintoc responds with the same `409 Conflict` status and `invalid_transfer_status` error code, and the error `message` says that Fintoc received the transfer too recently. Retry the request after the 90-second window. ## Return a transfer from the Dashboard You can also return an inbound transfer from the Fintoc Dashboard: 1. Go to the transfers list and find the inbound transfer with the `succeeded` status. 2. Open the transfer's options menu and select **Return**. 3. Review the amount and the recipient account. The Dashboard shows the standardized Mexican bank account number (CLABE) for Mexican transfers and the account number for Chilean transfers. 4. Select **Confirm return** and enter the 6-digit code from your authenticator app. A return from the Dashboard follows the same approval flow as a [manual transfer](/guides/business-accounts/overview/transfer-data-model#authorize-manual-transfers-in-the-dashboard). If you have Authorize permission with 100% for the account, Fintoc processes the return right away. Otherwise, the Dashboard shows **This return requires approval**. People with Authorize permission must approve the return in **Authorizations** within 72 hours, until the combined approvals reach 100%. This approval flow doesn't apply to returns you request with the API. The **Return** option only appears if you have permission to return transfers and Fintoc allows the return for that transfer. For Chilean transfers from another bank, reload the transfer after the 90-second window to see the option. ## Handle the return result Handle the following webhook events to track the outcome of a return: | Event | Description | | :- | :- | | `transfer.inbound.returned` | Fintoc returned the transfer. In Mexico, the `receipt_url` shows the original Comprobante Electrónico de Pago with the status `Devuelta`. | | `transfer.inbound.return_failed` | Fintoc could not return the transfer. The transfer's `status` changes back to `succeeded`. | ## Test the integration Confirm your integration in `test` mode before going live. Trigger a return for a simulated inbound transfer and check that your webhook handler receives the expected event: * For a successful return, expect the `transfer.inbound.returned` event and a transfer with `status` set to `returned`. * For a failed return, expect the `transfer.inbound.return_failed` event and a transfer with `status` set to `succeeded`. See [Test your integration](/guides/business-accounts/setup/test-your-integration) for the steps to simulate both scenarios. # Get account statements Source: https://docs.fintoc.com/guides/business-accounts/manage-accounts/account-statements List and download monthly PDF account statements for a Fintoc Account through the API or the dashboard, with filters by time period and account ID. Get a monthly PDF that summarizes all movements for an account during a specific period. You can list and download account statements through the API or the dashboard. Fintoc generates account statements for every active account at the beginning of each month. Each statement covers the previous month and follows local regulatory requirements. You do not need to request statement generation. ## List account statements Call the [List account statements endpoint](/api/business-accounts-api/account-statements/account-statements-list) with `account_id`. You can list all statements for the account or filter the statements by time period. ```bash cURL theme={null} curl --request GET \ --url 'https://api.fintoc.com/v2/accounts/acc_3AOIA4Hz09oHLeksYr9pYpBk3NS/account_statements?since=2026-03-01&until=2026-03-31' \ --header 'Authorization: sk_test_14ucwLs17VyE5XKFxMb3x8sHwPeSrGVh6hvVayzoi8Q' \ --header 'accept: application/json' ``` ```javascript Node theme={null} const statements = await fintoc.v2.accounts.accountStatements.list({ account_id: "acc_3AOIA4Hz09oHLeksYr9pYpBk3NS", since: "2026-03-01", until: "2026-03-31", }); ``` ```python Python theme={null} statements = client.v2.accounts.account_statements.list( account_id="acc_3AOIA4Hz09oHLeksYr9pYpBk3NS", since="2026-03-01", until="2026-03-31", ) ``` ```json Response theme={null} [ { "id": "acst_8sFkj2mNpQ4rTvWx6yZ1bC3d", "object": "account_statement", "created_at": "2026-04-01T00:00:00Z", "download_url": "https://files.fintoc.com/account_statements/acst_8sFkj2mNpQ4rTvWx6yZ1bC3d.pdf?signature=000000000000", "end_date": "2026-03-31", "final_balance_cents": 1500000, "initial_balance_cents": 1000000, "start_date": "2026-03-01", "total_credited_cents": 1000000, "total_debited_cents": 500000 } ] ``` ## Download the PDF The `download_url` field contains a signed URL. Make a `GET` request to the URL to download the PDF. If the URL has expired, list the account statements again to get a new URL. The downloaded statement looks like this: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/3102fdb25a14b2d086e46c67902204742d358de9c791d463e9f1aa43494bf15c-Screenshot_2026-04-14_at_6.11.13_PM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=d3bfa45e20f7a77f9b959a0aaeb3ee89) ## Test the integration In `test` mode, list the account statements and open the `download_url` from any item in the response. The signed URL opens the account statement PDF in your browser. If the PDF opens, the integration works end to end. # Create more accounts Source: https://docs.fintoc.com/guides/business-accounts/manage-accounts/creating-more-accounts Create additional Fintoc Accounts under your organization or for a third-party Entity so you can track balances separately across products or clients. Create accounts under your own entity or an entity you open for a client. Each account tracks a separate balance. An entity is the legal account holder. Your organization always has a main entity, and you can also create entities for your clients. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/a496b56e8856980f84c290cad865a13cf8d6ead40ac99f4d993298beffabff81-image.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=f370e6c9bb0ada3a356d276a4ad5eada) ## Account activation An `Account` is `active` as soon as Fintoc creates it. Accounts have no pending state: [`status`](/api/business-accounts-api/accounts/account-object) is `active`, `blocked`, or `closed`. * For your main entity, you can create accounts at any time. * For a new entity, Fintoc creates the entity's main `Account` when Fintoc approves the business verification. Verification takes up to 72 business hours. Until then, the entity has no accounts. ## Create more accounts for your organization's entity Your Fintoc organization starts with one `Account`. You can immediately create more accounts for your main entity. Multiple accounts improve reconciliation because each account keeps a separate balance. ### Use the API Call the [Create account](/api/business-accounts-api/accounts/accounts-create) endpoint with your main entity's `entity_id`. To retrieve the `entity_id`, call the [List entities](/api/business-accounts-api/entities/entities-list) endpoint. You can also create the account from the [Dashboard](https://dashboard.fintoc.com/accounts). ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/accounts \ --header 'Authorization: sk_test_32ExjlGaPrvG2AiNSU2lAmNiXL8' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "entity_id": "ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", "description": "My main account" } ' ``` ```javascript Node theme={null} const account = await fintoc.v2.accounts.create({ entity_id: "ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", description: "My main account" }); ``` ```python Python theme={null} account = client.v2.accounts.create( entity_id="ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", description="My main account", ) ``` ```json Response theme={null} { "id": "acc_32ExjlGaPrvG2AiNSU2lAmNiXL8", "object": "account", "mode": "test", "status": "active", "description": "My main account", "is_root": false, "root_account_number": "000000000000000001", "root_account_number_id": "acno_Kasf91034gj1AD", "available_balance": 0, "currency": "MXN", "entity": { "id": "ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", "holder_id": "AAA010101AAA", "holder_name": "Test Entity 1", "is_root": true } } ``` ## Create accounts for another entity (your clients) > [!NOTE] > > **Available in Chile and Mexico** > > You can create a client `Entity` and its `Account` objects in Chile and Mexico, from the dashboard or through the API. To do it through the API, see [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api). If you manage funds for clients, you can open accounts under each client's legal name. ### Example use case Consider a food delivery platform: * You keep one `Account` under your own entity to collect your platform fees. * You create one `Account` per restaurant under a new entity. When a customer pays, the transfer receipt shows the restaurant's name instead of your platform's name. You manage balances and payouts between your `Account` object and your clients' `Account` objects. ### 1. Create an entity Create the entity from the [Entities](https://dashboard.fintoc.com/entities) section of the Dashboard. Select **Create Entity**, then enter the entity's legal name and tax ID: the Chilean tax ID (RUT) or the Mexican tax ID (RFC). ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d658aaab0a4a5c708b1bdfdea652380b0e569a8cae531fb90bba07b3f21ff1d1-image.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=71d60270d394009ed3614f3a01d4458a) ### 2. Complete business verification Complete the business verification form for your new entity in the Dashboard. Fintoc's compliance team reviews your information within 72 business hours and confirms when the entity is ready to use. ### 3. Start using Business Accounts When Fintoc approves the business verification, Fintoc creates the client `Entity`'s main `Account` and root account number. Retrieve both with the [List accounts](/api/business-accounts-api/accounts/accounts-list) endpoint, filtered by `entity_id`. From there you can: * Create `Transfer` objects from the entity's main `Account`. * Receive transfers at its root account number or generate more account numbers. * Create more `Account` objects under this entity. ## Test the integration In `test` mode, use your test secret key to call the [Create account](/api/business-accounts-api/accounts/accounts-create) endpoint. Set `entity_id` to your main test entity. The response returns an `id` prefixed with `acc_` and a `status` of `active`, which confirms the `Account` is ready to use. # Manage your accounts Source: https://docs.fintoc.com/guides/business-accounts/manage-accounts/index Manage the accounts that hold your transfer balances: create accounts to keep balances separate and retrieve the monthly account statements for each one. Manage the accounts that hold your transfer balances. Create accounts to keep balances separate, and retrieve the monthly account statements for each account. The pages in this section explain both tasks. ## Fund your account In Mexico, you fund an `Account` in `live` mode with a Sistema de Pagos Electrónicos Interbancarios (SPEI) transfer in MXN. Send the transfer to the standardized Mexican bank account number (CLABE) in the account's `root_account_number`. The deposit appears as an inbound transfer. SPEI is the only funding method. The CLABE doesn't accept: * International transfers, including SWIFT wires. * Card payments. To fund your account from outside Mexico, send the money to a Mexican bank account that can receive SWIFT transfers. Then send the funds from that bank account to your Fintoc CLABE by SPEI. > [!NOTE] > > In `test` mode, fund your account with a simulated inbound transfer. See Step 4 of [the quickstart](/guides/business-accounts/quickstart#step-4-fund-your-test-account). ## Download an account certificate In Mexico, you can download an account certificate from the Fintoc Dashboard. The certificate is a PDF that Fintoc issues to show that an account is open and active in the name of its holder. Share it when a customer or partner asks for proof of who owns a CLABE, for example before registering you as a supplier. The certificate shows: * The holder's legal name, Mexican tax ID (RFC), and fiscal address. * The CLABE, the institution in SPEI (`FINTOC (738)`), and the currency (`MXN`). * The issue date. To download it in `live` mode: * **For the account's main CLABE:** open the account's detail and click **Account certificate**. * **For another CLABE of the account:** open the CLABE's detail and click **Download certificate**. Only enabled CLABEs have a certificate. The Dashboard only shows these buttons when Fintoc can issue the certificate. The account must be active, and its holder must have a legal name, RFC, and fiscal address with a postal code on file. If the button doesn't appear or the download fails, contact support to review the account holder's data. # Batch transfers Source: https://docs.fintoc.com/guides/business-accounts/outbound-transfers/batch-transfers Create up to 5,000 outbound transfers in Mexico or Chile from a Dashboard file or one API request, then authorize and track the batch. > [!NOTE] > > **Available in Mexico and Chile** > > You can create batch transfers from the Fintoc Dashboard or with the API. You always authorize them from the Dashboard. > > In Chile, organizations on a legacy Security setup can create batch transfers from the Dashboard in `live` mode only. ## Overview This page explains how to create, authorize, and track up to 5,000 transfers using one Dashboard file or one API request. Use batch transfers for payroll, supplier payouts, or daily client disbursements. ### Key benefits Batch transfers provide these controls: * Upload up to **5,000** transfers in one file. * Validate data automatically. * Review batches before executing them. * Require multifactor authentication before funds move. * Track the progress and outcome of each batch or transfer. *** ## How it works ### 1. Create a batch transfer 1. Go to **Transfers → Batch Transfers** in your Fintoc Dashboard and select **Create**. 2. Assign a **description**, for example `Pagos de octubre`. 3. Download the template for your country: * [Mexico template (MXN)](https://docs.google.com/spreadsheets/d/12jCDW2K69eeZ-Rk-l6c4PQf7eVYKBID-9hBjIeoZPts/edit?usp=sharing) * [Chile template (CLP)](https://storage.googleapis.com/fintoc-assets-prd/dashboard/templates/template_batch_transfers.csv%20-%20cl_cca.csv) ### 2. Fill out the template Each row represents one transfer. The columns depend on your organization's country. #### Mexico Use these fields for each transfer row: | Field | Description | Required | Notes | | - | - | - | - | | `sender_account_number` | Account number that sends the money. | Required | | | `counterparty_holder_id` | Destination account holder's Mexican tax ID (RFC). | Optional | | | `counterparty_name` | Destination account holder's name. | Optional | | | `counterparty_institution_id` | Institution that holds the destination account. | Required if you omit the standardized Mexican bank account number (CLABE) | Use a 5-digit code from [this list](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). | | `counterparty_account_number` | Destination account number, as a CLABE. | Required | | | `amount` | Amount sent to the destination account, in Mexican pesos. | Required | A decimal with `.`. | | `comment` | Free-text note attached to the transfer. | Optional | Up to 40 characters. | | `reference_id` | Numeric reference. | Optional | Up to 7 digits. | | `meta/...` | Custom metadata columns. | Optional | You can add up to 50 metadata columns. For example, `meta/user_name` creates the custom column `user_name`. | #### Chile Use these fields for each transfer row: | Field | Description | Required | Notes | | - | - | - | - | | `sender_account_number` | Fintoc account number that sends the money. | Required | | | `sender_holder_id` | Chilean tax ID (RUT) of the holder of the Fintoc account that sends the money. | Required | Must be a valid RUT. | | `counterparty_holder_id` | Destination account holder's RUT. | Required | Must be a valid RUT. | | `counterparty_name` | Destination account holder's name. | Required | Up to 100 characters. On a legacy Security setup, up to 50 characters. | | `counterparty_institution_id` | Fintoc ID of the institution that holds the destination account. | Required | Use an ID from [Chile institution codes](/api/fintoc-api/chile-institution-codes). | | `counterparty_account_number` | Destination account number. | Required | Digits only. | | `counterparty_account_type` | Destination account type. | Required | One of `CHECKING_ACCOUNT`, `SIGHT_ACCOUNT`, or `SAVINGS_ACCOUNT`. | | `amount` | Amount sent to the destination account, in Chilean pesos. | Required | An integer, for example `130500`. | | `comment` | Free-text note attached to the transfer. | Optional | Up to 40 characters. | | `counterparty_email` | Recipient's email address, used to send the transfer receipt. | Optional | | | `receipt_emails` | Additional email addresses that receive the transfer receipt. | Optional | Separate addresses with `;`. Up to 5 addresses. | | `meta/...` | Custom metadata columns. | Optional | You can add up to 50 metadata columns. For example, `meta/user_name` creates the custom column `user_name`. | For example, a Chile file with one transfer looks like this: ```csv Chile batch file theme={null} sender_account_number,sender_holder_id,counterparty_holder_id,counterparty_name,counterparty_institution_id,counterparty_account_number,counterparty_account_type,amount,comment,counterparty_email,receipt_emails,meta/employee_id 000000000,11111111-1,22222222-2,Test Customer 1,cl_banco_de_chile,00000000000,CHECKING_ACCOUNT,130500,Sueldo octubre,customer@example.com,payroll@example.com;finance@example.com,EMP-001 ``` If a transfer to another bank exceeds the per-operation transfer limit, Fintoc splits the amount into transfers that stay under that limit. The review step shows the resulting number of transfers. ### 3. Upload your file When you upload the file: * Fintoc supports **CSV** files. * Fintoc checks the file format and columns as soon as you upload it. When you select **Continue**, Fintoc validates every row and every sender account before you review the batch. Row errors show the CSV row number and the column to fix. Sender account errors tell you when an account doesn't exist, isn't active, isn't a main account, or doesn't have enough balance. If you see an error, correct your file or fund the account, and upload the file again. Fintoc doesn't let you continue to the review step until the file passes validation. ### 4. Review and confirm Before creating your batch: * Review the **total number of transfers** and **total transfer amount**. * If needed, go back and upload a new file. After you confirm the batch, it appears under **Pending Authorizations**. ### 5. Authorize the batch 1. Go to the **Authorizations** tab and select your batch to open its details. 2. Review the batch one last time. 3. Select one of these irreversible actions: * ✅ **Authorize** (requires multifactor authentication) * ❌ **Reject** ### 6. Execution and tracking Fintoc processes and tracks batches as follows: * The batch moves to `in_progress` after full authorization. * Each transfer appears individually in your **Transfers** view as `pending`, then `succeeded` or `failed`. * If some transfers fail, for example because of insufficient balance, the batch ends as `partially_succeeded`. * Batches expire automatically after two weeks if they remain unauthorized. ## Create a batch with the API Instead of uploading a file, send the transfers of a batch in one request to [Create a transfer batch](/api/business-accounts-api/transfer-batches/transfer-batches-create). The request needs a JSON Web Signature (JWS) in the `Fintoc-JWS-Signature` header, as it does for a single transfer. See [Generate JWS keys](/guides/business-accounts/setup/setting-up-jws-keys). The batch starts in `pending_authorization`. Authorize it from the Dashboard as described in [Authorize the batch](#5-authorize-the-batch). A batch you create in `test` mode waits for you to authorize it from the Dashboard in `test` mode. Track the batch with these tools: * **Webhooks:** Receive a `transfer_batch.*` event each time the batch changes status. See [Types of events](/api/main-resources/events-reference/types-of-events). * **Batch status:** Call [Get a transfer batch](/api/business-accounts-api/transfer-batches/transfer-batches-retrieve) or [List transfer batches](/api/business-accounts-api/transfer-batches/transfer-batches-list). * **Transfers of the batch:** Call [List transfers](/api/business-accounts-api/transfers/transfers-list) with the `transfer_batch_id` query parameter. ## Test the integration Confirm that the batch reaches `succeeded` or `partially_succeeded`. If any transfers appear as `failed` in your **Transfers** view, check the failure reason before retrying the transfers. ## Batch statuses A batch moves through these statuses: | Status | Description | | - | - | | `pending_authorization` | Created, awaiting approval. | | `in_progress` | Authorized and executing. | | `succeeded` | All transfers completed successfully. | | `partially_succeeded` | Some transfers succeeded, some failed. | | `failed` | All transfers failed. | | `rejected` | Rejected by an approver. | | `expired` | Not authorized within two weeks. | # Chilean transfer failure reasons Source: https://docs.fintoc.com/guides/business-accounts/outbound-transfers/failure-reasons What each `error_reason` on a failed Chilean outbound transfer means, and whether to send the payment again later or fix the counterparty details first. When a Chilean outbound transfer reaches the `failed` status, the `Transfer` includes an `error_reason` that explains why. Fintoc sends a `transfer.outbound.failed` webhook with the same `Transfer`. * **Fintoc returns the funds.** Fintoc credits the full `amount` back to your available balance. The recipient does not receive the funds. * **Fintoc does not retry a failed transfer.** To send the payment again, create a new transfer with a new `Idempotency-Key`. Reusing the original key returns the original response. * **`error_reason` is `null` in every other case.** Transfers in any status other than `failed` and all Mexican transfers report `error_reason: null`. * **Split transfers report one reason.** When every part of a [split transfer](/guides/business-accounts/outbound-transfers#large-transfers-in-chile) fails, the `error_reason` comes from the last part that failed. ## Failure reasons The **Action** column tells you whether to send the payment again later or to fix something before you send it again: | `error_reason` | Description | Action | | :- | :- | :- | | `recipient_institution_timeout` | The recipient's bank did not respond in time. | Retry later with a new transfer. | | `recipient_institution_unavailable` | The recipient's bank is unavailable, for example during scheduled maintenance. | Retry later with a new transfer. | | `invalid_recipient_account` | The recipient's bank reports that the account number is invalid. | Fix `counterparty.account_number`, then send a new transfer. | | `recipient_account_not_found` | The account number does not exist at the recipient's bank. | Check `counterparty.account_number` and `counterparty.institution_id`, then send a new transfer. | | `recipient_account_closed` | The recipient's account is closed. | Ask the recipient for another account. | | `invalid_recipient_holder_id` | The recipient's bank reports that the Chilean tax ID (RUT) is invalid. | Fix `counterparty.holder_id`, then send a new transfer. | | `invalid_holder_id_account_relationship` | The RUT does not belong to the holder of the account. | Confirm `counterparty.holder_id` and `counterparty.account_number` with the recipient, then send a new transfer. | | `account_type_not_enabled` | The recipient's account type cannot receive this transfer. | Check `counterparty.account_type`. If it is correct, ask the recipient for another account. | | `recipient_account_disabled_for_tef` | The recipient's account is not enabled to receive electronic funds transfers (TEF). | Ask the recipient to enable transfers with their bank or to give you another account. | | `product_account_not_enabled` | The recipient's account product is not enabled to receive transfers. | Ask the recipient for another account. | | `recipient_account_credit_restricted` | The recipient's account has a restriction that blocks incoming funds. | Ask the recipient to resolve the restriction with their bank or to give you another account. | | `recipient_institution_amount_limit_exceeded` | The amount exceeds the maximum that the recipient's bank accepts. | Send a smaller amount, or ask the recipient for an account at another bank. | | `system_amount_limit_exceeded` | The amount exceeds the maximum that the Chilean low-value payments clearing house (Cámara de Pagos de Bajo Valor) accepts. | Send a smaller amount. | | `unknown` | The recipient's bank or the clearing house returned a reason that does not map to any other value. | Check the counterparty details. If new transfers keep failing with `unknown`, contact Fintoc support with the transfer `id`. | # Send transfers Source: https://docs.fintoc.com/guides/business-accounts/outbound-transfers/index Send real-time outbound transfers with Fintoc's Business Accounts API, over SPEI in Mexico or the Centro de Compensación Automatizado in Chile. Complete the [Business Accounts setup guide](/guides/business-accounts/setup), then follow these steps to send outbound transfers: 1. Configure JSON Web Signature (JWS) signing keys and generate a JWS signature. 2. Add funds to the account's `root_account_number`. 3. Create a transfer from your backend using your secret key and a JWS signature. 4. Monitor transfer status. The following diagram shows how Fintoc interacts with you and the counterparty receiving the payout. ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/9ffbd4557c5c3486887b657a1c7f9651d9d1ea4630453e74b897c8e0a89cd679-image.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=7bc83c462682a768b75853602da128bd) ## Step 1: Configure JWS signing keys and generate a JWS signature Every request to a Fintoc Business Accounts API endpoint requires a JWS signature. JWS digitally signs data to verify its integrity and authenticity. To sign an API request, follow the [JWS signature guide](/guides/business-accounts/setup/setting-up-jws-keys). ## Step 2: Add funds to Fintoc Before creating transfers, deposit funds into your `Account` through its `root_account_number`. The deposit appears as an inbound transfer. To fund an account in `live` mode, see [Fund your account](/guides/business-accounts/manage-accounts#fund-your-account). ## Step 3: Create a transfer After you add funds to your account, create a transfer from your backend. Include your test secret key, JWS signature, origin account, amount, currency, and counterparty. The following examples show successful transfer responses. To test other terminal outcomes, use the table in [Test the integration](#test-the-integration). ### Use an idempotency key Fintoc supports [idempotency](https://en.wikipedia.org/wiki/Idempotence) so you can retry transfers without creating duplicates. Use an idempotency key when creating a transfer. If a connection error occurs, retry the request with the same key. To make an idempotent request, include the `Idempotency-Key` header. See [Idempotent requests](/api/fintoc-api/idempotent-requests) for details. ### Create a transfer for Mexico 🇲🇽 Here is an example that creates a transfer of \$590.13 MXN. The `amount` field is in the smallest currency unit, so \$590.13 is the integer `59013`. A successful request returns the created `Transfer`: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/transfers \ --header 'Authorization: sk_test_9c8d8CeyBTx1VcJzuDgpm4H' \ --header 'Fintoc-JWS-Signature: CNMaYaDGU3ZhFV1ve6p3sAdYXhEklej8DVIAMqIWCkpNmT6Jp7iigcndXwH5q3WQFHiswgIQU5-_-4rV3jKGptCROmEyWPW8_elhYH1apzAyjOjyZ55ygv37xKHzIFhixzAwmXlAv4pfD4lVelYWVNOSN7REA0QJeCy2vKdqZ5cjqCXQ1lkQUlzOE7dpuNoAkhAhAJJ8HaamFKy7Gl7uwmqbIr-dVYv21d_9O7mO26n0gy3zWXD2nJDxU5Mzl2pZd8-sFvUr9Kmp_YkeRMh4bSe0fr1Uc_YgkjpmYUyu7kaxRWTbAdJ3GwqWFMUDiyfhHdzvZPZyU4VkWreimoydMA' \ --header 'Idempotency-Key: 1ebfd86c-a75b-4606-872f-9f1cdd9724ca' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 59013, "currency": "MXN", "account_id": "acc_M8sKf230BgHjD4", "comment": "Pago de credito 10451", "reference_id": "150195", "counterparty": { "account_number": "012000000000000001" }, "metadata": { "customer_id": "12050123" } } ' ``` ```javascript Node theme={null} const transfer = await fintoc.v2.transfers.create({ idempotency_key: '1ebfd86c-a75b-4606-872f-9f1cdd9724ca', amount: 59013, currency: 'MXN', account_id: 'acc_M8sKf230BgHjD4', comment: 'Pago de credito 10451', reference_id: '150195', counterparty: { account_number: '012000000000000001' }, metadata: { customer_id: '12050123' } }); ``` ```python Python theme={null} transfer = client.v2.transfers.create( idempotency_key="1ebfd86c-a75b-4606-872f-9f1cdd9724ca", amount=59013, currency="MXN", account_id="acc_M8sKf230BgHjD4", comment="Pago de credito 10451", reference_id="150195", counterparty={"account_number": "012000000000000001"}, metadata={"customer_id": "12050123"} ) ``` ```json Response theme={null} { "object": "transfer", "id": "tr_jKaHD105H", "amount": 59013, "currency": "MXN", "direction": "outbound", "status": "succeeded", "transaction_date": "2020-04-17T05:12:41.462Z", "post_date": "2020-04-17T00:00:00.000Z", "comment": "Pago de credito 10451", "reference_id": "150195", "tracking_key": "s2123423423324334", "receipt_url": "https://www.banxico.org.mx/cep/", "mode": "test", "return_reason": null, "settled_amount": 59013, "counterparty": { "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "account_number": "012000000000000001", "account_type": "clabe", "institution": { "id": "mx_bbva_mexico", "name": "BBVA Mexico", "country": "mx" } }, "account_number": { "id": "acno_Kasf91034gj1AD", "account_id": "acc_Jas92lf9adg94ka", "number": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "description": null, "metadata": {}, "object": "account_number" }, "metadata": { "customer_id": "12050123" } } ``` > [!WARNING] > > **Currencies are represented as integers** > > For example, Fintoc represents **MXN \$10.29** as `1029`. > > See [Currencies](/guides/home/currencies) for details. > [!NOTE] > > **Add `institution_id` for mobile numbers and debit cards** > > When transferring to a standardized Mexican bank account number (CLABE), you do not need `institution_id`. Fintoc determines the institution from the CLABE. For a **mobile phone number** or **debit card**, include the five-digit `institution_id` from the [Banco de México institution list](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). Otherwise, the API returns a `400 Bad Request` error. In Mexico, the `Counterparty` object requires one attribute: | Parameter | Description | | :- | :- | | `account_number` | The recipient's CLABE, mobile number, or debit card number. | ### Create a transfer for Chile 🇨🇱 Here is an example that creates a transfer of \$1,869 CLP. Because CLP has no minor unit, the `amount` field is the same integer, `1869`. A successful request returns the created `Transfer`: ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/transfers \ --header 'Authorization: sk_test_9c8d8CeyBTx1VcJzuDgpm4H' \ --header 'Fintoc-JWS-Signature: CNMaYaDGU3ZhFV1ve6p3sAdYXhEklej8DVIAMqIWCkpNmT6Jp7iigcndXwH5q3WQFHiswgIQU5-_-4rV3jKGptCROmEyWPW8_elhYH1apzAyjOjyZ55ygv37xKHzIFhixzAwmXlAv4pfD4lVelYWVNOSN7REA0QJeCy2vKdqZ5cjqCXQ1lkQUlzOE7dpuNoAkhAhAJJ8HaamFKy7Gl7uwmqbIr-dVYv21d_9O7mO26n0gy3zWXD2nJDxU5Mzl2pZd8-sFvUr9Kmp_YkeRMh4bSe0fr1Uc_YgkjpmYUyu7kaxRWTbAdJ3GwqWFMUDiyfhHdzvZPZyU4VkWreimoydMA' \ --header 'Idempotency-Key: 1ebfd86c-a75b-4606-872f-9f1cdd9724ca' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "amount": 1869, "currency": "CLP", "account_id": "acc_M8sKf230BgHjD4", "comment": "Pago de credito 10451", "counterparty": { "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "11111111", "account_type": "checking_account", "institution_id": "cl_banco_de_chile" }, "metadata": { "customer_id": "12050123" } } ' ``` ```javascript Node theme={null} const transfer = await fintoc.v2.transfers.create({ idempotency_key: '1ebfd86c-a75b-4606-872f-9f1cdd9724ca', amount: 1869, currency: 'CLP', account_id: 'acc_M8sKf230BgHjD4', comment: 'Pago de credito 10451', counterparty: { holder_id: '11.111.111-1', holder_name: 'Test Customer 1', account_number: '11111111', account_type: 'checking_account', institution_id: 'cl_banco_de_chile' }, metadata: { customer_id: '12050123' } }); ``` ```python Python theme={null} transfer = client.v2.transfers.create( idempotency_key="1ebfd86c-a75b-4606-872f-9f1cdd9724ca", amount=1869, currency="CLP", account_id="acc_M8sKf230BgHjD4", comment="Pago de credito 10451", counterparty={ "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "11111111", "account_type": "checking_account", "institution_id": "cl_banco_de_chile" }, metadata={"customer_id": "12050123"} ) ``` ```json Response theme={null} { "object": "transfer", "id": "tr_jKaHD105H", "amount": 1869, "currency": "CLP", "direction": "outbound", "status": "succeeded", "transaction_date": "2020-04-17T05:12:41.462Z", "post_date": "2020-04-17T00:00:00.000Z", "comment": "Pago de credito 10451", "reference_id": null, "receipt_url": null, "tracking_key": null, "mode": "test", "return_reason": null, "settled_amount": 1869, "counterparty": { "holder_id": "11.111.111-1", "holder_name": "Test Customer 1", "account_number": "11111111", "account_type": "checking_account", "institution": { "id": "cl_banco_de_chile", "name": "Banco de Chile", "country": "cl" } }, "account_number": { "id": "acno_Kasf91034gj1AD", "account_id": "acc_Jas92lf9adg94ka", "number": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "object": "account_number", "description": null, "metadata": {} }, "metadata": { "customer_id": "12050123" } } ``` In Chile, the `Counterparty` object requires five attributes: | Parameter | Description | | :- | :- | | `holder_id` | The account holder's [Chilean tax ID (RUT)](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario). | | `holder_name` | The account holder's full name. | | `account_number` | The recipient's bank account number at the counterparty institution. | | `account_type` | Type of account. Supported types are `checking_account` and `sight_account`. | | `institution_id` | Fintoc institution ID for the bank receiving the transfer. See [Chilean institution codes](/api/fintoc-api/chile-institution-codes). | ### Large transfers in Chile Some Chilean banks cap incoming transfers at \$7,000,000 CLP. To send more, create one transfer for the full amount. Fintoc splits every outbound transfer over \$7,000,000 CLP into parts of up to \$7,000,000 CLP, whatever the counterparty's bank, and sends each part to the counterparty. > [!TIP] > > **Transfers between Fintoc accounts are not split** > > A transfer to another Fintoc account settles immediately for the full amount, with no \$7,000,000 CLP limit. The counterparty receives one transfer and has no parts to reconcile. When your suppliers, customers, or partners also hold Fintoc accounts, every payment between you arrives this way. * **You work with one transfer.** The API returns a single `Transfer` with the full `amount`. Webhooks, the receipt, and the account movement all belong to that transfer. The parts do not appear in the API. * **The counterparty receives one transfer per part.** Every part is \$7,000,000 CLP except the last, which can be smaller. For example, \$15,000,000 CLP arrives as \$7,000,000, \$7,000,000, and \$1,000,000 CLP. * **Each part's comment names its position.** Fintoc appends `X de N` to your `comment` so the counterparty can reconcile the parts. For example, `Factura 1042` becomes `Factura 1042 2 de 3` on the second of three parts. Without a `comment`, the part's comment is only `2 de 3`. To keep each part's comment within 40 characters, Fintoc truncates your `comment` to leave room for the suffix. A transfer split into 2 to 9 parts keeps the first 33 characters. The `comment` on the `Transfer` stays as you sent it. * **Your balance must cover the full amount.** Fintoc holds the full `amount` when you create the transfer. If your balance is lower, the request fails and Fintoc sends no parts. * **Parts go out one after another.** A split transfer stays `pending` longer than a single transfer. The transfer stays `pending` until every part finishes. A part can fail if, for example, the counterparty's bank goes down while Fintoc is still sending the parts. When every part finishes, the transfer reaches one of these statuses: | Parts that settle | Transfer `status` | `settled_amount` | Webhook event | | :- | :- | :- | :- | | All | `succeeded` | Equal to `amount` | `transfer.outbound.succeeded` | | Some | `partially_succeeded` | Sum of the parts that settled | `transfer.outbound.partially_succeeded` | | None | `failed` | `0` | `transfer.outbound.failed` | Fintoc returns the amount of every part that does not settle to your available balance, and does not retry those parts. To send the rest of a `partially_succeeded` transfer, create a new transfer for `amount` minus `settled_amount`. > [!NOTE] > > To receive a notification when a split transfer reaches `partially_succeeded`, [subscribe your webhook endpoint](/guides/resources/webhooks-walkthrough/webhooks-activating) to `transfer.outbound.partially_succeeded`. ## Step 4: Monitor transfer status ### Transfer status flow An outbound transfer's status is one of `pending`, `succeeded`, or `failed`. Mexican transfers can also reach `returned`; Chilean transfers can also reach `partially_succeeded`, `reverse_pending`, and `reversed`. Outbound transfers never report `rejected`. In both countries, a rejected outbound transfer ends as `failed`. For more details on transfer statuses, see the [Transfer data model](/guides/business-accounts/overview/transfer-data-model). ### Monitor status using webhooks Fintoc sends a `transfer.outbound.succeeded` event when the transfer settles. Use the [webhook guide](/guides/resources/webhooks-walkthrough) to receive these events. You can then notify your customer or log the transfer in your ERP. Subscribe your webhook endpoint to these events and handle each one, including `transfer.outbound.partially_succeeded` if you send Chilean transfers over \$7,000,000 CLP: | Event | Description | | - | - | | `transfer.outbound.succeeded` | Sent when the transfer settles successfully. | | `transfer.outbound.partially_succeeded` | 🇨🇱 Sent when only some parts of a [split transfer](#large-transfers-in-chile) settle. | | `transfer.outbound.failed` | Sent when the transfer cannot reach the destination account because of a processing error, a Banco de México rejection, or a recipient institution rejection. The final status is `failed`; for the reason, see the [SPEI rejection causes](/api/business-accounts-api/transfers/spei-codes) in Mexico or `error_reason` and the [Chilean transfer failure reasons](/guides/business-accounts/outbound-transfers/failure-reasons) in Chile. | | `transfer.outbound.returned` | 🇲🇽 Sent when Banco de México or the recipient institution returns a transfer that already settled. | | `transfer.outbound.reversed` | 🇨🇱 Sent when a settled transfer is reversed. | > [!WARNING] > > **Webhooks may arrive out of order** > > For example, a `transfer.outbound.reversed` event can arrive before the same transfer's `transfer.outbound.succeeded` event. In that case, the transfer settled first, and Fintoc reversed it later. The final status is `reversed`, and Fintoc credits the `amount` back to your available balance. > > To get the current status, [retrieve the transfer](/api/business-accounts-api/transfers/transfers-retrieve) instead of relying on the order of events. ## Test the integration Use your test secret key (`sk_test_...`) to run transfers in `test` mode without moving real money. Every response sets `mode` to `test`. In `test` mode, a transfer reaches the same terminal statuses as in production. Predefined inputs do not force an outcome. The outcome depends on how the receiving party resolves the transfer. Use these terminal statuses to confirm your webhook handling: | Outcome | Resulting status | Webhook event | | :- | :- | :- | | Succeeded | `succeeded` | `transfer.outbound.succeeded` | | 🇨🇱 Partially succeeded | `partially_succeeded` | `transfer.outbound.partially_succeeded` | | Failed | `failed` | `transfer.outbound.failed` | | 🇲🇽 Returned | `returned` | `transfer.outbound.returned` | | 🇨🇱 Reversed | `reversed` | `transfer.outbound.reversed` | # Verify Mexican accounts Source: https://docs.fintoc.com/guides/business-accounts/outbound-transfers/verify-clabes Confirm a standardized Mexican bank account number (CLABE), debit card, or mobile phone number with a 0.01 MXN micro-deposit before a full payout, then retrieve the account holder details. Account verification confirms a Mexican destination account identified by a standardized Mexican bank account number (CLABE), a 16-digit debit card number, or a 10-digit mobile phone number. Fintoc sends a 0.01 MXN micro-deposit from your account balance to the destination. When the verification completes, Fintoc returns the account holder's information. ## Create an account verification An account verification creates a 0.01 MXN `Transfer` from your root `Account` to retrieve the target account holder's information. Because this call moves money from your account, you must sign the request with a JSON Web Signature (JWS). See [setting up JWS keys](/guides/business-accounts/setup/setting-up-jws-keys). ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/account_verifications \ --header 'Authorization: YOUR_TEST_SECRET_API_KEY' \ --header 'Fintoc-JWS-Signature: YOUR_JWS_SIGNATURE' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_number": "000000000000000000" } ' ``` ```javascript Node theme={null} const verification = await fintoc.v2.accountVerifications.create({ account_number: '000000000000000000', }); ``` ```python Python theme={null} verification = client.v2.account_verifications.create( account_number="000000000000000000" ) ``` When you request an account verification, the API returns an `account_verification` object with a `pending` status. The `holder_id` and `holder_name` fields are `null` in this initial response. Fintoc populates these fields once the verification succeeds. The response looks like this: ```json theme={null} { "id": "accv_a1b2c3d4e5f6g7h8", "object": "account_verification", "status": "pending", "reason": null, "transfer_id": "tr_a1b2c3d4e5f6g7h8", "counterparty": { "account_number": "000000000000000000", "holder_id": null, "holder_name": null, "account_type": "clabe", "institution": { "id": "mx_banco_bbva", "name": "BBVA Mexico", "country": "mx" } }, "mode": "test", "receipt_url": null, "transaction_date": null } ``` ## Verify a debit card or mobile phone number A CLABE encodes its bank, but a debit card or mobile phone number does not. To verify one, add the bank's five-digit `institution_id` from the [Banco de México institution list](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). If you omit `institution_id`, the API returns a `400 Bad Request` error. ```bash cURL theme={null} curl --request POST \ --url https://api.fintoc.com/v2/account_verifications \ --header 'Authorization: YOUR_TEST_SECRET_API_KEY' \ --header 'Fintoc-JWS-Signature: YOUR_JWS_SIGNATURE' \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --data ' { "account_number": "4111111111111111", "institution_id": "40012" } ' ``` ```javascript Node theme={null} const verification = await fintoc.v2.accountVerifications.create({ account_number: '4111111111111111', institution_id: '40012', }); ``` ```python Python theme={null} verification = client.v2.account_verifications.create( account_number="4111111111111111", institution_id="40012" ) ``` The API returns the same `account_verification` object, with `account_type` set to `debit_card` or `mobile`. The response looks like this: ```json theme={null} { "id": "accv_a1b2c3d4e5f6g7h8", "object": "account_verification", "status": "pending", "reason": null, "transfer_id": "tr_a1b2c3d4e5f6g7h8", "counterparty": { "account_number": "4111111111111111", "holder_id": null, "holder_name": null, "account_type": "debit_card", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } }, "mode": "test", "receipt_url": null, "transaction_date": null } ``` > [!NOTE] > > For card numbers, account verification supports debit cards only, not credit cards. ## Monitor verification status When Fintoc retrieves the transfer and account holder information, it sends an `account_verification.succeeded` webhook. This event includes the account holder's information in an `account_verification` object with a `succeeded` status. The event looks like this: ```json theme={null} { "id": "evt_a4xK32BanKWYn", "type": "account_verification.succeeded", "object": "event", "mode": "test", "created_at": "2020-04-17T00:00:00.000Z", "data": { "id": "accv_a1b2c3d4e5f6g7h8", "object": "account_verification", "status": "succeeded", "reason": null, "transfer_id": "tr_a1b2c3d4e5f6g7h8", "counterparty": { "account_number": "000000000000000000", "holder_id": "000000000", "holder_name": "Test Customer 1", "account_type": "clabe", "institution": { "id": "mx_banco_bbva", "name": "BBVA Mexico", "country": "mx" } }, "mode": "test", "receipt_url": "https://www.banxico.org.mx/cep/", "transaction_date": "2020-04-17T00:00:00.000Z" } } ``` If Fintoc cannot retrieve the information, you receive an `account_verification.failed` webhook with a `reason` field explaining why the verification failed. For more on receiving webhooks with Fintoc, see the [webhooks guide](/guides/resources/webhooks-walkthrough). # Test your integration Source: https://docs.fintoc.com/guides/movements/data-aggregation-test-your-integration Use test credentials to simulate a user connecting a bank account in `test` mode, with individual and company credentials for Chile, before moving to `live` mode. To confirm that your integration works correctly, use test credentials to simulate a user connecting a bank account. Any time you work with a test credential, use test API Keys in all API calls. In test mode you cannot connect real bank accounts. If you try to connect a real account, Fintoc throws an error. Before you move to `live` mode, make sure your business meets the [requirements to use Fintoc](/guides/movements/overview-data-aggregation#who-can-use-fintoc). ## Test credentials ### Chile 🇨🇱 You can use the following test credentials to log in to a bank account: #### Individuals | Username | Password | | :- | :- | | 41614850-3 | jonsnow | | 40427672-7 | jonsnow | | 41579263-8 | jonsnow | #### Companies | Username | Password | | :- | :- | | 45XXXXXX-X | jonsnow | > [!WARNING] > > **About companies account usernames** > > Notice that the account listed above has the **X** character many times. **Do not write X characters** when using the sandbox. Those characters are there to represent that you can use **any valid RUT** when connecting as a company using the sandbox **as long as the RUT is over 45.XXX.XXX-X**. # Document types Source: https://docs.fintoc.com/guides/movements/fiscal-links/document-types The codes the Servicio de Impuestos Internos (SII) assigns to each electronic tax document, and how they map to the `document_type` attribute of an `Invoice`. ## Electronic fiscal documents [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list) returns several kinds of electronic tax documents. Each [Invoice](/api/fiscal-api/fiscal-invoices/fiscal-invoices-object) includes `institution_invoice.document_type`, the code the Servicio de Impuestos Internos (SII) assigns to the document type. The most common codes are: | Document Type | Description | | :- | :- | | 30 | Invoice | | 32 | Sales and services invoice exempt from value-added tax (VAT) | | 33 | Electronic invoice | | 34 | Electronic invoice exempt from VAT | | 35 | Receipt | | 38 | Exempt receipt | | 39 | Electronic receipt | | 40 | Invoice settlement | | 41 | Electronic exempt receipt | | 43 | Electronic invoice settlement | | 45 | Purchase invoice | | 46 | Electronic purchase invoice | | 47 | Total of the month special electronic voucher | | 48 | Electronic payment | | 50 | Dispatch guide | | 52 | Electronic dispatch guide | | 55 | Debit note | | 56 | Electronic debit note | | 60 | Credit note | | 61 | Electronic credit note | | 103 | Settlement | | 110 | Electronic export invoice | | 111 | Electronic export debit note | | 112 | Electronic export credit note | `document_type` is `null` for fee receipts for professional services (boletas de honorarios). The SII does not code fee receipts as electronic tax documents. Identify them with `institution_invoice.is_services_invoice`. See [Electronic tax documents](/guides/movements/fiscal-links/invoices) to learn how to classify each document. # Fiscal Links Source: https://docs.fintoc.com/guides/movements/fiscal-links/index Connect a taxpayer's account at Chile's Servicio de Impuestos Internos (SII) to fetch their invoices, fee receipts, F29 and F22 through the Fiscal API. This page explains what a fiscal `Link` is, which fiscal products Fintoc offers, and which documents from the tax authority each product returns. For field-level details, see the [Invoice object](/api/fiscal-api/fiscal-invoices/fiscal-invoices-object), [Tax statement object](/api/fiscal-api/tax-statements/tax-statements-object), and [Tax return object](/api/fiscal-api/tax-returns/tax-returns-object). ## What a fiscal Link is A fiscal `Link` connects a taxpayer's account at the Servicio de Impuestos Internos (SII), the Chilean tax authority, to Fintoc, the same way a banking `Link` connects a bank account. Your user creates the fiscal `Link` through the [Widget](/guides/resources/widget/web-integration) with the credentials they use at the tax authority. After creating the `Link`, Fintoc sends the `link.created` event to the `webhookUrl` you configured in the Widget. That event includes the `link_token`, which authenticates every Fiscal API request for that `Link`. Save the `link_token` when you receive it, because Fintoc does not store it. The connection flow follows the [Integration Flow](/guides/movements/integration-with-exchange-token) guide for banking `Links`. A fiscal `Link` belongs to one taxpayer, identified by its Chilean tax ID (RUT). The `holder_type` of the `Link` is `individual` for a natural person and `business` for a company. ## Fiscal products Create one fiscal `Link` for each product you need. The product determines which documents Fintoc fetches from the tax authority and which endpoint returns them. To get two kinds of documents from the same taxpayer, for example invoices and tax statements, create two `Links`. | `product` | What Fintoc returns | Source at the SII | Endpoint | | :- | :- | :- | :- | | `invoices` | The electronic tax documents the taxpayer issued or received: invoices, credit and debit notes, dispatch guides, receipt summaries, and fee receipts for professional services. | Registro de Compras y Ventas (purchase and sales registry) and the fee receipts registry. | [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list) | | `tax_statements` | Tax statements: what the taxpayer declared each month in the F29 form, including value-added tax (VAT) and monthly provisional payments. | F29 form. | [List tax statements](/api/fiscal-api/tax-statements/tax-statements-list) | | `tax_returns` | Tax returns: what the taxpayer declared each year in the F22 form, including the refund requested and the account that receives it. | F22 form. | [List tax returns](/api/fiscal-api/tax-returns/tax-returns-list) | Use `invoices` when you reconcile purchases and sales, verify the income of an independent worker through their fee receipts, or need the full activity of a company. Use `tax_statements` for a monthly view of the declared VAT and `tax_returns` for the yearly income declaration. ## Institutions The SII supports these fiscal products: | Institution | `institution_id` | Country | `holder_type` | Products | | :- | :- | :- | :- | :- | | Servicio de Impuestos Internos (SII) | `cl_fiscal_sii` | Chile | `individual`, `business` | `invoices`, `tax_statements`, `tax_returns` | ## Keeping the data up to date Fiscal data changes after the taxpayer connects the `Link`: new documents appear, acknowledgment statuses change, and the taxpayer files new monthly statements. Fintoc keeps each product current in a different way. * **Invoices and fee receipts.** When the `Link` is created, Fintoc fetches the last 12 months of documents. The documents become available after your user connects. Fintoc then refreshes the `Link` periodically with the refresh interval of your plan. Each refresh fetches the documents of the current and the previous month, because the SII can still change a document after the month closes. When a refresh finishes, Fintoc sends the [`link.refresh_intent.succeeded`](/api/main-resources/events-reference/types-of-events) event. If the refresh does not complete, Fintoc sends `link.refresh_intent.failed`. You can also refresh a `Link` created with the `invoices` product on demand with a [Refresh Intent](/guides/movements/refresh-intents-walkthrough/index). * **Tax statements.** Fintoc fetches the filed statements when the `Link` is created and refreshes them periodically with the refresh interval of your plan. * **Tax returns.** Fintoc fetches the filed returns when the `Link` is created. Tax returns aren't refreshed periodically. Use the `updated_since` parameter of [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list) to fetch only the documents that changed since your last sync. ## Next steps > [card] [Electronic tax documents](/guides/movements/fiscal-links/invoices) > > Which documents `invoices` returns and how to classify invoices, notes, receipts, and fee receipts. > [card] [Tax statements](/guides/movements/fiscal-links/tax-statements) > > Monthly F29 declarations and the amounts they include. > [card] [Tax returns](/guides/movements/fiscal-links/tax-returns) > > Annual F22 declarations, declared income, and the refund account. > [card] [Document types](/guides/movements/fiscal-links/document-types) > > SII codes for each electronic tax document. # Electronic tax documents Source: https://docs.fintoc.com/guides/movements/fiscal-links/invoices Which electronic tax documents the `invoices` product returns, how to tell issued from received documents, and how to read the SII registry and acknowledgment. This page explains which electronic tax documents the `invoices` product returns, how to classify each document, and how Fintoc keeps them up to date. For every attribute, see the [Invoice object](/api/fiscal-api/fiscal-invoices/fiscal-invoices-object). ## Which documents you get In Chile, the Servicio de Impuestos Internos (SII) publishes electronic tax documents (Documento Tributario Electrónico, DTE) in the taxpayer's purchase and sales registry (Registro de Compras y Ventas). The registry includes the documents the taxpayer issues or receives. Fee receipts for professional services (boletas de honorarios) live in a separate registry. A `Link` created with the `invoices` product returns every document in the purchase and sales registry: invoices, credit and debit notes, dispatch guides, settlements, export documents, and receipt summaries. It returns both issued and received documents. It also returns the fee receipts the taxpayer issued and received. [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list) and [Get an invoice](/api/fiscal-api/fiscal-invoices/fiscal-invoices-get) return every document as an `Invoice` object, from either registry. ## Issued and received documents The `issue_type` attribute tells you the direction of the document from the point of view of the taxpayer who owns the `Link`. | `issue_type` | Meaning | Counterparty | | :- | :- | :- | | `issued` | The taxpayer issued the document. It is a sale. | `receiver` holds the customer's tax ID and name. `issuer` is `null`. | | `received` | The taxpayer received the document. It is a purchase. | `issuer` holds the supplier's tax ID and name. `receiver` is `null`. | Filter by direction with the `issue_type` parameter of [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list). ## Classify a document The `Invoice` object holds the attributes shared by every document. The `institution_invoice` field holds the detail the SII reports for that type of document: type, statuses, value-added tax (VAT) breakdown, and fee receipt data. Use the following attributes to tell the documents apart. ### Document type `institution_invoice.document_type` is the SII code of the document. For example, `33` is an electronic invoice, `61` is an electronic credit note, and `39` is an electronic receipt. See the full list in [Document types](/guides/movements/fiscal-links/document-types). `document_type` is `null` for fee receipts, which the SII doesn't code as an electronic tax document (DTE). Identify them with `institution_invoice.is_services_invoice`. ### Fee receipts When `institution_invoice.is_services_invoice` is `true`, the document is a fee receipt for professional services. `institution_invoice.services_invoice` then holds the receipt's own data: the withheld amount, whether a third party issued it, and its `status` at the SII. Status values are `VIG` (valid), `ANUL` (annulled), `ObR` (observed), and `VCA` (valid with an annulment request). For any other document, `is_services_invoice` is `false` and `services_invoice` is `null`. ### Summary documents The SII reports some documents as a daily summary instead of one row per document. These are receipts (`35`, `38`, `39`, and `41`), the special monthly voucher (`47`), and electronic payments (`48`). Fintoc returns one `Invoice` per day and document type for them, with the total of the day. For a summary document, `institution_invoice.total_documents` holds the number of documents grouped. The `number`, `issuer`, and `receiver` attributes are `null`, because the summary has no folio and no single counterparty. ### Registry status `institution_invoice.invoice_status` tells you in which tab of the purchase and sales registry the SII reports the document. | `invoice_status` | Meaning | | :- | :- | | `registered` | The document is part of the official registry (the SII's **Registro** tab). | | `pending` | The document was received but awaits acknowledgment from the receiver (the SII's **Pendientes** tab). | Filter by registry status with the `invoice_status` parameter of [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list). ### Acknowledgment status `institution_invoice.confirmation_status` shows the result of the SII's acknowledgment or claim process (acuse de recibo) for a received invoice. The receiver has 8 calendar days to acknowledge or claim the invoice. If the receiver does nothing, the SII acknowledges it automatically. | `confirmation_status` | Meaning | | :- | :- | | `C` | Acknowledged by the receiver within the term. | | `A` | Acknowledged automatically when the term lapsed without a claim. | | `P` | Paid in cash, so no acknowledgment is needed. | | `G` | Acknowledged through the dispatch guides of the previous month. | | `R` | Claimed by the receiver. | | `null` | The SII hasn't recorded an event yet. | `null` is not a rejection and does not make the document invalid. The SII reports `null` in three cases: the document is still inside the 8-day term, the document type skips the acknowledgment process (receipts, credit and debit notes, and dispatch guides), or the document is `issued` and the counterparty has not acted. To know where the document stands, use `invoice_status`, `accepted_at`, and `rejected_at`. ### Other attributes * `institution_invoice.transaction_category` is the classification the taxpayer gives to a received document in the purchase registry, such as `Del Giro` (part of the business activity), `Supermercado`, or `Activo Fijo`. It is `null` when the SII doesn't report it. * `institution_invoice.has_note` is `true` when a credit or debit note references the document. * Amounts (`total_amount`, `net_amount`, `institution_invoice.exempt_amount`, `institution_invoice.vat_amount`, and `institution_invoice.other_taxes`) are integers in CLP, the smallest unit of the currency. ## Filter the list [List invoices](/api/fiscal-api/fiscal-invoices/fiscal-invoices-list) returns the documents sorted by descending `date`, paginated. These parameters narrow the result set. | Parameter | Effect | | :- | :- | | `since`, `until` | Only documents with `date` inside the range. Both are ISO 8601 dates. | | `updated_since` | Only documents that Fintoc created or updated on or after this ISO 8601 datetime with timezone offset, for example `2024-01-01T00:00:00Z`. Use it to sync incrementally. | | `issue_type` | Only `issued` or only `received` documents. | | `invoice_status` | Only `registered` or only `pending` documents. | ## How Fintoc keeps invoices up to date When your user creates the `Link`, Fintoc fetches the documents of the last 12 months. The documents become available after your user connects. Fintoc then refreshes the `Link` periodically with the refresh interval of your plan. Each refresh fetches the documents of the current and the previous month, because the SII can still change a document after the month closes. Fintoc sends the `link.refresh_intent.succeeded` event when a refresh finishes. If the refresh does not complete, Fintoc sends `link.refresh_intent.failed`. See the [events reference](/api/main-resources/events-reference/types-of-events) for the payload. To refresh a `Link` created with the `invoices` product on demand, create a [Refresh Intent](/guides/movements/refresh-intents-walkthrough/index). ## Example A received electronic invoice (`document_type` `33`), already part of the registry: ```json theme={null} { "id": "inv_nMNejK7BT8oGbvO4", "object": "invoice", "currency": "CLP", "date": "2021-06-25T04:00:00.000Z", "institution_id": "cl_fiscal_sii", "institution_invoice": { "accepted_at": "2021-06-26T12:00:00.000Z", "common_use_vat": null, "confirmation_status": "A", "construction_company_credit": 0, "container_deposit_guarantee": 0, "document_type": 33, "domestic_ticket_sales": 0, "exempt_amount": 0, "exempt_commissions": 0, "fixed_assets_net_amount": null, "fixed_assets_vat_amount": null, "free_zone_tax": 0, "has_note": false, "international_ticket_sales": 0, "invoice_status": "registered", "is_services_invoice": false, "net_commissions": 0, "non_credit_tax_amount": null, "non_refundable_vat_amount": null, "non_refundable_vat_code": null, "non_withheld_vat": 0, "other_taxes": { "other_taxes_detail": [ { "tax_amount": 400, "tax_code": 14, "tax_rate": "19" } ], "total_amount": 400 }, "out_of_time_vat": 0, "own_vat": 0, "partial_vat_withheld": 0, "receipt_reference_number": null, "received_at": "2021-06-25T19:27:04.000Z", "reference_number": null, "reference_type_code": null, "rejected_at": null, "services_invoice": null, "settlement_issuer_id": null, "third_party_vat": 0, "tobacco": { "cigarettes": 0, "cigars": 0, "processed_tobacco": 0 }, "total_documents": null, "total_vat_withheld": 0, "transaction_category": "Del Giro", "vat_amount": 1900, "vat_commissions": null }, "issue_type": "received", "issuer": { "id": "111111111", "institution_tax_payer": null, "name": "Test Customer 1" }, "net_amount": 10000, "number": "135", "receiver": null, "tax_period": "06/2021", "total_amount": 12300 } ``` # Tax returns Source: https://docs.fintoc.com/guides/movements/fiscal-links/tax-returns Get the annual income tax returns (F22) a taxpayer filed at Chile's SII: declared salaries and fees, withholdings, and the refund requested or amount owed. This page explains what a tax return is and which amounts it includes. For every attribute, see the [Tax return object](/api/fiscal-api/tax-returns/tax-returns-object). ## What a tax return is In Chile, taxpayers declare their income tax once a year to the Servicio de Impuestos Internos (SII) with the F22 form (Operación Renta). The form sums up the income of the previous calendar year and the taxes already withheld. The resulting balance is either a refund the SII pays into the taxpayer's bank account, or an amount the taxpayer owes. A `TaxReturn` is one filed F22 form. Fintoc returns one `TaxReturn` per fiscal year. Tax returns are available for `Links` connected to the SII (`cl_fiscal_sii`). Create the `Link` with the `tax_returns` product. ## Read a tax return These attributes help you read a tax return: | Attribute | Meaning | | :- | :- | | `fiscal_year` | Year the return was filed. The declared income corresponds to the previous calendar year. | | `document_number` | Folio the SII assigned to the filed form. | | `institution_tax_return.income.salary` | Salaries, pensions, and similar income (code 1098 of the F22 form). | | `institution_tax_return.income.fees` | Income from fee receipts for professional services (code 547). It is the sum of `fees_with_retention` (code 461) and `fees_without_retention` (code 545). | | `institution_tax_return.income.withheld_fees` | Taxes withheld from fee receipts (code 492). | | `institution_tax_return.refund_amount` | Refund the taxpayer requested. | | `institution_tax_return.due_amount` | Tax the taxpayer still has to pay. | | `institution_tax_return.refund_account` | Bank account where the SII deposits the refund, as a transfer account with the holder's tax ID, account number, and institution. | | `taxpayer` | The taxpayer who filed the form, with the activities, addresses, and authorized documents registered at the SII. | Amounts are integers in CLP, the smallest unit of the currency. ## Endpoints [List tax returns](/api/fiscal-api/tax-returns/tax-returns-list) returns the tax returns of the `Link`, paginated. [Get a tax return](/api/fiscal-api/tax-returns/tax-returns-get) returns one tax return by `id`. ## How Fintoc fetches tax returns Fintoc fetches the filed returns when your user creates the `Link`. Tax returns aren't refreshed periodically, so to get a return filed after the connection, create a new `Link`. ## Example ```json theme={null} { "id": "taxret_nMNejK7BT8oGbvO4", "object": "tax_return", "currency": "CLP", "document_number": "12345", "fiscal_year": "2021", "institution_id": "cl_fiscal_sii", "institution_tax_return": { "due_amount": 0, "income": { "fees": 746546, "fees_with_retention": 234212, "fees_without_retention": 512334, "salary": 2313123, "withheld_fees": 42341 }, "refund_account": { "holder_id": "000000000", "holder_name": "Test Customer 1", "institution": { "country": "cl", "id": "cl_banco_de_chile", "name": "Banco de Chile" }, "number": "0000000000" }, "refund_amount": 1000 }, "taxpayer": { "id": "000000000", "institution_tax_payer": { "activities": [ { "category": "1", "code": "0123", "description": "Servicios de tecnología", "iva": false, "started_at": "2020-04-16T04:00:00.000Z" } ], "addresses": [ { "apartment": null, "city": "Santiago", "code": "0000000", "commune": "PROVIDENCIA", "number": "123", "region": "REGION METROPOLITANA", "street": "CALLE FALSA", "type": "DOMICILIO" } ], "authorized_documents": [ { "authorized_at": "2021-11-30T15:57:38.584Z", "code": "33", "description": "FACTURA ELECTRONICA", "max_documents": 414 } ], "email": "test@example.com", "phone": "000000000" }, "name": "Test Customer 1" } } ``` # Tax statements Source: https://docs.fintoc.com/guides/movements/fiscal-links/tax-statements Get the monthly tax statements (F29) a taxpayer filed at Chile's SII: VAT debit and credit, fee and salary withholdings, provisional payments, and total due. This page explains what a tax statement is and which amounts it includes. For every attribute, see the [Tax statement object](/api/fiscal-api/tax-statements/tax-statements-object). ## What a tax statement is In Chile, taxpayers declare and pay their monthly taxes to the Servicio de Impuestos Internos (SII) with the F29 form. The form includes the value-added tax (VAT) charged on sales, the VAT paid on purchases, withholdings on fee receipts and salaries, and the monthly provisional payments of the income tax. A `TaxStatement` is one filed F29 form. Taxpayers file the F29 form once per month, so a `Link` created with the `tax_statements` product gives you the taxpayer's monthly tax activity. Tax statements are available for `Links` connected to the SII (`cl_fiscal_sii`). Create the `Link` with the `tax_statements` product. ## Read a tax statement These attributes help you read a tax statement: | Attribute | Meaning | | :- | :- | | `fiscal_year`, `period` | Year and month the statement covers. `period` is the month number, for example `10` for October. | | `document_number` | Folio the SII assigned to the filed form. | | `status` | Status of the form at the SII, for example `Vigente` for a form currently in force. | | `institution_tax_statement.total_debit` | VAT charged on sales during the month (débito fiscal). | | `institution_tax_statement.total_credit` | VAT paid on purchases during the month (crédito fiscal). | | `institution_tax_statement.retention_fee` | Tax withheld on fee receipts for professional services. | | `institution_tax_statement.salary_tax` | Second category tax withheld on salaries (impuesto único de segunda categoría). | | `institution_tax_statement.monthly_provisional_payments` | Monthly provisional payment of the income tax. `null` when the taxpayer didn't declare one. | | `institution_tax_statement.total_payment` | Total amount to pay for the month within the legal term. | | `taxpayer` | The taxpayer who filed the form, with the activities, addresses, and authorized documents registered at the SII. | Amounts are integers in CLP, the smallest unit of the currency. ## Endpoints [List tax statements](/api/fiscal-api/tax-statements/tax-statements-list) returns the statements of the `Link`, paginated. Fintoc orders them by year and period, with the most recent statement first. [Get a tax statement](/api/fiscal-api/tax-statements/tax-statements-get) returns one statement by `id`. ## How Fintoc keeps tax statements up to date Fintoc fetches the filed statements when your user creates the `Link`. Fintoc then refreshes them periodically with the refresh interval of your plan, so newly filed months appear in the list. ## Example ```json theme={null} { "id": "taxstmt_nMNejK7BT8oGbvO4", "object": "tax_statement", "currency": "CLP", "document_number": "123456", "fiscal_year": 2021, "institution_id": "cl_fiscal_sii", "institution_tax_statement": { "monthly_provisional_payments": null, "retention_fee": 6497, "salary_tax": 1870153, "total_credit": 403497, "total_debit": 1173692, "total_payment": 2646845 }, "interval_unit": "monthly", "period": "10", "status": "Vigente", "taxpayer": { "id": "000000000", "institution_tax_payer": { "activities": [ { "category": "1", "code": "0123", "description": "Servicios de tecnología", "iva": false, "started_at": "2020-04-16T04:00:00.000Z" } ], "addresses": [ { "apartment": null, "city": "Santiago", "code": "0000000", "commune": "PROVIDENCIA", "number": "123", "region": "REGION METROPOLITANA", "street": "CALLE FALSA", "type": "DOMICILIO" } ], "authorized_documents": [ { "authorized_at": "2021-11-30T15:57:38.584Z", "code": "33", "description": "FACTURA ELECTRONICA", "max_documents": 414 } ], "email": "test@example.com", "phone": "000000000" }, "name": "Test Customer 1" } } ``` # Get bank movements Source: https://docs.fintoc.com/guides/movements/guides/guides-bank-movements Fetch bank account movements from the Fintoc API using a Link token and your secret key, with example requests in cURL and the Python and Node SDKs. > [!WARNING] > > **Warning** > > This guide is meant to be followed by a **backend**. Your Secret Key should **never** be sent to the frontend. Before we can start using Fintoc, you need to get your Fintoc account's Secret Key. It will be used throughout this guide, so make sure to follow [the guide on how to get your API keys](/guides/home/dashboard/guides-api-keys) to get your live Secret Key. To get the movements from your bank account, first you need to create a Link and get its Link Token. You can do this from [the dashboard](https://app.fintoc.com/), following [this guide](/guides/movements/guides/guides-banking-link-from-dashboard). Once you have your Link Token, we can start. > [!NOTE] > > **Tip** > > Because we will need to use our Secret Key and a Link Token, some sensitive information needs to be replaced by you to make the code from this guide fully functional. From now on, we will write `FINTOC_SECRET_KEY` to represent the Secret Key that you need to get and `LINK_TOKEN` to represent the Link Token required for any of this code to work. ## Tooling This guide shows how to use the Fintoc API using the [Python SDK](https://github.com/fintoc-com/fintoc-python), the [Node SDK](https://github.com/fintoc-com/fintoc-node) and [cURL](https://curl.se/). The `cURL` tool can be replaced with any tool that allows HTTP requests to be issued through the terminal and shell scripts (for example, [Wget](https://www.gnu.org/software/wget/)). The SDKs can be installed with the following commands: ```bash Python theme={null} pip install fintoc ``` ```bash Node theme={null} # Using npm npm install fintoc # Using yarn yarn add fintoc ``` When using any of the SDKs, make sure that you're using the latest version. You can find the changelog and versions of the SDKs [here](https://github.com/fintoc-com/fintoc-python/releases) (Python SDK) and [here](https://github.com/fintoc-com/fintoc-node/releases) (Node SDK). ## Getting the correct account As [the guide for creating a Link from the dashboard](/guides/movements/guides/guides-banking-link-from-dashboard) mentions, a Link represents the username/password combination of the bank. This means that a Link might have more than one account (for example, maybe you have a checking account and a savings account under the same username/password combination). Let's decide which of our accounts has the information that we need. First, let's list all of our accounts: ```bash cURL theme={null} curl --request GET \ --url 'https://api.fintoc.com/v1/accounts/?link_token=LINK_TOKEN' \ --header 'Authorization: FINTOC_SECRET_KEY' ``` ```javascript Node theme={null} import { Fintoc } from 'fintoc'; async function main() { const fintocClient = new Fintoc('FINTOC_SECRET_KEY'); const link = await fintocClient.links.get('LINK_TOKEN'); const accounts = await link.accounts.all(); for await (const account of accounts) { console.log(account.serialize()); } } main(); ``` ```python theme={null} from fintoc import Fintoc fintoc_client = Fintoc("FINTOC_SECRET_KEY") link = fintoc_client.links.get("LINK_TOKEN") accounts = link.accounts.all() for account in accounts: print(account.serialize()) ``` The output to each of the snippets above should look something like this: ```text cURL theme={null} # Prettyfied Output [ { "balance": { "available": 0, "current": 0, "limit": 0 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "TEST CUSTOMER 1", "id": "acc_MNejK7B76wbJGbl1", "name": "Cuenta de Ahorro", "number": "000000000", "object": "account", "official_name": "Cuenta de Ahorro", "refreshed_at": "2021-11-30T17:53:59.438000+00:00", "type": "savings_account" } { "balance": { "available": 0, "current": 0, "limit": 200000 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "TEST CUSTOMER 1", "id": "acc_O38ioEA4QejjnGeb", "name": "Cuenta Corriente", "number": "0000000", "object": "account", "official_name": "Cuenta Corriente MN", "refreshed_at": "2021-11-30T16:54:23.441000+00:00", "type": "checking_account" } ] ``` ```javascript Node theme={null} // Prettyfied Output { balance: { available: 0, current: 0, limit: 0 }, currency: 'CLP', holder_id: '111111111', holder_name: 'TEST CUSTOMER 1', id: 'acc_MNejK7B76wbJGbl1', name: 'Cuenta de Ahorro', number: '000000000', object: 'account', official_name: 'Cuenta de Ahorro', refreshed_at: '2021-11-30T17:53:59.438000+00:00', type: 'savings_account' } { balance: { available: 0, current: 0, limit: 200000 }, currency: 'CLP', holder_id: '111111111', holder_name: 'TEST CUSTOMER 1', id: 'acc_O38ioEA4QejjnGeb', name: 'Cuenta Corriente', number: '0000000', object: 'account', official_name: 'Cuenta Corriente MN', refreshed_at: '2021-11-30T16:54:23.441000+00:00', type: 'checking_account' } ``` ```python Python theme={null} # Prettyfied Output { "balance": { "available": 0, "current": 0, "limit": 0 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "TEST CUSTOMER 1", "id": "acc_MNejK7B76wbJGbl1", "name": "Cuenta de Ahorro", "number": "000000000", "object": "account", "official_name": "Cuenta de Ahorro", "refreshed_at": "2021-11-30T17:53:59.438000+00:00", "type": "savings_account" } { "balance": { "available": 0, "current": 0, "limit": 200000 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "TEST CUSTOMER 1", "id": "acc_O38ioEA4QejjnGeb", "name": "Cuenta Corriente", "number": "0000000", "object": "account", "official_name": "Cuenta Corriente MN", "refreshed_at": "2021-11-30T16:54:23.441000+00:00", "type": "checking_account" } ``` In our case, we want to use the data from our checking account, so we now know that we need to use the account with id `acc_O38ioEA4QejjnGeb` to search for our movements. The id of your account should be different, but it should also start with `acc_`. > [!NOTE] > > **Tip** > > From now on, we will write `ACCOUNT_ID` to represent the id of the account that we want to use. ## Getting the movements Now that we know the id of the account that we want to use, we just need to use it to get the movements. ```bash cURL theme={null} curl --request GET \ --url 'https://api.fintoc.com/v1/accounts/ACCOUNT_ID/movements?link_token=LINK_TOKEN' \ --header 'Authorization: FINTOC_SECRET_KEY' \ --header 'Accept: application/json' ``` ```javascript Node theme={null} import { Fintoc } from 'fintoc'; async function main() { const fintocClient = new Fintoc('FINTOC_SECRET_KEY'); const link = await fintocClient.links.get('LINK_TOKEN'); const account = await link.accounts.get('ACCOUNT_ID'); const movements = await account.movements.all(); for await (const movement of movements) { console.log(movement.serialize()); } } main(); ``` ```python theme={null} from fintoc import Fintoc fintoc_client = Fintoc("FINTOC_SECRET_KEY") link = fintoc_client.links.get("LINK_TOKEN") account = link.accounts.get("ACCOUNT_ID") movements = account.movements.all() for movement in movements: print(movement.serialize()) ``` The output to each of the snippets above should look something like this: ```text cURL theme={null} # Prettyfied Output [ { "id": "mov_J32e7dHabkrqQ48P", "description": "Abono por transferencia de Test Customer 1 Rut 11.111.111-1 desde Cuenta Corriente de B.Santander, el 28/11/2021 a las 19:16", "amount": 3143097, "currency": "CLP", "post_date": "2021-11-29T00:00:00.000Z", "transaction_date": "2021-11-28T19:16:00.000Z", "type": "transfer", "recipient_account": null, "sender_account": { "holder_id": "111111111", "number": null, "institution": null, "holder_name": "Test Customer 1" }, "comment": null, "reference_id": null, "pending": false, "object": "movement" }, { . . . }, . . . ] ``` ```javascript Node theme={null} // Prettyfied Output { id: 'mov_J32e7dHabkrqQ48P', description: 'Abono por transferencia de Test Customer 1 Rut 11.111.111-1 desde Cuenta Corriente de B.Santander, el 28/11/2021 a las 19:16', amount: 3143097, currency: 'CLP', post_date: '2021-11-29T00:00:00.000Z', transaction_date: '2021-11-28T19:16:00.000Z', type: 'transfer', recipient_account: null, sender_account: { holder_id: '111111111', number: null, institution: null, holder_name: 'Test Customer 1' }, comment: null, reference_id: null, pending: false, object: 'movement' } { . . . } . . . ``` ```python theme={null} # Prettyfied Output { "id": "mov_J32e7dHabkrqQ48P", "description": "Abono por transferencia de Test Customer 1 Rut 11.111.111-1 desde Cuenta Corriente de B.Santander, el 28/11/2021 a las 19:16", "amount": 3143097, "currency": "CLP", "post_date": "2021-11-29T00:00:00.000Z", "transaction_date": "2021-11-28T19:16:00.000Z", "type": "transfer", "recipient_account": None, "sender_account": { "holder_id": "111111111", "number": None, "institution": None, "holder_name": "Test Customer 1" }, "comment": None, "reference_id": None, "pending": False, "object": "movement" } { . . . } . . . ``` > [!WARNING] > > **Warning** > > Notice that, while every Fintoc SDK handles pagination internally, the `cURL` method does not *automagically* paginate the results of the API. Every page returns the last 30 elements of the resource by default. Each response also returns with a `Link` header that contains the pagination information. To get the next page, look for the `next` element on the `Link` header of the response, and make a request to that URL. The pages of a resource end when there is no `next` element on the `Link` header of the response. > > You can read more about pagination [here](/api/fintoc-api/pagination). ## Deposits with more than one check or document A deposit with more than one check or document arrives as one movement for the total amount, without a breakdown of each item. Deposits of checks or documents have `type` set to `check`, and cash deposits have `type` set to `other`. If the bank later splits the deposit, Fintoc changes the aggregated movement to `reversed` and creates the individual movements. To learn how this affects your reconciliation, see [Deposits with more than one check or document](/api/movements-api/movements/movements-object#deposits-with-more-than-one-check-or-document). ## Keep stored movements in sync The bank can update a movement's `type`, `description`, `status`, and other fields days or weeks after the movement first appears. A `confirmed` movement isn't guaranteed to be final. Fintoc keeps the same movement `id` when a movement changes. Store movements by `id`, then: * Subscribe to the `account.refresh_intent.movements_modified` and `account.refresh_intent.movements_removed` events. * When a movement changes, request it again by `id` and replace your stored copy. * When `movements_removed` includes a movement `id`, remove that movement from your records. * Periodically list the current month's movements again and replace your stored copies. See [Movements can change after creation](/api/movements-api/movements/movements-object#movements-can-change-after-creation). ## Troubleshooting Links that stop updating Credentials problems can stop a Link from updating. Follow these best practices to keep each Link updating and to fix a Link that the bank rejects. ### Check that your Movements plan is active If a Link in `live` mode shows as active in the Dashboard but has no next update scheduled, your organization's free Movements trial probably ended or your plan isn't active. Fintoc only updates Links in `live` mode for organizations with an active Movements trial or plan. To hire a plan, contact Fintoc's commercial team at [sales@fintoc.com](mailto:sales@fintoc.com). See [Movements free trial](/guides/movements/overview-data-aggregation#movements-free-trial). ### Use a separate bank user for each Link A Link uses one bank portal username and password combination. If you create more than one Link with the same bank portal user, those Links depend on the same credentials. Banks can report valid credentials as invalid, so a single rejection doesn't stop a Link from updating. If the bank rejects the same credentials twice in a row, Fintoc pauses updates for every Link that uses that user, even when the bank's response is wrong. For Banco Santander, Fintoc pauses those Links after the first rejection. While those Links are paused, Fintoc retries the credentials later to confirm whether they're invalid. Fintoc limits the number of retries because too many failed login attempts can make the bank block the user. If more than one Link shares the same user, each Link adds login attempts with those credentials, which makes a block more likely. To avoid this, use a different bank portal user for each Link. ### Reconnect a Link with invalid credentials If the user changed their bank password, or Fintoc confirms that the credentials are invalid, the Link stops updating and Fintoc sends a `link.credentials_changed` webhook event. Fintoc can't refresh the Link until the user reconnects the Link through the widget with their current credentials. For a refresh triggered on demand, the `POST` request succeeds even if the bank later rejects the credentials. The rejection arrives as an `account.refresh_intent.rejected` webhook event. See [Refresh Intent webhooks](/guides/movements/refresh-intents-walkthrough/refresh-intents-webhook). New on-demand refresh requests for the Link return a `rejected_refresh_intent` error only while Fintoc has paused the Link, or within one hour of the rejection. After that hour, a Link with a single rejection accepts new on-demand requests again. See [Refresh Intent errors](/guides/movements/refresh-intents-walkthrough/refresh-intents-errors). > [!NOTE] > > Each time the user connects through the widget, Fintoc issues a new Link Token and the previous one stops working. Save the new `link_token` that you get from the [token exchange](/guides/movements/integration-with-exchange-token). A Link belongs to one bank portal user. If the user connects with a different bank portal user, Fintoc creates a separate Link, even if both users access the same company. ### Fix blocked credentials If the bank blocked the user's credentials, Fintoc can't connect or refresh the Link. The user must first restore their access to the bank portal with their bank. After the user can log in to the bank portal again, connect the Link again through the widget. ### Reconnect BCI 360 Links BCI has two business portals: BCI Empresarios and BCI 360. The widget shows each portal as a separate option, but the API returns `cl_banco_bci` as the institution `id` for Links from both portals. To reconnect a BCI business Link, ask the user which portal they log in to. If they use BCI 360, select the **BCI 360** option in the widget. See [Products and institutions](/guides/movements/overview-data-aggregation/products-and-institutions-movements#banco-bci). # Create a banking Link from the dashboard Source: https://docs.fintoc.com/guides/movements/guides/guides-banking-link-from-dashboard Create a banking `Link` from [the dashboard](https://dashboard.fintoc.com/) to use in your application. First, switch the dashboard to `live` mode: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/64f98f3c53ac101ca527912131899b01e669218acc7c2cefc11345b2bdf36455-Screenshot_2025-05-02_at_10.34.56_AM_copy_2.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=f73bc4b6808f21c181c8c81e9b4e1b1c) Select the option to create a `Link`. This example creates a personal `Link`, but the same steps apply to a business `Link`: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/a436316c430ba0215335577787850544c4f0b3daaecdd3cce306fa585a80a33e-Screenshot_2025-05-02_at_10.34.56_AM_copy.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=faaec50bf86caf447f30b5f10e2a6abf) The dashboard opens a modal where you select the country and `Link` type. For this example, select Chile, Banking, and Individual. Then confirm your selections: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/f93a5321624d5c199c84597fac8c1b4545e7f72f10f565f2ba71592cc661f171-Screenshot_2025-05-02_at_10.36.43_AM.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=9347f317c15ad751a4f66d0d5f8aa1b7) The Fintoc widget opens. Select **Continue**: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/da909b3b93b041ebcc80d14c39c8d92f05e5098193a7590d4827f7bb3f78b6c8-Screenshot_2025-05-02_at_10.37.49_AM.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=d95cc490afd6dab37320cc168f268fb4) Select the bank that holds the account you want to associate with the `Link`: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/731a419ce5258ad02e4cbfc4bb33a6a833c27c1230e92c57caafa00ac70f0ffb-Screenshot_2025-05-02_at_10.38.02_AM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=27e5cd1f96386f7d6577664a727e3cd0) Enter your bank credentials, then select **Continue**: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/9ff50a1e48fd67344a5d7bffac980b063288cc7b7f613f4c5dc9866c29049a6a-Screenshot_2025-05-02_at_10.38.21_AM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=c6cd3a49a000eee421cffb3a4cb493ef) Fintoc creates and connects the `Link`, then displays a confirmation screen. Select **Finish**: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/fe83b0fb5ab557e5bf4e1ca12d3ab980885f19e497e60d0cc7d74d88bcd597dc-Screenshot_2025-05-02_at_10.38.44_AM.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=2fa6ed21971e2cdef8baf51fbe5e16c5) The dashboard displays the Link Token in a modal: ![](https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/2eaaea9d9b71cab9e2c568c556def24626822ae8bf2e2b0871993ed2adf798e3-Screenshot_2025-05-02_at_10.38.59_AM.png?fit=max\&auto=format\&n=YQmOnq8Zegydl6oL\&q=85\&s=088effce7f329633d6f80aac8a2973d1) Copy the Link Token and store it securely. The Link Token represents your bank credentials and lets you request banking data through Fintoc. Fintoc does not store the Link Token, so you cannot retrieve it after closing the modal. # Reconnect a Link Source: https://docs.fintoc.com/guides/movements/guides/guides-reconnect-link Detect when a Movements Link needs new credentials and reconnect it from the dashboard or the Widget. A `Link` stops updating when Fintoc can no longer log in to the bank with the `Link`'s stored credentials. This happens when the account holder changes their bank password or when the bank rejects the credentials. The `Link` also stops updating when Fintoc deletes credentials that a bank requires the account holder to renew periodically. To resume updates, reconnect the `Link` with the account holder's current bank credentials. ## Detect a Link that needs reconnecting Use any of these signals: * **Webhook event:** Fintoc sends a [`link.credentials_changed`](/api/main-resources/events-reference/types-of-events) event when the credentials of a `Link` change or Fintoc deletes them. Reconnect the `Link` when you receive this event. Subscribe a [Webhook Endpoint](/guides/resources/webhooks-walkthrough) to receive it as soon as Fintoc sends it. * **Link status:** The [Link object](/api/movements-api/links/link-object) has `status: "login_required"`. * **Refresh status:** The `Link` has `refresh_status: "interrupted"`. * **Refresh Intent rejected:** A Refresh Intent fails with the `rejected_refresh_intent` error code, or you receive an `account.refresh_intent.rejected` event. See [Errors](/guides/movements/refresh-intents-walkthrough/refresh-intents-errors). ## Periodic re-authentication Some banks require you to reconnect a `Link` periodically, even if the account holder didn't change their password. For example, Fintoc deletes the stored credentials for Banco Santander `Link` objects 6 months after the account holder last entered them. When Fintoc deletes the credentials, it sends a `link.credentials_changed` event and the `Link` stops updating until you reconnect it. ## Reconnect from the dashboard Use the dashboard to reconnect a `Link` for your own bank account. 1. Go to the [dashboard](https://dashboard.fintoc.com/) and switch to `live` mode. 2. Create a `Link` with the same country, `Link` type, and holder type as the original `Link`. Follow the steps in [Create a banking Link from the dashboard](/guides/movements/guides/guides-banking-link-from-dashboard). 3. In the Fintoc Widget, select the same bank and enter the account holder's current credentials. Use the same bank username as the original `Link`. 4. Copy the new `link_token` from the modal and store it securely. 5. Replace the previous `link_token` in your integration with the new one. ## Reconnect from the Widget Use the Widget to let your users reconnect their own bank accounts. 1. From your backend, [create a Link Intent](/api/movements-api/linkintents/link-intents-create) with the same `country`, `holder_type`, and `product` as the original `Link`. 2. Open the Widget in your frontend with the Link Intent's `widget_token`, as described in the [integration flow](/guides/movements/integration-with-exchange-token). 3. Ask your user to select the same bank and log in with the same bank username and their current password. 4. In the `onSuccess` callback, send the `exchangeToken` to your backend. 5. From your backend, call the [exchange endpoint](/api/movements-api/links/links-exchange) to get the `Link` with its new `link_token`. 6. Replace the previous `link_token` with the new one wherever you store it. ## What changes after reconnecting When your user reconnects with the same bank username and holder, Fintoc updates the existing `Link` instead of creating a new one. This table shows what happens to each resource or field: | Resource or field | After reconnecting | | :- | :- | | `Link` `id` | Stays the same | | `Account` and movement `id`s | Stay the same | | `link_token` | Fintoc issues a new one | | `status` | Returns to `active` | The previous `link_token` stops working. Use the new `link_token` for all requests. > [!WARNING] > > If your user logs in with a different bank username or holder, Fintoc creates a new `Link` with a new `id`. Update your integration to use the new `Link`. ## Test the integration Run the Widget flow in `test` mode with your `test` API keys and the credentials in [Test your integration](/guides/movements/data-aggregation-test-your-integration). Confirm that your backend exchanges the `exchangeToken` and stores the new `link_token`. # Integration Flow Source: https://docs.fintoc.com/guides/movements/integration-with-exchange-token Connect users' bank accounts to Fintoc through the Widget by exchanging a public token for a Link Token, then use it to fetch bank movements from your backend. > [!NOTE] > > **Use the dashboard to connect your own acount** > > We recommend you integrate the Widget only if you want to connect your users' bank account. If you want to get data from your own bank account, you should connect your account using the Dashboard as its much easier. > > [Learn how to connect your account using the Dashboard here.](/guides/movements/guides/guides-banking-link-from-dashboard) The connection flow begins when your user wants to connect their bank account to your app: ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/b8d1bde-Public_Exchange_Token_Flow.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=e5f164c636fa35d0d59bb6ff09a93f07) So, putting it into words: 1. You need to **create a[Link Intent](/api/movements-api/linkintents/link-intent-object)** resource with the [create endpoint](/api/movements-api/linkintents/link-intents-create). This object represents the connection intent of the user and receives all configurations needed to open the Widget in your frontend.\ In order to correctly update the movements in your bank account, make sure the account used to create the Link has the necessary permissions to review the balance and movements page, the historical statement, the provisional statement, and any other movement-related pages. To connect an account in Test Mode, see our [testing guide](/guides/movements/data-aggregation-test-your-integration). 2. The Link Intent resource you just created has a field named `widget_token`. You need to open the Widget in your frontend using this token and the public [API Key](/guides/home/api-keys): ```html theme={null} ``` 3. Once the connection is succeeded, you will receive the Link Intent object as a parameter in your `onSuccess` callback. This object now will have the `exchange_token`. This is a temporary key that allows you to retrieve the Link information, including the `link_token`, so then you can access all information provided by your user: ```html theme={null} ``` 4. **From your backend**, use the `exchangeToken` and your secret key to get the Link information using the [exchange endpoint](/api/movements-api/links/links-exchange). And that's it. # Bank movements overview Source: https://docs.fintoc.com/guides/movements/overview-data-aggregation/index Get bank movement history from your users' financial institutions with Fintoc's Data Aggregation API for reconciliation, risk analysis, and cash flow reporting. Transactional data can be useful for an infinite amount of applications, including personal finance management, expense reports, bank reconciliation, cash flow, risk analysis and more. With Fintoc you can access the history of bank movements of your users. ## Who can use Fintoc To use Fintoc, your business must meet all of these requirements: * **A company tax ID.** In Mexico, this is your company's Mexican tax ID (RFC), which has 12 characters. In Chile, this is your company's Chilean tax ID (RUT). * **A bank account in your company's name.** Fintoc only sends your payouts to an account associated with your company's RFC or RUT. * **An email address on your company's domain.** Sign up with a corporate email, not a personal one such as Gmail or Hotmail. Fintoc doesn't accept individuals, including a natural person with business activity (persona natural con giro). Your company also needs at least 6 months of business activity, counted from the start date on your business initiation certificate. If your company is younger, the Dashboard shows an error when you upload the certificate and you can't complete the onboarding. These requirements apply to every Fintoc product, including Movements and Payments. Confirm that your business meets them before you build your integration in `test` mode. ### Movements free trial When you create an organization in Chile, Fintoc starts a free 2-week Movements trial. During the trial, Fintoc updates Links in `live` mode on schedule. When the trial ends, Fintoc stops updating Links in `live` mode until your organization hires a Movements plan. The Links still show as active in the Dashboard, but they don't have a next update scheduled. To hire a plan, contact Fintoc's commercial team at [sales@fintoc.com](mailto:sales@fintoc.com). Your business must meet the requirements above. ## Bank movements Once your user connects their account, you can get the history of bank movements using the endpoint to [List movements](/api/movements-api/movements/movements-list). You can read about the supported account types [here](/api/movements-api/accounts/accounts-object). The bank movements API returns the accounting date, amount and other useful data. A bank movement should look like this: ```json theme={null} { "id": "mov_BO381oEATXonG6bj", "object": "movement", "amount": 59400, "post_date": "2020-04-17T00:00:00.000Z", "description": "Traspaso de:Fintoc SpA", "transaction_date": "2020-04-16T11:31:12.000Z", "currency": "CLP", "reference_id": "123740123", "type": "transfer", "pending": false, "recipient_account": null, "sender_account": { "holder_id": "111111111", "holder_name": "Test Customer 1", "number": "0000000000", "institution": { "id": "cl_banco_de_chile", "name": "Banco de Chile", "country": "cl" } }, "comment": "Pago factura 198" } ``` ## Movements update Bank movements aren't static. Once an account connects to Fintoc, Fintoc will periodically update the account's information. The update intervals depend on the selected plan. You can also have a plan in which you explicitly ask Fintoc to update an account using the Fintoc API. # Products and Institutions Source: https://docs.fintoc.com/guides/movements/overview-data-aggregation/products-and-institutions-movements Banks in Chile that the Movements module supports, with the account types, currencies, statement history, and special permissions required for each. # Banks in Chile 🇨🇱 The Movements module supports the following banks in Chile: ## Banco de Chile This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_de_chile` | [People Portal](https://portales.bancochile.cl/personas) | 24 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | | Business `cl_banco_de_chile` | [Banconexión 2.0 Portal](https://login.portalempresas.bancochile.cl/bancochile-web/empresa/login/index.html#/login) | 24 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | Special statement permissions: * Balances and Movements * Historical Statement * Line of Credit * USD Currency Account ## Banco Santander This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_santander` | [People Portal](https://banco.santander.cl/personas) | 24 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_santander` | [Office Banking Portal](https://www.officebanking.cl/) | 24 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | Special statement permissions: * Balances and Movements * Provisional Statement * Historical Statement > [!WARNING] > > Fintoc can't connect Office Banking (business) Links when Santander asks the person signing in for a second authentication factor or an extra key at login. Only that person holds the second factor, so Fintoc can't complete the login on that person's behalf. > > To fix this limitation, contact Fintoc support. Share the Chilean tax ID (RUT) of the person with portal access and the RUT of the company you want to connect. Fintoc asks Santander to make an exception for that person. Santander usually takes 3 to 5 business days to apply the exception. ## Banco Itaú This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_itau` | [People Portal](https://banco.itau.cl/) | 24 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_itau` | [Companies Portal](https://banco.itau.cl/wps/portal/newiol/web) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | Special statement permissions: * Received Transfers Statement * Sent Transfers Statement ## Banco BICE This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_bice` | [People Portal](https://login.bice.cl/loginpersona2020/index2.html) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_bice` | [Companies Portal](https://www.bice.cl/empresas) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | ## Banco Scotiabank This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_scotiabank` | [People Portal](https://www.scotiabankchile.cl/) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_scotiabank` | [Companies Portal](https://www.scotiabankchile.cl/Grandes-Empresas) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | Special statement permissions: * Recent Transactions * Historical Statements * Transfers and Payments Statement * Line of Credit ## Banco BCI This institution supports movements for individuals as well as for companies (for companies, two different portals exist: the BCI Empresarios portal and the BCI 360 portal) | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_bci` | [People Portal](https://www.bci.cl/corporativo/banco-en-linea/personas) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_bci` | [BCI Empresarios Portal](https://www.bci.cl/corporativo/banco-en-linea/pyme) | 6 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_bci_360` | [BCI 360 Portal](https://www.bci.cl/empresas) | 3 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP ✅ USD | ## Banco Estado This institution supports movements for individuals as well as for companies | Type | Portal | History | Products | Currency | | - | - | - | - | - | | Individual `cl_banco_estado` | [People Portal](https://www.bancoestado.cl/content/bancoestado-public/cl/es/home/home.html#/) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | | Business `cl_banco_estado` | [Companies Portal](https://www.bancoestado.cl/content/bancoestado-public/cl/es/home/inicio---bancoestado-empresas.html#/) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | ## Banco Security This institution supports movements only for companies | Type | Portal | History | Products | Currency | | :- | :- | :- | :- | :- | | Business `cl_banco_security` | [Companies Portal](https://empresas.bancosecurity.cl/) | 12 months | ✅ Checking Accounts ✅ Sight Accounts | ✅ CLP | > [!WARNING] > > **Make sure the linked account has the necessary permissions** > > To keep movements up to date for any of the account types above, make sure the credentials you use to create the Link **have** every permission needed to view movement-related pages. Required pages include the balance and movements page, the historical statement, the provisional statement, and the transfers statements. > [!WARNING] > > **Foreign currency accounts refresh once a day** > > If you need your foreign currency accounts to refresh with the same frequency as the national currency accounts, contact our support team and specify which accounts need this behavior. # Fiscal institution in Chile 🇨🇱 Fiscal `Links` connect to the Servicio de Impuestos Internos (SII), the Chilean tax authority, instead of a bank. The institution is `cl_fiscal_sii` and it supports individuals and companies. Each fiscal product has its own history and refresh behavior: | Product | History | Updates | | :- | :- | :- | | Invoices | Last 12 months of documents | Periodic refresh and on-demand Refresh Intents | | Tax statements (F29) | Every filed statement | Periodic refresh | | Tax returns (F22) | Every filed return | Fetched when the `Link` is created | See [Fiscal Links](/guides/movements/fiscal-links/index) to learn what each fiscal product returns. # Data aggregation quickstart Source: https://docs.fintoc.com/guides/movements/overview-data-aggregation/quickstart Get started with Fintoc's Data Aggregation API and pull your first bank account movements in under five minutes using the Widget and a secret key. To start using Fintoc, you just need to create an account on our [Dashboard](https://app.fintoc.com) and follow these three steps: 1. Create a test **Link** and obtain its **link\_token** 2. Get your API Keys to be able to interact with the API 3. Get the movements and balances from the test **Link** we just created > [!NOTE] > > To use Movements in `live` mode, your business needs a company tax ID, a bank account in your company's name, and an email address on your company's domain. Fintoc doesn't accept individuals. See [Who can use Fintoc](/guides/movements/overview-data-aggregation#who-can-use-fintoc). > [!NOTE] > > **[Sample repository](https://github.com/fintoc-com/quickstart)** > > You can check out the repository [fintoc-com/quickstart](https://github.com/fintoc-com/quickstart) to see examples of how to integrate the Fintoc API in your code with different languages while using our Widget. ## Step 1: Create a test Link A **Link** represents a connection (or *link*) between a financial entity's account and Fintoc. That means that when we say "*create a test Link*", we mean to ask you to connect a test account (from your preferred financial entity) to Fintoc. The quickest way to *link* an account with Fintoc is through our [Dashboard](https://app.fintoc.com). To achieve this, you first need to create an account on the Fintoc Dashboard (not to be confused with, for example, your bank account which we will use later to create a Link). Once your Fintoc account has been created, you will be able to create Links. When creating a new **Link**, you will need to select your bank and then use your bank account's credentials to login. Because we are creating a test Link, you can use any credential from the [sandbox](/guides/resources/test-mode) on any bank. For example, try using `41614850-3` as the username and `jonsnow` as the password. > [!WARNING] > > **Make sure the linked account has the necessary permissions** > > In order to correctly update the movements in your bank account, make sure the account used to create the Link has the necessary permissions to review the balance and movements page, the historical statement, the provisional statement, and any other movement-related pages. Once you have created the test **Link**, your **link\_token** will be shown in the Dashboard. The **link\_token** represents your bank credentials, and you will have to use it whenever you want to get the balance or movements of that **Link**. ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/d586d550d421ebc19454cc1715d1b17d83d3ee3de74c1808651fe56331140d0b-image.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=c9f8ab86f7ef6ed1e684729c1feec594) ## Step 2: Get your API Keys Every interaction with the Fintoc API must be authenticated with the [API Keys](/guides/home/api-keys) of your Fintoc account. If an interaction with the API does not include your API Key or includes an incorrect API Key, Fintoc will return an error. Every Fintoc account has two key pairs: one pair corresponds to the [sandbox](/guides/resources/test-mode), while the other pair corresponds to the actual API environment. Every resource is stored either in the [sandbox](/guides/resources/test-mode) or in the actual API environment, and resources from one environment cannot be manipulated by resources from the other environment. Your API Keys will be available in the [Dashboard](https://app.fintoc.com). In this case, you must use the **Secret Key** from the [sandbox](/guides/resources/test-mode). To identify it easily, we added the prefix **sk\_test\_**. ## Step 3: Get the balance and movements To make it easier, we will call the API for the first time using [cURL](https://curl.se/). You can also use [Postman](https://www.postman.com/) or one of our [open source libraries](/guides/resources/libraries-and-integrations). To get the movements of an account, you first need the **ID** that Fintoc assigned to said account. Open your terminal and paste the following code to list every account associated with a **Link**: ```bash theme={null} curl https://api.fintoc.com/v1/accounts?link_token=YOUR_LINK_TOKEN \ -H "Authorization: YOUR_SECRET_API_KEY" ``` For every account, you should be able to see the total balance and its owner information. You can use the following code to list the movements of an account: ```bash theme={null} curl https://api.fintoc.com/v1/accounts/ACCOUNT_ID/movements?link_token=YOUR_LINK_TOKEN \ -H "Authorization: YOUR_SECRET_API_KEY" ``` You should now see the movements of that account. You have completed the quickstart integration with the Fintoc Movements API. # Refreshing on demand Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/index Refresh Intents request the latest movement data from the bank for a `Link`. With Refresh Intents, you can update a `Link`'s movements on demand. Fintoc fetches the latest movements from your accounts instead of waiting to refresh the data. After the Refresh Intent completes, Fintoc sends an [event](/api/main-resources/events-reference/events-object) to your application through a [webhook](/guides/resources/webhooks-walkthrough). The event indicates the outcome of the refresh. Use the [List movements](/api/movements-api/movements/movements-list) endpoint to retrieve new movements. This feature is available only for supported use cases and regions. On-demand refreshes aren't enabled by default. To enable them for your organization, contact Fintoc's commercial team. To refresh movements on demand, follow these steps: 1. Create a Refresh Intent. 2. Open the Widget if the bank requires multi-factor authentication during sign-in. 3. Wait for an event with the refresh outcome. 4. Use the List movements endpoint to retrieve the latest movements. > [!NOTE] > > See [Errors](/api/fintoc-api/errors) for refresh limitations. # Create a refresh intent Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-creating Create a RefreshIntent with the Fintoc API to request an on-demand refresh of a Link and pull the latest bank account data outside the normal schedule. ## Send the request Create a [`RefreshIntent`](/api/movements-api/refresh-intents) to request an on-demand update of a `Link`. ```bash theme={null} curl --request POST "https://api.fintoc.com/v1/refresh_intents?link_token=link_000000000_token_00000000" \ --header 'Authorization: sk_live_0000000000000000' \ --header 'Content-Type: application/json' ``` ```javascript theme={null} import { Fintoc } from 'fintoc'; async function main() { const fintoc = new Fintoc('sk_live_0000000000000000'); const refreshIntent = await fintoc.refreshIntents.create({ link_token: 'link_000000000_token_00000000', }); console.log(refreshIntent.serialize()); } main(); ``` ```python theme={null} from fintoc import Fintoc fintoc = Fintoc("sk_live_0000000000000000") refresh_intent = fintoc.refresh_intents.create( link_token="link_000000000_token_00000000" ) print(refresh_intent.serialize()) ``` ## Handle the response The API returns a [`RefreshIntent` object](/api/movements-api/refresh-intents/refresh-intents-object): ```json theme={null} { "id": "ri_ml4K3O4RSvALRjnV", "requires_mfa": null, "object": "refresh_intent", "refreshed_object": "link", "refreshed_object_id": "link_000000000", "status": "created", "created_at": "2021-12-07T20:40:53.513Z", "type": "only_last" } ``` Use the response `id` to [get the refresh intent](/api/movements-api/refresh-intents/refresh-intents-get). If `requires_mfa` is `null`, wait for Fintoc to send a `link.refresh_intent.succeeded` webhook event. Otherwise, open the widget so your user can complete multifactor authentication. In that case, the response includes `widget_token`: ```json theme={null} { "id": "ri_ml4K3O4RSvALRjnV", "requires_mfa": { "widget_token": "ri_ml4K3O4RSvALRjnV_sec_29K7Ar45AiSFnSgLgDx7nGHX" }, "object": "refresh_intent", "refreshed_object": "link", "refreshed_object_id": "link_000000000", "status": "created", "created_at": "2021-12-07T20:40:53.513Z", "type": "only_last" } ``` Open the widget with `requires_mfa.widget_token` to complete the refresh. # Errors Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-errors ## Your organization doesn't have on-demand refreshes enabled On-demand refreshes aren't enabled by default. If your organization doesn't have them enabled and you create a Refresh Intent for a live `Link`, the API returns a `403` error: ```json theme={null} { "error": { "type": "authorization_error", "message": "Your organization does not have access to on demand refreshes. Send an email to sales@fintoc.com to hire this refresh method.", "code": "on_demand_policy_required" } } ``` To enable on-demand refreshes, contact Fintoc's commercial team at [sales@fintoc.com](mailto:sales@fintoc.com). ## You can't create a Refresh Intent while another is in progress If you create a Refresh Intent while another is in progress, the API returns this error: ```json theme={null} { "error": { "type": "invalid_request_error", "message": "There is already a refresh intent in progress for link_00000000.", "code": "refresh_intent_in_progress", "param": null, "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` ## You have to wait 5 minutes to create a new Refresh Intent If you created a successful Refresh Intent less than 5 minutes ago, the API returns this error: ```json theme={null} { "error": { "type": "invalid_request_error", "message": "This Link was recently refreshed.You have to wait at least 5 minutes between refresh intents", "code": "rate_limit_exceeded", "param": null, "doc_url": "https://docs.fintoc.com/reference/errors" } } ``` > [!NOTE] > > If a Refresh Intent created less than 5 minutes ago fails, you can create another without waiting. ## The credentials are invalid If Fintoc confirms that your credentials are invalid, the API returns this error: ```json theme={null} { "error": { "type": "link_error", "message": "The institution indicated that the credentials are invalid. You need to reconnect the account.", "code": "rejected_refresh_intent" } } ``` To resume updates, reconnect the `Link`. See [Reconnect a Link](/guides/movements/guides/guides-reconnect-link). If the bank rejects your credentials but Fintoc has not confirmed they are invalid, you must wait at least one hour. The API returns this error: ```json theme={null} { "error": { "type": "link_error", "message": "The institution indicated that the credentials are invalid. You have to wait at least an hour to avoid locking your credentials", "code": "rejected_refresh_intent" } } ``` # Request new movements Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-new-movements The `account.refresh_intent.succeeded` event confirms that the account includes the latest movements available from the bank. To get the latest movements, call the [List movements](/api/movements-api/movements/movements-list) endpoint with the account `id` included in the event. The `new_movements` field only indicates the number of movements created during the Link Intent update. > [!NOTE] > > Fintoc sends one event for each updated account. Request an account's movements only after you receive the event for that account. If a `Link` has three accounts, the other two accounts might still be updating when the first event arrives. ## Update movements that already exist The `account.refresh_intent.succeeded` event and `new_movements` only cover new movements. The bank can also change or delete movements you already stored. Fintoc reports those changes with the `account.refresh_intent.movements_modified` and `account.refresh_intent.movements_removed` events. When a movement changes, request it again by `id` and replace your stored copy. When `movements_removed` includes a movement `id`, remove that movement from your records. See [Movements can change after creation](/api/movements-api/movements/movements-object#movements-can-change-after-creation). # Wait for the results using a Webhook Endpoint Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-webhook Create a Webhook Endpoint to get an Event for each account when a Refresh Intent finishes, and handle `succeeded`, `failed`, and `rejected` refresh results. When you request a Refresh Intent, the update isn't immediate. Fintoc first needs to go to the bank to search for new movements and the time that can take depends on the bank and its conection status, but it normally takes between 1 and 3 minutes. So you don't need to ask if the update is finished every 5 seconds, you should create a [Webhook Endpoint](/api/main-resources/webhook-endpoints), where we will notify you through an [Event](/api/main-resources/events-reference) when the Refresh Intent has been completed. For each account in your Link, we will send you an event. For example, if your Link has three accounts, you will receive three events, each one containing the result of each account update. Keep in mind that the three results could be different, and the Refresh Intent will be marked successful only if **every account** gets successfully updated. ## If everything goes right If the update goes according to planned when refreshing an account, we will send you an `account.refresh_intent.succeeded` event that looks like this: ```json theme={null} { "id": "evt_00000000", "type": "account.refresh_intent.succeeded", "mode": "live", "created_at": "2021-12-07T21:43:54.343Z", "data": { "object": "refresh_intent", "refreshed_object": "account", "refreshed_object_id": "acc_00000000", "status": "succeeded", "public_error": null, "created_at": "2021-12-03T00:00:00.000Z", "type": "only_last", "new_movements": 5 }, "object": "event" } ``` Inside the `data` key, you will find the detail about the refresh. In this case, the account with `id: acc_00000000` got successfully updated, as its `status` is `succeeded`. The `new_movements` field indicates how many new movements were found during the update. If this number is different to zero, you should query the [List Movements](/api/movements-api/movements/movements-list) endpoint to obtain the new movements. If that number is zero, you can assume that you have the latest movements already. > [!NOTE] > > **On demand, recurrent and the `new_movements` field** > > The `new_movements` field refers to the amount of movements new after the update, and not since you last called the API, so you must be careful if your account also has recurrent updates, as the `new_movements` of a refresh may not be the amount of new movements since you last requested movements to Fintoc. ## If something goes wrong If the update fails, for example if the bank application is down, we will send you an `account.refresh_intent.failed` event. ```json theme={null} { "id": "evt_00000000", "type": "account.refresh_intent.failed", "mode": "test", "created_at": "2021-12-07T21:56:07.711Z", "data": { "object": "refresh_intent", "refreshed_object": "account", "refreshed_object_id": "acc_00000001", "status": "failed", "public_error": "retryable_error/support_required_error", "created_at": "2021-12-07T00:00:00.000Z", "type": "only_last", "new_movements": 0 }, "object": "event" } ``` Inside the `data` key, you will find the detail about the refresh. In this case, the account with `id: acc_00000001` failed to be updated, as its `status` is `failed`. If the `public_error` is `retryable_error`, you can create a new Refresh Intent without needing to wait 5 minutes (the time you need to wait between Refresh Intents). If the `public_error` is `support_required_error`, contact our support team. ## If the credentials are invalid If the update fails because the credentials are invalid, we will send you an `account.refresh_intent.rejected` event: ```json theme={null} { "id": "evt_00000000", "type": "account.refresh_intent.rejected", "mode": "test", "created_at": "2021-12-07T21:56:07.711Z", "data": { "object": "refresh_intent", "refreshed_object": "account", "refreshed_object_id": "acc_00000002", "status": "rejected", "public_error": null, "created_at": "2021-12-07T00:00:00.000Z", "type": "only_last", "new_movements": 0 }, "object": "event" } ``` Inside the `data` key, you will find the detail about the refresh. In this case, the account with `id: acc_00000002` failed to be updated due to the bank rejecting the credentials as invalid, as its `status` is `rejected`. If this is the case, you can create a new Refresh Intent without needing to wait 5 minutes (the time you need to wait between Refresh Intents). But **beware**. Doing this too many times too fast could lock the user out of its account. We recommend waiting some time between retries. > [!NOTE] > > **Invalid credentials** > > Sometimes, banks say a set of credentials are invalid when they are not. For this reason, Fintoc lets you retry the Refresh Intent after a `rejected` status. If the credentials are invalid, reconnect the `Link`. See [Reconnect a Link](/guides/movements/guides/guides-reconnect-link). # Open the widget for Refresh Intents Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-widget > [!NOTE] > > **Only for multifactor authentication logins** > > You don't need to open the widget for Refresh Intents if the `requires_mfa` field is `null`. If the bank of the link you're trying to refresh requires multifactor authentication (MFA) for the *login*, then you will have to open the widget on your frontend so the user can enter its second factor. For security reasons, this cannot be done purely through the API. You can review which institutions require MFA on login at the [Institutions](/guides/movements/overview-data-aggregation/products-and-institutions-movements) table. For now, this functionality is only enabled for banks in Mexico. The configuration to open the widget should look like this: ```html theme={null} ``` Here, the `widgetToken` parameter corresponds to the token located inside the `requires_mfa` object of the Refresh Intent. You can read more about the widget and its configurations at the [Widget](/guides/resources/widget) documentation. # Connection flow UX guidelines Source: https://docs.fintoc.com/guides/movements/ux-guidelines-1 Best practices for the Fintoc connection flow: approved button terminology, Fintoc logo and imagotype URLs, safe space, and color and sizing rules. We take customer experience and safety seriously. To ensure your success, our UX/UI experts have created this helpful guide for your organization. ### Best practices ✅ Do: * Only use images provided by Fintoc by embedding the URL provided. * Use the same image style throughout your site. * Button text should only include Fintoc-approved terminology. * Make sure you choose a background color that contrasts with the image color. ❌ Do not: * Do not modify the font, color, button radius, or padding inside the logo in any way. * Do not utilize a png, jpg or non URL version of the buttons and images provided. * Do not use a background color that is similar to the image color. * Do not add shadow effects to the image. * Do not add hover effects. * Do not utilize any other terminology than the recommended one. ### Why use URLs in your website or app We recommend that you use the URL links directly in your application or website to get the most up-to-date version of the images. This way you don't have to update manually every time there is a change. ```html theme={null} src="https://assets.fintoc.com/?img_name=button_cl_light_trailing" ``` ### Within the connection flow **Accepted terminology:** *Conéctate* or *Conectar*. In the process of your users connecting their account to Fintoc, use the recommended terminology for the button that will open our widget. You may also want to display our complete logo as a way to show that this process is powered by Fintoc. | Preview | Description | HTML | | :- | :- | :- | | ![Dark logotype](https://assets.fintoc.com/?img_name=logo_dark) | Dark logotype | `` | | ![Light logotype](https://assets.fintoc.com/?img_name=logo_light) | Light logotype | `` | ### Other logo usage You may want to display our logo to show who your work with. We want to help you do this in the best way. We are providing two URLs for you to embed within your website or app for this purpose. Leave the recommended safe space around our logo. | Preview | Description | HTML | | :- | :- | :- | | ![Dark imagotype](https://assets.fintoc.com/?img_name=imagotype_dark) | Dark imagotype | `` | | ![Light imagotype](https://assets.fintoc.com/?img_name=imagotype_light) | Light imagotype | `` | ![](https://mintcdn.com/fintoc-49b8bee8/SkvJJ-DZ5D4yC6tQ/images/edbf04ab7028cb07548fd8cad9e5dc4453e28005ff7c92ecd1f803df4279d873-Clearance_explanation.png?fit=max\&auto=format\&n=SkvJJ-DZ5D4yC6tQ\&q=85\&s=802304f49619c947326b70e4e995ba47) If you have any questions on how to implement these recommendations, contact our team. # Account number object Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-number-object Fields on the `AccountNumber` object that routes inbound transfers to an `Account`, including `status`, `options`, `metadata`, and `is_root`. ## The Account Number object An `AccountNumber` represents a bank account number tied to one of your accounts that can receive inbound transfers. In Mexico, it corresponds to a standardized Mexican bank account number (CLABE). Fintoc returns an `AccountNumber` object when you create one for an account, or when you list or retrieve the account numbers you own. ```json theme={null} { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Lq7dP901xZgA2B", "created_at": "2024-03-01T20:09:42.949787176Z", "deleted_at": null, "description": "My payins", "is_root": false, "last_transfer_at": "2026-03-15T14:22:01.000Z", "metadata": { "order_id": "12343212" }, "mode": "test", "number": "000000000000000000", "options": { "max_amount": 400, "min_amount": 300 }, "status": "enabled", "updated_at": "2024-03-01T20:09:42.949787176Z" } ``` | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier for the account number. | | `object` | string | The type of the object, which is always `account_number`. | | `account_id` | string | Account the Account Number points to. | | `created_at` | string | Timestamp when the account number was created (in ISO 8601 format). | | `deleted_at` | string | Timestamp when the account number was deleted. `null` if the account number has not been deleted. | | `description` | string | Label to identify this Account Number. Up to 40 characters. | | `is_root` | bool | Indicates if the Account Number is the main Account Number of the Account. Root Account Numbers appear as the sender Account Number for Outbound Transfers. | | `last_transfer_at` | string | Timestamp of the last inbound transfer received by this account number. `null` if no inbound transfer has ever been received. | | `metadata` | object | Optional key-value pairs associated with this account number. | | `mode` | string | Mode of the API (`test` or `live`). | | `number` | string | Account number that receives inbound transfers. In Mexico, this value is a standardized Mexican bank account number (CLABE). | | `options` | object | Additional configurations for Account Numbers. | | `status` | string | Account number status. One of `enabled`, `disabled`, `blocked`, or `deleted`. Fintoc automatically returns inbound transfers directed to `disabled`, `blocked`, or `deleted` account numbers. | | `updated_at` | string | Timestamp when the account number was last updated (in ISO 8601 format). | ### The Options object (within the Account Number object) The `Options` object holds the minimum and maximum amount thresholds that filter inbound `Transfers`. It appears in the `options` field of the `AccountNumber` object. | Field | Type | Description | | :- | :- | :- | | `max_amount` | integer | Maximum amount accepted for inbound transfers. Fintoc automatically rejects transfers exceeding this threshold. Amounts use the smallest currency unit for the account's country: centavos for Mexico, pesos for Chile. Must be a positive integer or `null`. | | `min_amount` | integer | Minimum amount accepted for inbound transfers. Fintoc automatically rejects transfers below this threshold. Amounts use the smallest currency unit for the account's country: centavos for Mexico, pesos for Chile. Must be a positive integer or `null`. | # Create an account number Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-numbers-create reference/core-api.json POST /v2/account_numbers Creates a new account number for one of your accounts, in the `live` or `test` mode of the API key used. In Mexico, Fintoc generates 18-digit standardized Mexican bank account numbers (CLABEs) for you. In Chile, Fintoc generates the account number for you. # Delete an account number Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-numbers-delete reference/core-api.json DELETE /v2/account_numbers/{id} Deletes an account number of your organization. Available only for Mexico account numbers, which are standardized Mexican bank account numbers (CLABEs). You cannot delete the root account number. Returns the deleted account number. Deleting an account number that is already deleted is idempotent: the endpoint returns the account number again with its `deleted` status instead of an error. The endpoint returns `404 Not Found` only when no account number with the given ID exists. The underlying CLABE becomes available in the recycling pool 30 days after deletion, and Fintoc may reassign the CLABE to a different account or organization. Deletion is permanent and cannot be undone. # List account numbers Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-numbers-list reference/core-api.json GET /v2/account_numbers Lists the account numbers of your organization in the `live` or `test` mode of the API key used. Filter by `account_id` and `no_transfers_since`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to move through the list. The `Link` response header carries the URLs to navigate the paginated list. # Get an account number Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-numbers-retrieve reference/core-api.json GET /v2/account_numbers/{id} Retrieves the details of an account number of your organization, by its ID. # Update an account number Source: https://docs.fintoc.com/api/business-accounts-api/account-numbers/account-numbers-update reference/core-api.json PATCH /v2/account_numbers/{id} Updates the editable fields of an account number of your organization: `description`, `status`, `metadata`, and inbound `options`. # Account statement object Source: https://docs.fintoc.com/api/business-accounts-api/account-statements/account-statement-object Fields on the `AccountStatement` object, including monthly balances, totals, `download_url`, `start_date`, and `end_date` for an `Account`. ## The Account Statement object An `AccountStatement` represents a monthly PDF document that summarizes the `Movements` and balances of an `Account` over a given period. You receive an `AccountStatement` object when you list the statements available for an `Account`, and you download the document itself from its `download_url`. ```json theme={null} { "id": "acst_3COTQ3yzsq7Y6irrhHlm2R8d5XQ", "object": "account_statement", "created_at": "2026-04-15T12:19:58.096Z", "download_url": "https://storage.googleapis.com/fin-sandbox-core-statements-prd/corg_3AOGg2wCBU78MtvheS1ecdjW3lm/AccountStatement/acst_3COTQ3yzsq7Y6iSsqHlm2R8d5XQ/account_statement/20260415121957660-statement-0350-03-2026.pdf?GoogleAccessId=sa-url-presigning-prd%40fin-prd-wch4ah7y4a.iam.gserviceaccount.com&Expires=1776269474&Signature=xxxxxx&response-content-disposition=attachment", "end_date": "2026-03-31", "final_balance_cents": 699675, "initial_balance_cents": 0, "start_date": "2026-03-01", "total_credited_cents": 1159675, "total_debited_cents": 460000 } ``` | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier for the statement. | | `object` | string | Always `"account_statement"`. | | `created_at` | string | ISO 8601 timestamp in UTC when Fintoc generated the account statement. | | `download_url` | string | Signed URL to download the statement as a PDF. Expires after a short time window. | | `end_date` | string | End date of the statement period in ISO 8601 format. | | `final_balance_cents` | integer | Account balance at the end of the period, in cents. | | `initial_balance_cents` | integer | Account balance at the start of the period, in cents. | | `start_date` | string | Start date of the statement period in ISO 8601 format. | | `total_credited_cents` | integer | Total amount credited during the period, in cents. | | `total_debited_cents` | integer | Total amount debited during the period, in cents. | # List account statements Source: https://docs.fintoc.com/api/business-accounts-api/account-statements/account-statements-list reference/core-api.json GET /v2/accounts/{account_id}/account_statements Lists the account statements of one of your accounts for the `live` or `test` mode of the API key you use. Filter by date range with the `since` and `until` query parameters. The response is paginated. Use `starting_after`, `ending_before`, and `limit` to page through the results. When more results are available, the `Link` response header carries the URL of the next page. # The Account Verification object Source: https://docs.fintoc.com/api/business-accounts-api/account-verification/account-verification-object Fields on the account verification object that confirms counterparty ownership through a micro-deposit, including `status` and `receipt_url`. An account verification confirms that a counterparty bank account exists and belongs to the expected holder. Fintoc issues a verification transfer from one of your accounts to the counterparty account, then reports the outcome through the verification's `status`. Use an account verification to validate a counterparty account, such as a standardized Mexican bank account number (CLABE), before you pay out to it. ```json Account verification object theme={null} { "id": "accv_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "object": "account_verification", "counterparty": { "account_number": "000000000000000000", "account_type": "clabe", "holder_id": "000000000", "holder_name": "Test Customer 1", "institution": { "id": "40012", "country": "mx", "name": "BBVA Mexico" } }, "mode": "test", "reason": null, "receipt_url": "https://www.banxico.org.mx/cep/", "status": "succeeded", "transaction_date": "2026-03-11T20:42:49Z", "transfer_id": "tr_2daFu0zqqDtZGJaSi2TGI2Mm1nN" } ``` The account verification object has the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the account verification. | | `object` | `string` | Literal that identifies the object type. Always `account_verification`. | | `counterparty` | `object` | Details of the verified counterparty account. See the Counterparty object table below. | | `mode` | `string` | API key mode for the verification. One of `live` or `test`. | | `reason` | `string` | Failure reason. `null` unless `status` is `failed`. See the [account verification failure reasons](/api/business-accounts-api/account-verification/account-verification-object#account-verification-failure-reasons). | | `receipt_url` | `string` | Verification receipt URL. `null` until the verification transfer settles. | | `status` | `string` | Current verification state. One of `pending` (in progress), `succeeded` (ownership confirmed), or `failed` (could not be completed). | | `transaction_date` | `string` | ISO 8601 datetime in UTC when Fintoc performed the verification. `null` until the verification transfer settles. | | `transfer_id` | `string` | Identifier of the transfer issued to verify the account. `null` until the verification transfer is created. | ## Counterparty The `counterparty` field describes the account holder that Fintoc verifies. The field has the following attributes: | Attribute | Type | Description | | - | - | - | | `account_number` | `string` | The 18-digit standardized Mexican bank account number (CLABE) of the verified counterparty. | | `account_type` | `string` | Lowercase account type for the counterparty. Always `clabe` for Mexican account verifications. | | `holder_id` | `string` | Mexican tax ID (RFC) of the account holder. `null` when not available. | | `holder_name` | `string` | Name of the account holder. `null` when not available. | | `institution` | `object` | Financial institution of the counterparty. See the Institution object table below. | ## Institution The `institution` field identifies the counterparty's financial institution and has the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Identifier assigned to the institution. See the [Mexico (Banxico) institution codes](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). | | `country` | `string` | ISO 3166-1 alpha-2 country code of the institution, in lowercase. Always `mx`. | | `name` | `string` | Name of the institution. | ## Account verification failure reasons The following reasons explain why an account verification failed, including return codes from Mexico's Interbank Electronic Payment System (SPEI): | Reason | Description | | - | - | | `transfer_fail` | Fintoc could not send the verification transfer. | | `cep_unavailable` | Banxico did not publish the electronic payment receipt (CEP) within the 30-minute verification window, so Fintoc could not confirm the account. Retry the verification later. | | `unknown` | The reason could not be determined. | | Any SPEI return code | The counterparty institution returned the verification transfer through SPEI. The code mirrors the transfer `return_reason`. See the [SPEI codes](/api/business-accounts-api/transfers/spei-codes) for each code and the recommended action. | # Create an account verification Source: https://docs.fintoc.com/api/business-accounts-api/account-verification/account-verifications-create reference/core-api.json POST /v2/account_verifications Checks a counterparty account by issuing a verification transfer from one of your accounts. In Mexico, Fintoc sends `0.01 MXN` and returns the holder name and tax ID that the receiving bank reports. In Chile, Fintoc sends `1 CLP` with the Chilean tax ID (RUT) you provide. A successful verification means the receiving bank accepted the transfer with that RUT. Some banks accept transfers without validating the RUT. Chilean verifications do not return the holder name. The verification uses the `live` or `test` mode of the API key. Requires a JSON Web Signature (JWS). Verifying the same `account_number` again within 24 hours returns the first verification created in that window instead of issuing a new transfer. In Chile, the previous verification must also match the `institution_id`, `account_type`, and `holder_id`. Fintoc does not reuse verifications with a `failed` status, so you can retry them immediately. # Get an account verification Source: https://docs.fintoc.com/api/business-accounts-api/account-verification/account-verifications-get reference/core-api.json GET /v2/account_verifications/{id} Retrieves the details of an account verification by its ID. # List account verifications Source: https://docs.fintoc.com/api/business-accounts-api/account-verification/account-verifications-list reference/core-api.json GET /v2/account_verifications Lists the account verifications of your organization for the mode (`live` or `test`) of the API key used. Filter by `account_number`, `transfer_id`, or by date range with `since` and `until`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to move through the list. The `Link` response header carries the URLs to navigate the paginated list. # Account object Source: https://docs.fintoc.com/api/business-accounts-api/accounts/account-object Fields on the `Account` object, including `available_balance`, `entity`, `currency`, `status`, and root account details for outbound transfers. ## The Account object An `Account` represents funds held for an entity. In Mexico, an `Account` is also known as Centro de Costos. You use an account to track available funds and send outbound transfers. You receive an `Account` object when you create, list, or retrieve an account. The account list includes the root account that holds your initial Fintoc balance. The following table describes the attributes of an `Account` object: | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the `Account` object. | | `object` | `string` | Identifier for the object type. Always `account`. | | `available_balance` | `integer` | Balance available for outbound transfers, in the smallest currency unit. | | `currency` | `string` | Three-letter [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html) for the account balance. | | `description` | `string` | Text you can use to identify the account. Up to 40 characters. | | `entity` | `object` | Legal holder that owns the account. See [The `Entity` object](#the-entity-object-within-the-account-object). | | `is_root` | `boolean` | If `true`, the account is the root account. Fintoc creates root accounts automatically, and root accounts hold your initial Fintoc balance. | | `mode` | `string` | API mode used for the account. One of `test` or `live`. | | `root_account_number` | `string` | Number assigned to the associated root account. | | `root_account_number_id` | `string` | Unique identifier for the associated root account number. | | `status` | `string` | Current state of the account. One of `active`, `blocked`, or `closed`. | A `blocked` account cannot send transfers. You can change a `blocked` account back to `active`. A `closed` account cannot receive or send transfers. You cannot reverse the `closed` status. The following example shows a fully populated `Account` object: ```json Account Object theme={null} { "id": "acc_23JlasHas241", "object": "account", "available_balance": 23459183, "currency": "MXN", "description": "My root account", "entity": { "id": "ent_4324qwkalsds", "holder_id": "ND", "holder_name": "Test Entity 1" }, "is_root": true, "mode": "test", "root_account_number": "000000000000000000", "root_account_number_id": "acno_Kasf91034gj1AD", "status": "active" } ``` ### The Entity object (within the Account object) The `Entity` object identifies the account's legal holder. The `Entity` object appears in the `entity` field of the `Account` object. The following table describes the attributes of an `Entity` object: | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the entity. | | `holder_id` | `string` | Tax identifier for the account owner. Use a Chilean tax ID (RUT) in Chile. Use a Mexican tax ID (RFC) or Unique Population Registry Code (CURP) in Mexico. | | `holder_name` | `string` | Name of the account owner. | # Create an account Source: https://docs.fintoc.com/api/business-accounts-api/accounts/accounts-create reference/core-api.json POST /v2/accounts Creates an account for an entity of your organization, in the `live` or `test` mode of the API key used. Every account gets a root account number. In Mexico, the account gets a standardized Mexican bank account number (CLABE) that Fintoc generates for you. In Chile, the account gets a number that Fintoc generates unless you choose your own with `number`. # List accounts Source: https://docs.fintoc.com/api/business-accounts-api/accounts/accounts-list reference/core-api.json GET /v2/accounts Lists the accounts of your organization for the `live` or `test` mode of the API key used. Filter by `entity_id` and `status`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to move through the list. The `Link` response header carries the URLs to navigate the paginated list. # Get an account Source: https://docs.fintoc.com/api/business-accounts-api/accounts/accounts-retrieve reference/core-api.json GET /v2/accounts/{id} Returns the details of an account of your organization, identified by its ID. # Update an account Source: https://docs.fintoc.com/api/business-accounts-api/accounts/accounts-update reference/core-api.json PATCH /v2/accounts/{id} Updates the editable fields of an account of your organization. Currently, only the `description` is editable. You can update only the `description` attribute of an `Account`. # Create an entity Source: https://docs.fintoc.com/api/business-accounts-api/entities/entities-create reference/core-api.json POST /v2/entities # Get an entity Source: https://docs.fintoc.com/api/business-accounts-api/entities/entities-get reference/core-api.json GET /v2/entities/{id} # Entities list Source: https://docs.fintoc.com/api/business-accounts-api/entities/entities-list reference/core-api.json GET /v2/entities # The Entity object Source: https://docs.fintoc.com/api/business-accounts-api/entities/entity-object Fields on the `Entity` object, the legal holder of `Account` objects, including `country_code`, `holder_id`, `holder_name`, and lifecycle status. An `Entity` represents the legal holder of one or more `Account` objects. Fintoc returns an `Entity` object when you list or retrieve your organization's entities. Your organization has one root `Entity`, indicated by `is_root`. An entity progresses from `draft` to `operational` before it can transact. The `Entity` object has the following attributes: | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for this object. | | `object` | `string` | Type of the object. Always `entity`. | | `country_code` | `string` | ISO 3166-1 alpha-2 country code of the entity, in lowercase, for example `cl` or `mx`. `null` when not set. | | `holder_id` | `string` | Mexican tax ID (RFC) of the entity owner, without dots or hyphens. The example uses the placeholder `AAA010101AAA`. Foreign entities use the generic RFC `XEXX010101000`. | | `holder_name` | `string` | Legal name of the entity owner. | | `is_root` | `boolean` | If `true`, this entity is your organization's root entity. | | `mode` | `string` | API key mode used to create the entity. One of `live` or `test`. | | `status` | `string` | Current status of the entity. One of `draft`, `under_review`, `pending_signature`, `canceled`, `waiting_initialization`, `operational`, `rejected`, or `paused`. | ```json Entity object theme={null} { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "object": "entity", "country_code": "mx", "holder_id": "AAA010101AAA", "holder_name": "Test Entity 1", "is_root": true, "mode": "test", "status": "operational" } ``` # The Movement object Source: https://docs.fintoc.com/api/business-accounts-api/movements/movement-object Fields on the `Movement` object that records each change to an `Account` balance, including `amount`, `direction`, `balance`, `resource_id`, and `type`. A `Movement` is a single change to the balance of an `Account`. Each `Movement` records whether money entered (`inbound`) or left (`outbound`) the account in `direction`. The `balance` field shows the resulting balance right after the change. ```json Movement object theme={null} { "id": "mov_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "object": "movement", "account_id": "acc_2rN1bQ8xHvK3mWpYzLd7TfGcRsE", "amount": 50000, "balance": 1050000, "currency": "MXN", "direction": "inbound", "mode": "test", "resource_id": "tr_2sP9cR4yJwM6nXqZaNe8UgHdSt0", "return_pair_id": null, "transaction_date": "2026-03-01T12:00:00.000Z", "type": "transfer" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the movement. | | `object` | `string` | Object type. Always `movement`. | | `account_id` | `string` | Identifier of the account the movement belongs to. | | `amount` | `integer` | Change to the account balance, in the smallest currency unit. Use `direction` to tell whether money entered or left the account. | | `balance` | `integer` | Account balance right after the movement, in the smallest currency unit. | | `currency` | `string` | Three-letter [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). One of `CLP` or `MXN`. | | `direction` | `string` | Flow of funds relative to the account. One of `inbound` (money entered) or `outbound` (money left). | | `mode` | `string` | API key mode used to record the movement. One of `live` or `test`. | | `resource_id` | `string` or `null` | Identifier of the resource that originated the movement, such as a transfer. `null` when no resource originated the movement. | | `return_pair_id` | `string` or `null` | Identifier of the other movement in a reversal pair. The identifier appears on both the reversed movement and the corresponding reversal movement, such as a `transfer_return`. `null` when the movement is not part of a reversal pair. | | `transaction_date` | `string` | ISO 8601 datetime in UTC when Fintoc recorded the movement in the account. | | `type` | `string` | Kind of movement. One of `transfer`, `transfer_return` (the reversal of a previous transfer), `fee`, `check`, `compensation`, or `other`. | # Get a movement Source: https://docs.fintoc.com/api/business-accounts-api/movements/movements-get reference/core-api.json GET /v2/accounts/{account_id}/movements/{id} Retrieves the details of a movement that belongs to one of your accounts, by its ID. # List movements Source: https://docs.fintoc.com/api/business-accounts-api/movements/movements-list reference/core-api.json GET /v2/accounts/{account_id}/movements Lists the movements of one of your accounts for the mode (`live` or `test`) of the API key used. Filter by `direction` and `resource_id`, or by date range with `since` and `until`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to move through the list. The `Link` response header carries the URLs to navigate the paginated list. Movements appear in descending `transaction_date` order. Movements with the same timestamp appear in reverse creation order. # Create an onboarding Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-create reference/main-api.json POST /v2/entities/{entity_id}/onboardings Creates an onboarding from the data required for the entity's country. Provide all company answers when creating the onboarding, then upload documents and submit it for review. # Get an onboarding Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-get reference/main-api.json GET /v2/entities/{entity_id}/onboardings/{id} Retrieves the onboarding with the given `id` for the entity. Only onboardings belonging to the organization of the API key used are visible. Requesting an onboarding that does not exist or belongs to another organization or entity returns a `404 Not Found` error. # List onboardings Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-list reference/main-api.json GET /v2/entities/{entity_id}/onboardings Lists the onboardings of the entity. Only onboardings belonging to the organization of the API key used are visible. # Submit an onboarding Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-submit reference/main-api.json POST /v2/entities/{entity_id}/onboardings/{id}/submit Use this endpoint to submit an onboarding for review once every requirement is met. The onboarding must have the `in_progress` status, completed required fields, and uploaded required documents. The required documents depend on the onboarding answers. For example, a Chilean account holder with `plaft.uaf_obligated` set to `true` needs `uaf_registration_certificate` and `plaft_manual_and_policies`. On success, the onboarding moves to the `submitted` status and can no longer be modified. # Upload a legal representative document Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-upload-legal-representative-document reference/main-api.json PUT /v2/entities/{entity_id}/onboardings/{id}/legal_representatives/{legal_representative_id}/documents/{slot_key} Uploads one document to an onboarding legal representative's document slot and returns the updated onboarding. Send the file as `multipart/form-data`. Each slot holds a single file: uploading to a slot that already has a file replaces the previous file. You can upload documents only while the onboarding is in progress. # Upload a shareholder document Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-upload-shareholder-document reference/main-api.json PUT /v2/entities/{entity_id}/onboardings/{id}/shareholders/{shareholder_id}/document Use this endpoint to upload the identity document for one onboarding shareholder. Send the file as `multipart/form-data`. The file must be a PDF, JPEG, or PNG and cannot exceed 30 MB. The expected document type depends on the shareholder type: an identification for a natural person, or the articles of incorporation for a legal entity. You can upload documents only while the onboarding is in progress. # Upload an onboarding document Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/entities-onboardings-upload-step-document reference/main-api.json PUT /v2/entities/{entity_id}/onboardings/{id}/documents/{slot_key} Use this endpoint to upload a document to an onboarding document slot, identified by `slot_key`. Send the file as `multipart/form-data`. The file cannot exceed 30 MB and must be a PDF. The `proof_of_address` slot also accepts JPEG and PNG files. Uploading a document to a slot that already has one replaces the existing document. You can upload documents only while the onboarding is in progress. # Onboarding object Source: https://docs.fintoc.com/api/business-accounts-api/onboardings/onboarding-object Fields on the `Onboarding` object for the Know Your Customer review of an `Entity`, including step data, documents, representatives, shareholders, and `status`. An `Onboarding` holds the Know Your Customer review of an `Entity`: company information, legal representatives, transactional profile, shareholders, and documents. The fields inside `data`, and the document slots, depend on `type` and on the `Entity`'s country. You create one onboarding per `Entity`, complete each step and document, and submit the onboarding for Fintoc to review. The `Onboarding` object has these attributes: | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier of the onboarding. | | `object` | string | The type of the object, which is always `onboarding`. | | `data` | object | Reviewed data for each completed step, keyed by step key. Chilean account holders return `company_basics`, `company_information`, `senior_management`, `transactional_profile`, and `plaft`. Mexican account holders return `company_information` and `transactional_profile`. See [Account holder onboarding](/guides/business-accounts/entities/account-holder-onboarding). | | `documents` | array | Document slots across every step, with their upload status. See the `OnboardingDocument` object. | | `entity_id` | string | Identifier of the `Entity` this onboarding belongs to. `null` if the onboarding is not associated with an `Entity`. | | `legal_representatives` | array | Legal representatives declared for the `Entity`. See the `OnboardingLegalRepresentative` object. | | `reviewed_at` | string | ISO 8601 datetime in UTC when Fintoc reviewed the onboarding. `null` until Fintoc reviews the onboarding. | | `shareholders` | array | Shareholders declared for the `Entity`. See the `OnboardingShareholder` object. | | `source` | string | Completion channel for the onboarding. One of `api` or `dashboard`. | | `status` | string | Current status of the onboarding. One of `pending`, `in_progress`, `submitted`, `approved`, `rejected`, or `cancelled`. | | `submittable` | boolean | Whether the onboarding has every required step and document completed. | | `submitted_at` | string | ISO 8601 datetime in UTC when you submitted the onboarding for review. `null` until you submit the onboarding. | | `type` | string | Kind of onboarding. One of `account_holder` (the `Entity` can own `Account` objects) or `settlement_recipient` (the `Entity` receives its share of split payments). | ## Onboarding Legal Representative object The `OnboardingLegalRepresentative` object has these attributes: | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier of the legal representative. | | `object` | string | Always `onboarding_legal_representative`. | | `documents` | array | Document slots for the representative: `identification_front` and `identification_back` in Chile, or `identification` and `power_of_attorney` in Mexico. See the `OnboardingDocument` object. | | `email` | string | Email address of the legal representative. | | `first_name` | string | Given name of the legal representative. | | `identification_number` | string | Identification number of the legal representative: an individual Chilean tax ID (RUT) or a passport number in Chile, or the Mexican Unique Population Registry Code (CURP) in Mexico. | | `last_name` | string | Family name of the legal representative. | | `nationality` | string | Two-letter ISO 3166-1 alpha-2 country code of the legal representative's nationality, in lowercase. | | `phone` | string | Contact phone number in E.164 format. `null` if not provided. Only present for Chilean account holder onboardings. | | `position` | string | Role the legal representative holds in the company. Can be `null` for Chilean account holder onboardings. | ## Onboarding Shareholder object The `OnboardingShareholder` object has these attributes: | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier of the shareholder. | | `object` | string | The type of the object, which is always `onboarding_shareholder`. | | `address` | string | Address of the shareholder. Only present for Chilean account holder onboardings. | | `document` | object | Document slot for the shareholder. See the `OnboardingDocument` object. `null` when the country requires no shareholder document, as in Chile. | | `effective_controller` | boolean | If `true`, the shareholder is an effective controller of the company. Only present for Chilean account holder onboardings. | | `fiscal_address` | string | Address of the shareholder registered with the tax authority. Only present for Chilean account holder onboardings. | | `holder_id` | string | Tax ID of the shareholder: the Chilean tax ID (RUT) or another identification number in Chile, or the Mexican tax ID (RFC) in Mexico. `null` if not provided. | | `last_name` | string | Last name. Only present when `type` is `natural_person`. | | `name` | string | Given name of a natural person, or business name of a legal entity. | | `parent_id` | string | Identifier of the parent shareholder when nested. `null` for root shareholders. | | `percentage` | number | Participation percentage held by the shareholder, from `0` to `100`. | | `type` | string | Type of shareholder. One of `natural_person` or `legal_entity`. | ## Onboarding Document object The `OnboardingDocument` object has these attributes: | Field | Type | Description | | :- | :- | :- | | `id` | string | Unique identifier of the uploaded document. Only present when `status` is `uploaded`. Pass it to `DELETE .../documents/{slot_key}/{document_id}` to remove the file. | | `filename` | string | Original filename of the uploaded document. Only present when `status` is `uploaded`. | | `slot_key` | string | Key identifying the document slot. | | `status` | string | Document slot status. One of `uploaded` or `missing`. | | `uploaded_at` | string | ISO 8601 datetime in UTC when you uploaded the document. Only present when `status` is `uploaded`. | ```json Onboarding object theme={null} { "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding", "data": { "company_information": { "business_activity": "Servicios financieros", "sector": "ecommerce" } }, "documents": [ { "id": "onbdoc_3cpDyiBmvdBJ8a0aJc8Vo2gO", "filename": "csf.pdf", "slot_key": "tax_registration_certificate", "status": "uploaded", "uploaded_at": "2026-01-15T14:30:00Z" } ], "entity_id": "ent_8anBwgZktbZH6ydyHa6Tm0eM", "legal_representatives": [ { "id": "onblr_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_legal_representative", "documents": [ { "id": "onbdoc_4dqEzjCnweCK9b1bKd9Wp3hP", "filename": "ine.pdf", "slot_key": "identification", "status": "uploaded", "uploaded_at": "2026-01-15T14:30:00Z" } ], "email": "rep@example.com", "first_name": "Test Customer 1", "identification_number": "AAAA010101HDFAAA01", "last_name": "Customer", "nationality": "mx", "position": "Director General" } ], "reviewed_at": null, "shareholders": [ { "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_shareholder", "document": { "id": "onbdoc_5erFakDoxfDL0c2cLe0Xq4iQ", "filename": "ine.pdf", "slot_key": "identification", "status": "uploaded", "uploaded_at": "2026-01-15T14:30:00Z" }, "holder_id": "AAAA010101AAA", "last_name": "Customer", "name": "Test Customer 1", "parent_id": null, "percentage": 76, "type": "natural_person" } ], "source": "api", "status": "in_progress", "submittable": false, "submitted_at": null, "type": "account_holder" } ``` # Recipient object Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipient-object Fields of the `Recipient` object, a saved destination account in Chile or Mexico with its holder, institution, and account details for transfers. ## The Recipient object A `Recipient` is a saved destination account for an entity. It stores the account holder, the institution, and the account details of a destination account in Chile or Mexico. You manage recipients with [Create a recipient](/api/business-accounts-api/recipients/recipients-create), [Update a recipient](/api/business-accounts-api/recipients/recipients-update), and [Delete a recipient](/api/business-accounts-api/recipients/recipients-delete). The `Recipient` object has these fields: | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the recipient. | | `object` | `string` | Type of the object. Always `recipient`. | | `account_number` | `string` | Destination bank account number. In Mexico, an 18-digit standardized Mexican bank account number (CLABE), a 16-digit debit card number, or a 10-digit mobile number. | | `account_type` | `string` or `null` | Destination account type, in lowercase. In Mexico, Fintoc infers it from `account_number`. `null` when unknown. One of `clabe`, `debit_card`, `mobile`, `vostro_account`, `vostro_account1`, `vostro_account2`, `vostro_account3`, `vostro_account4`, `values_custody`, `institution`, `checking_account`, `sight_account`, or `savings_account`. | | `alias` | `string` or `null` | Label you assign to the recipient. `null` when none is set. | | `created_at` | `string` | ISO 8601 datetime in UTC of when you created the recipient. | | `email` | `string` or `null` | Contact email address. `null` when none is set. | | `holder_id` | `string` or `null` | Account holder identification. In Chile, the Chilean tax ID (RUT). You can't change it after you create the recipient. `null` when none is set. | | `holder_name` | `string` or `null` | Account holder name. `null` when unavailable. | | `holder_type` | `string` | Account holder category. One of `person`, `company`, or `unknown`. | | `institution` | `object` | Financial institution that holds the destination account. Contains `id`, `name`, and `country` (`cl` or `mx`). | | `updated_at` | `string` | ISO 8601 datetime in UTC of when you last updated the recipient. | For example, a recipient with a checking account in Chile looks like this: ```json Recipient object theme={null} { "id": "rcp_2hQ9vBmKpR7xLtZ3sWn1fJ4dGcA", "object": "recipient", "account_number": "000000001", "account_type": "checking_account", "alias": "Test recipient", "created_at": "2026-03-01T12:00:00Z", "email": "recipient@example.com", "holder_id": "111111111", "holder_name": "Test Customer 1", "holder_type": "person", "institution": { "id": "cl_banco_santander", "name": "Banco Santander", "country": "cl" }, "updated_at": "2026-03-01T12:00:00Z" } ``` # Create a recipient Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipients-create reference/core-api.json POST /v2/recipients Creates a recipient for an entity in your organization, in the `live` or `test` mode of your API key. In Chile, provide the Chilean tax ID (RUT), `account_type`, and `holder_type`. In Mexico, Fintoc infers `account_type` from `account_number`. Returns the created recipient. # Delete a recipient Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipients-delete reference/core-api.json DELETE /v2/recipients/{id} Deletes a recipient in Chile or Mexico. Returns an empty response. Subsequent requests for the recipient return `404 Not Found`. # List recipients Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipients-list reference/core-api.json GET /v2/recipients Lists recipients in your organization for the `live` or `test` mode of your API key, newest first. Filters apply in Chile and Mexico. Returns a paginated array of recipient objects. Use the `Link` response header to navigate pages. # Get a recipient Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipients-retrieve reference/core-api.json GET /v2/recipients/{id} Returns a recipient in your organization for the `live` or `test` mode of your API key. Available in Chile and Mexico. # Update a recipient Source: https://docs.fintoc.com/api/business-accounts-api/recipients/recipients-update reference/core-api.json PATCH /v2/recipients/{id} Updates recipient details in Chile and Mexico. You can update `account_type` only in Chile. The `account_number`, `institution_id`, and `holder_id` fields cannot change. Omitted fields keep their current values. Send `null` or a blank string to clear `alias` or `email`. Returns the updated recipient. # Simulate receiving a transfer Source: https://docs.fintoc.com/api/business-accounts-api/simulation/transfers-simulate-receive reference/core-api.json POST /v2/simulate/receive_transfer Test-mode helper that simulates an inbound transfer into one of your account numbers, so you can exercise incoming-transfer flows. Only available with a `test` API key. # Transfer batch object Source: https://docs.fintoc.com/api/business-accounts-api/transfer-batches/transfer-batch-object Fields of the `TransferBatch` object, which groups up to 5,000 outbound transfers for one Dashboard approval, plus the batch statuses. ## The Transfer Batch object A `TransferBatch` groups up to 5,000 outbound transfers that you create in one request and approve once from the Dashboard. You create a `TransferBatch` with [Create a transfer batch](/api/business-accounts-api/transfer-batches/transfer-batches-create) or from the Dashboard. Fintoc sends the transfers in the batch only after you approve the batch from the Dashboard. To read those transfers, call [List transfers](/api/business-accounts-api/transfers/transfers-list) with the `transfer_batch_id` query parameter. The `TransferBatch` object has these fields: | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier of the transfer batch. | | `object` | `string` | Type of the object. Always `transfer_batch`. | | `amount` | `integer` | Sum of the amounts of the transfers in the batch, in the smallest currency unit (for example, centavos for MXN). CLP has no minor unit, so the value is the number of pesos. | | `authorized_at` | `string` or `null` | ISO 8601 datetime in UTC of when you approved the batch from the Dashboard. `null` until you approve the batch. | | `created_at` | `string` | ISO 8601 datetime in UTC of when you created the batch. | | `currency` | `string` | Currency of the transfers in the batch. One of `CLP` or `MXN`. | | `description` | `string` | Human-readable label for the batch. Up to 40 characters. | | `expired_at` | `string` or `null` | ISO 8601 datetime in UTC of when the batch expired without approval. `null` unless `status` is `expired`. | | `mode` | `string` | Mode of the API. One of `test` or `live`. | | `partially_succeeded_at` | `string` or `null` | ISO 8601 datetime in UTC of when the batch finished with some successful transfers and some failed transfers. `null` unless `status` is `partially_succeeded`. | | `rejected_at` | `string` or `null` | ISO 8601 datetime in UTC of when you rejected the batch from the Dashboard. `null` unless `status` is `rejected`. | | `settled_amount` | `integer` | Sum of the `settled_amount` of the transfers in the batch, in the smallest currency unit. | | `status` | `string` | Status of the batch. One of `pending_authorization`, `rejected`, `expired`, `in_progress`, `succeeded`, `partially_succeeded`, or `failed`. See [Batch statuses](#batch-statuses). | | `succeeded_at` | `string` or `null` | ISO 8601 datetime in UTC of when every transfer in the batch succeeded. `null` unless `status` is `succeeded`. | | `succeeded_count` | `integer` | Number of transfers in the batch that succeeded. | | `transfer_count` | `integer` | Number of transfers in the batch. | For example, a batch where every transfer succeeded looks like this: ```json Transfer batch object theme={null} { "id": "trbatch_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "object": "transfer_batch", "amount": 150000, "authorized_at": "2026-03-01T12:05:00Z", "created_at": "2026-03-01T12:00:00Z", "currency": "MXN", "description": "Supplier payouts March", "expired_at": null, "mode": "test", "partially_succeeded_at": null, "rejected_at": null, "settled_amount": 150000, "status": "succeeded", "succeeded_at": "2026-03-01T12:20:00Z", "succeeded_count": 3, "transfer_count": 3 } ``` ### Batch statuses A batch moves through these statuses: | Status | Description | | :- | :- | | `pending_authorization` | The batch waits for your approval in the Dashboard. | | `rejected` | You rejected the batch in the Dashboard. Fintoc sends no transfers. | | `expired` | Nobody approved the batch within two weeks. Fintoc sends no transfers. | | `in_progress` | You approved the batch, and Fintoc is sending its transfers. | | `succeeded` | Every transfer in the batch succeeded. | | `partially_succeeded` | Some transfers in the batch succeeded, and the rest failed. | | `failed` | No transfer in the batch succeeded. | Fintoc sends a `transfer_batch.*` webhook event when a batch moves to any status after `pending_authorization`. See [Types of events](/api/main-resources/events-reference/types-of-events). # Create a transfer batch Source: https://docs.fintoc.com/api/business-accounts-api/transfer-batches/transfer-batches-create reference/core-api.json POST /v2/transfer_batches Creates a batch of outbound transfers from your accounts, in the `live` or `test` mode of the API key used. The batch starts in `pending_authorization` and Fintoc sends its transfers only after you approve the batch from the Dashboard. An approved batch moves to `in_progress`. Requirements differ by country. In Chile, the currency is `CLP` and each counterparty needs a `holder_id`, which is the Chilean tax ID (RUT), a `holder_name`, an `account_type`, and an `institution_id`. In Mexico, the currency is `MXN` and each counterparty's `account_number` can be a standardized Mexican bank account number (CLABE), debit card, or phone number. When `account_number` is a debit card or phone number, the counterparty also needs an `institution_id`. To read the transfers of the batch, call `GET /v2/transfers` with the `transfer_batch_id` query parameter. Requires a JSON Web Signature (JWS) in the `Fintoc-JWS-Signature` header. # List transfer batches Source: https://docs.fintoc.com/api/business-accounts-api/transfer-batches/transfer-batches-list reference/core-api.json GET /v2/transfer_batches Lists the transfer batches of your organization in the `live` or `test` mode of the API key used, including the batches created from the Dashboard. Filter by `status`, or by creation date range with `since` and `until`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to page through it. The `Link` response header carries the URLs to navigate the pages. To read the transfers of a batch, call `GET /v2/transfers` with the `transfer_batch_id` query parameter. # Get a transfer batch Source: https://docs.fintoc.com/api/business-accounts-api/transfer-batches/transfer-batches-retrieve reference/core-api.json GET /v2/transfer_batches/{id} Gets a transfer batch for your organization by ID. A batch in `in_progress` was approved from the Dashboard and its transfers are being sent. To read the transfers of the batch, call `GET /v2/transfers` with the `transfer_batch_id` query parameter. # SPEI codes Source: https://docs.fintoc.com/api/business-accounts-api/transfers/spei-codes Return causes and codes for Mexican SPEI transfers, mapping each `return_reason` and `return_reason_code` to its meaning and response. # Return causes and codes When an inbound or outbound SPEI transfer is returned, the `return_reason` describes why. The following table lists the return causes and codes, along with what to do for each one. | return\_reason | return\_reason\_code | Description | | - | - | - | | `non_existing_account` | `01` | The destination account number does not exist. Check if the number is correct. | | `blocked_account` | `02` | The destination account is blocked. Check with the account holder for details or a new account. | | `canceled_account` | `03` | The destination account is closed. Check with the account holder for details or a new account. | | `wrong_currency` | `05` | The destination account is in a different currency than your origin account. Use an account in the same currency. | | `non_fintoc_account` | `06` | The destination account and institution don't match. Confirm you are using the correct institution. | | `wrong_operation_type` | `16` | Error in the code or type of operation being attempted. | | `account_type_does_not_correspond` | `17` | The destination account does not receive SPEI transfers. Try with a different account. | | `exceeds_account_limit` | `20` | The recipient account has reached its holding limit. Try again later. | | `exceeds_account_monthly_payments_limit` | `21` | The recipient account has reached its monthly limit. Try again later. | | `non_registered_mobile_phone` | `22` | The recipient's mobile phone number is not registered. Confirm the number or use a different account. | | `missing_payment_instruction_due_to_balance_limit_reached` | `25` | The destination account does not receive SPEI transfers. Try with a different account. | | `sender_client_protection_agreement` | `26` | The receiving bank has implemented a rule that prevents it from accepting payments from certain issuing participants or under certain conditions. Try with a different account. | | `optional_payment_not_accepted_by_recipient_institution` | `27` | The transfer attempted to use an additional payment type that the receiving bank does not support. | # Transfer object Source: https://docs.fintoc.com/api/business-accounts-api/transfers/transfer-object Fields on the `Transfer` object that records inbound and outbound bank transfers, including `counterparty`, `direction`, `status`, `amount`, and return details. ## The Transfer object A `Transfer` represents a movement of funds into or out of one of your accounts. You receive a `Transfer` object when an inbound transfer lands on an `AccountNumber` (CLABE, the standardized Mexican bank account number) you own. You create a `Transfer` when you initiate an outbound transfer from one of your `Accounts`. Each `Transfer` references the `AccountNumber` it settled against and the `Counterparty` on the other side of the rail. ```json Transfer object theme={null} { "id": "tr_jKaHD105H", "object": "transfer", "account_number": { "id": "acno_Kasf91034gj1AD", "object": "account_number", "account_id": "acc_Jas92lf9adg94ka", "created_at": "2024-03-01T20:09:42.949787176Z", "description": "Mis payins", "metadata": { "id_cliente": "12343212" }, "mode": "test", "number": "000000000000000000" }, "amount": 2864, "comment": "Pago de gas", "counterparty": { "account_number": "000000000000000000", "account_type": "clabe", "email": null, "holder_id": "AAA010101AAA", "holder_name": "Test Customer 1", "institution": { "id": "mx_banco_bbva", "country": "mx", "name": "BBVA Mexico" } }, "currency": "MXN", "direction": "inbound", "metadata": {}, "mode": "test", "post_date": "2020-04-17T00:00:00.000Z", "receipt_url": "https://www.banxico.org.mx/cep/example", "reference_id": "130824", "return_reason": null, "settled_amount": 2864, "status": "succeeded", "tracking_key": "TEST0000000000000001", "transaction_date": "2020-04-17T05:12:41.462Z" } ``` | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the transfer. | | `object` | `string` | Type of the object. Always `transfer`. | | `account_number` | `object` | The [AccountNumber](/api/business-accounts-api/account-numbers/account-number-object) you used to send or receive this transfer. | | `amount` | `integer` | Amount of the transfer in the smallest currency unit (for example, centavos for MXN). CLP has no minor unit, so the value is the number of pesos. For Chilean outbound transfers over `7000000` CLP, Fintoc splits the transfer into parts and sends them one after another. The transfer stays `pending` longer than a single transfer. See [Large transfers in Chile](/guides/business-accounts/outbound-transfers#large-transfers-in-chile). | | `comment` | `string` | A comment or reference describing the transfer, up to 40 characters. For outbound transfers, you provide it; for inbound transfers, you see what the sender wrote. When Fintoc splits a Chilean transfer, this field keeps the comment you sent, while each part's comment carries an `X de N` suffix. | | `counterparty` | `object` | Information about the counterparty: the party sending you the funds if inbound, or the party you are paying if outbound. | | `currency` | `string` | Currency of the transfer, in [ISO 4217 format](https://www.iso.org/iso-4217-currency-codes.html), for example `MXN`. | | `direction` | `string` | Either `inbound` if you are receiving a transfer to your `AccountNumber`, or `outbound` if you are sending a transfer from your `Account`. | | `metadata` | `object` | Set of key-value pairs you can attach to the object. Useful for storing additional information about the object in a structured format. | | `mode` | `string` | Mode of the API. One of `test` or `live`. | | `post_date` | `string` | ISO 8601 datetime in UTC of when the transfer was posted. | | `receipt_url` | `string` | A URL to the receipt of the transfer, if available. | | `reference_id` | `string` | A unique reference ID for the transfer, used for reconciliation purposes. | | `return_reason` | `string` or `null` | Reason the transfer was returned. `null` unless `status` is `returned`. See the full list of [Sistema de Pagos Electrónicos Interbancarios (SPEI) return codes](/api/business-accounts-api/transfers/spei-codes). | | `settled_amount` | `integer` | Settled portion of the transfer, in the smallest currency unit. Equals `amount` when `status` is `succeeded`, the sum of the settled parts when `status` is `partially_succeeded`, and `0` for every other status. | | `status` | `string` | The status of the transfer. One of `pending`, `succeeded`, `rejected`, `failed`, `returned`, `return_pending`, `reject_failed`, `partially_succeeded`, `reverse_pending`, or `reversed`. The `partially_succeeded` status is available for Chilean outbound transfers only. The `reverse_pending` and `reversed` statuses are available for Chilean transfers only. | | `tracking_key` | `string` | The unique tracking key for the transaction provided by the banking system. | | `transaction_date` | `string` | ISO 8601 datetime in UTC of when the transfer was initiated. | ### The Counterparty object (within the Transfer object) The `Counterparty` object describes the party on the other side of the transfer, the sender if inbound or the payee if outbound. The `Counterparty` object appears in the `counterparty` field of the `Transfer` object. | Field | Type | Description | | :- | :- | :- | | `account_number` | `string` | Account number of the counterparty. In Mexico, this is a standardized Mexican bank account number (CLABE). | | `account_type` | `string` | Type of the counterparty account. In Mexico, one of `clabe`, `debit_card`, or `phone_number`. In Chile, one of `checking` or `sight`. | | `email` | `string` or `null` | Email of the counterparty. `null` when not provided. | | `holder_id` | `string` | Tax identifier of the counterparty. In Mexico, a Mexican tax ID (RFC). | | `holder_name` | `string` | Name of the counterparty. | | `institution` | `object` | The institution object containing details about the counterparty's financial institution. | ### The Institution object (within the Counterparty object) The `Institution` object identifies the counterparty's financial institution, and it appears in the `institution` field of the `Counterparty` object. | Field | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the institution. See [Chile Institution Codes](/api/fintoc-api/chile-institution-codes) or [Mexico Institution Codes](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). | | `country` | `string` | Country where the financial institution is located, in ISO 3166-1 alpha-2 format, for example `mx` for Mexico. | | `name` | `string` | Name of the financial institution. | # Create a transfer Source: https://docs.fintoc.com/api/business-accounts-api/transfers/transfers-create reference/core-api.json POST /v2/transfers Creates an outbound transfer from one of your accounts, in the `live` or `test` mode of the API key used. Requirements differ by country. In Chile, the currency is `CLP` and the counterparty needs a `holder_id`, which is the Chilean tax ID (RUT), and an `institution_id`. In Mexico, the currency is `MXN` and the counterparty's `account_number` is a standardized Mexican bank account number (CLABE). Requires a JSON Web Signature (JWS) in the `Fintoc-JWS-Signature` header. # List transfers Source: https://docs.fintoc.com/api/business-accounts-api/transfers/transfers-list reference/core-api.json GET /v2/transfers Lists the transfers of your organization in the `live` or `test` mode of the API key used. Filter by `account_id`, `account_number_id`, `direction`, `status`, `tracking_key`, and `transfer_batch_id`, or by date range with `since` and `until`. The list is paginated. Use the `starting_after`, `ending_before`, and `limit` query parameters to page through it. The `Link` response header carries the URLs to navigate the pages. # Get a transfer Source: https://docs.fintoc.com/api/business-accounts-api/transfers/transfers-retrieve reference/core-api.json GET /v2/transfers/{id} Retrieves the details of a transfer of your organization, by its ID. # Return a transfer Source: https://docs.fintoc.com/api/business-accounts-api/transfers/transfers-return reference/core-api.json POST /v2/transfers/return Returns an inbound transfer to its original sender. You can only return `MXN` transfers. Requires a JSON Web Signature (JWS) in the `Fintoc-JWS-Signature` header. # Account object Source: https://docs.fintoc.com/api/movements-api/accounts/accounts-object ## The Account object An `Account` represents a single bank account held by a user at a financial institution, including its type, holder, currency, and balance. It appears within the `accounts` array of a `Link` and reflects the data retrieved from the institution on the last refresh. ```json Account Object theme={null} { "id": "acc_nMNejK7BT8oGbvO4", "object": "account", "balance": { "available": 500000, "current": 500000, "limit": 500000 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "Test Customer 1", "name": "Cuenta Corriente", "next_refresh": "2020-11-18T22:43:54.591Z", "number": "0000000000", "official_name": "Cuenta Corriente Moneda Local", "refresh_status": "refreshing", "refreshed_at": "2020-11-18T18:43:54.591Z", "removed_from_link": false, "type": "checking_account" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Account | | `object` | `string` | Identifier for the type of object. Its value for `Account` will always correspond to `account` | | `balance` | `object` | Account balance | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | `holder_id` | `string` | Account owner's tax ID. In Chile, this value is a Chilean tax ID (RUT). In Mexico, this value is a Mexican tax ID (RFC). | | `holder_name` | `string` | Name of the owner of the account | | `name` | `string` | Standardized name of the account | | `next_refresh` | `string` | `Account`'s next update date using ISO 8601. If the account is removed, it will be `null` | | `number` | `string` | Account number. Does not include hyphens nor prefixed zeros | | `official_name` | `string` | Name of the account used by the institution | | `refresh_status` | `string` | Status of the `Account`. It can take the values: `starting`, `refreshing`, or `interrupted`. | | `refreshed_at` | `string` | `Account`'s last update date, using ISO 8601. If the account has never been updated, it will be `null` | | `removed_from_link` | `boolean` | Is `true` when the `Account` has been removed from the `Link`. Else is `false`. | | `type` | `string` | Type of account. Learn more by looking at the available account types table below | ### The Balance object The `Balance` object holds the monetary amounts for an account. It appears in the `balance` field of the `Account` object. | Attribute | Type | Description | | :- | :- | :- | | `available` | `integer` | Available amount in the account, according to the bank. When looking at accounts with types within `checking_account`, `savings_account`, `sight_account` and `rut_account`, the `available` attribute **does not** include the amount of money that the line of credit provides (if it exists). When looking at accounts with type `line_of_credit`, generally the `available` attribute value is equal to the limit of the line of credit, minus the accounting amount | | `current` | `integer` | Accounting amount of the Account | | `limit` | `integer` | When looking at accounts with types within `checking_account`, `savings_account`, `sight_account` and `rut_account`, the `limit` attribute is equal to the available amount plus the amount available on the associated line of credit (if it exists). When looking at accounts with type `line_of_credit`, the `limit` attribute corresponds to the approved amount for that line of credit | > [!WARNING] > > For **Santander** accounts with type `checking_account`, the used amount from the line of credit will be deducted from the available amount. ## Account types | Type | Description | | :- | :- | | `checking_account` | Checking account | | `savings_account` | Savings account | | `sight_account` | Sight account | | `line_of_credit` | Line of credit | | `credit_card` | Credit card | # Link intent object Source: https://docs.fintoc.com/api/movements-api/linkintents/link-intent-object This represents your user connection attempt. ## The Link Intent object A `Link Intent` represents your end user's attempt to connect a financial account through the Fintoc Widget. You create one to start the connection flow, and once the user finishes successfully, you exchange its `exchange_token` for the resulting `Link`. > [!NOTE] > > **Connect a test account** > > To connect an account in Test Mode, see our [Testing Guide](/guides/movements/data-aggregation-test-your-integration) ```json Link Intent Object theme={null} { "id": "li_a6WUojQ2SjSSeFjH", "object": "link_intent", "country": "cl", "created_at": "2022-12-01T01:50:12Z", "exchange_token": "li_a6WUojQ2SjSSeFjH_exchange_token_5bgMY0PHd7NaUkboxXObu30HNhRqoc1Z", "exchange_token_expires_at": "2022-12-01T02:20:12Z", "holder_type": "individual", "mode": "live", "product": "movements", "status": "created", "widget_token": "li_a6WUojQ2SjSSeFjH_sec_Q802GD8ZLmMuK0Atl4ucJuLp" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Link Intent | | `object` | `string` | Identifier of the object type. Its value for `Link Intent` will always correspond to `link_intent` | | `country` | `string` | ISO Code (Alpha-2) of the country. Currently only `cl` is supported | | `created_at` | `string` | When the Link Intent was created | | `exchange_token` | `string` | Temporary token that can be used to retrieve Link information when your user connection is `succeeded` | | `exchange_token_expires_at` | `string` | When the `exchange_token` will expire | | `holder_type` | `string` | Indicates whether the account to be connected is an `individual` or a `business` | | `mode` | `string` | Indicates whether the Link Intent is in `live` mode or `test` mode. Currently only `live` is supported | | `product` | `string` | Product that will be used with this connection. Currently only `movements` is supported | | `status` | `string` | Link Intent current status. | | `widget_token` | `string` | Temporary token to configure the widget. This attribute is only returned when creating the Link Intent. After that, it will always be `null` | # Link object Source: https://docs.fintoc.com/api/movements-api/links/link-object ## The Link object A `Link` represents a connection between an end user and a financial institution, granting access to the bank accounts the user holds at that institution. It is created when a user completes the Fintoc Widget flow, and it groups the associated `Account` objects along with their refresh status. ```json Link Object theme={null} { "id": "link_nMNejK7BT8oGbvO4", "object": "link", "accounts": [ { "id": "acc_Z6AwnGn4idL7DPj4", "object": "account", "balance": { "available": 7010510, "current": 7010510, "limit": 7510510 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "Test Customer 1", "name": "Cuenta Corriente", "number": "0000000000", "official_name": "Cuenta Corriente Moneda Local", "type": "checking_account" }, { "id": "acc_BO381oEATXonG6bj", "object": "account", "balance": { "available": 500000, "current": 500000, "limit": 500000 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "Test Customer 1", "name": "Línea de Crédito", "number": "00000000000", "official_name": "Linea De Credito Personas", "type": "line_of_credit" } ], "active": true, "created_at": "2020-04-22T21:10:19.254Z", "holder_id": "111111111", "holder_type": "individual", "institution": { "id": "cl_banco_de_chile", "country": "cl", "name": "Banco de Chile" }, "last_time_refreshed": "2020-04-22T23:10:19.254Z", "link_token": "link_nMNejK7BT8oGbvO4_token_GLtktZX5SKphRtJFe_yJTDWT", "mode": "test", "refresh_status": "refreshing", "status": "active", "username": "111111111" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Link | | `object` | `string` | Identifier for the type of object. Its value for `Links` will always correspond to `link` | | `accounts` | `array` | Accounts associated with the `Link`. See the [Account object](/api/movements-api/accounts/accounts-object) for details. Fintoc includes this field when you exchange a link token or get a single `Link`, and returns `null` when you list links. | | `active` | `boolean` | Indicates if Fintoc refreshes the `Link`'s bank accounts automatically. When you deactivate a `Link` (`false`), Fintoc excludes it from automatic refreshes and stops billing it. Deactivating a `Link` doesn't switch it to [on-demand refreshes](/guides/movements/refresh-intents-walkthrough). | | `created_at` | `string` | `Link`'s creation date, using ISO 8601 | | `holder_id` | `string` | Identifier of the owner of the accounts held under the Link. In Chile, it corresponds to a RUT. In Mexico, it corresponds to a RFC | | `holder_type` | `string` | Indicates whether the account owner is an `individual` or a `business` | | `institution` | `object` | Financial institution associated to the `Link` | | `last_time_refreshed` | `string` | Last time the link was refreshed considering its bank accounts. | | `link_token` | `string` | Token to be used to make requests for resources nested under a `Link` (for example, bank movements). This attribute will only be returned when creating a `Link`. After that, this field will always be `null`. | | `mode` | `string` | Indicates whether the `Link` is in `live` mode or in `test` mode (for the sandbox) | | `refresh_status` | `string` | Refresh status of the `Link`. Its values can be: `idle`, `refreshing`, `partially_refreshing`, or `interrupted` | | `status` | `string` | Indicates if the `Link` needs to be reconnected (`login_required`) or if it is being updated with no problems (`active`). If the `Link` has been deactivated, this value will correspond to `inactive` | | `username` | `string` | Name of the user for the bank's platform. In Chile, it always corresponds to a RUT. | # List links Source: https://docs.fintoc.com/api/movements-api/links/links-list reference/main-api.json GET /v1/links Returns a paginated list of the links of your organization, in the `live` or `test` mode of the API key used. `link_token` and `accounts` are always `null` when listing links. > [!NOTE] > > **Accounts** > > The `accounts` field is `null` when you list links. To retrieve a link's accounts, send a request to the [Get link](/api/movements-api/links/links-get) endpoint using the `link_token` returned when you exchanged the link. > [!NOTE] > > **Pagination** > > The API paginates links and returns 30 links per page by default. See [Pagination](/api/fintoc-api/pagination) for details. Increment the `page` query parameter to retrieve the remaining links. # Update a link Source: https://docs.fintoc.com/api/movements-api/links/links-update reference/main-api.json PATCH /v1/links/{id} Updates a link using its `link_token` as identifier. You can update only the `active` field: Fintoc stops refreshing deactivated links. > [!NOTE] > > **Important** > > Fintoc bills you only for active `Link` objects. Set `active` to `false` to deactivate a `Link`. Fintoc then stops refreshing it automatically. This isn't a way to keep the `Link` available for on-demand refreshes only. To create [Refresh Intents](/guides/movements/refresh-intents-walkthrough), your organization needs on-demand refreshes enabled. # Movement object Source: https://docs.fintoc.com/api/movements-api/movements/movements-object Reference for the Movement object in Fintoc's Movements API, representing a single bank account transaction such as a transfer, check, debit, or credit. ## The Movement object A `Movement` represents a single transaction in a bank account, such as a transfer, a check, or another debit or credit. It is retrieved from an institution for an account under a `Link` and is returned when you list or fetch movements. ```json Movement Object theme={null} { "id": "mov_BO381oEATXonG6bj", "object": "movement", "amount": 59400, "comment": "Pago factura 198", "currency": "CLP", "description": "Traspaso de:Fintoc SpA", "document_number": null, "pending": false, "post_date": "2020-04-17T00:00:00.000Z", "recipient_account": null, "reference_id": "123740123", "sender_account": { "holder_id": "111111111", "holder_name": "Test Company 1", "institution": { "id": "cl_banco_de_chile", "country": "cl", "name": "Banco de Chile" }, "number": "0000000000" }, "status": "confirmed", "transaction_date": "2020-04-16T11:31:12.000Z", "transfer_id": null, "type": "transfer" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Movement | | `object` | `string` | Identifier for the type of object. Its value for `Movements` will always correspond to `movement` | | `amount` | `integer` | Movement amount in the smallest currency unit. Positive values increase the account balance, and negative values decrease it. | | `comment` | `string` | If the movement is a transfer, this attribute indicates the transfer comment. It can be `null` | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | `description` | `string` | Description for the movement, retrieved from the institution | | `document_number` | `string` or `null` | Document number the institution assigns to the movement. `null` when the institution does not provide a document number. | | `pending` | `boolean` | If the movement is a check, this field indicates whether the bank has yet to clear the check. If the movement isn't a check, this attribute is `false`. `pending` is independent of `status`. See [`pending` and `status`](#pending-and-status). | | `post_date` | `string` | Movement's accounting date, using ISO 8601. This field holds a date only, so its time component is always `00:00:00.000Z`. | | `recipient_account` | `object` | Account that received the transfer. This field is `null` when the movement is not a transfer. See the Transfer Account object table below for details. | | `reference_id` | `string` | Identifier retrieved from the institution. For transfers, this value is the operation number or transaction `id`. If the bank does not provide a transaction `id`, Fintoc uses the document number. For checks, this value is the document number. It can be `null`. | | `sender_account` | `object` | Account that made the transfer. This field is `null` when the movement is not a transfer. See the Transfer Account object table below for details. | | `status` | `string` | Status of the movement. Its values can be `confirmed`, `processing`, or `reversed`. See [Movement status](#movement-status). | | `transaction_date` | `string` | Date and time the institution reports for the movement, using ISO 8601. It can be `null` when the movement is not a transfer. See the note below for details. | | `transfer_id` | `string` or `null` | Identifier the institution assigns to the transfer. `null` when the movement is not a transfer or no transfer identifier is available. | | `type` | `string` | Type of movement. Its values can be `transfer`, `check` or `other` | > [!NOTE] > > **Post date and transaction date** > > Each movement includes `post_date` and `transaction_date` because banks use accounting dates internally. A transaction made on a Saturday can appear with Monday as its `post_date`. In that case, Saturday is the `transaction_date`, and Monday is the `post_date`. > > The `post_date` field is a date without a time, so Fintoc always returns it at `00:00:00.000Z`. Don't convert it to your local time zone, because the conversion can shift it to the previous day. > > The `transaction_date` field includes the time the institution reports. Depending on the institution, Fintoc can return Chilean local time with a `Z` suffix instead of a true UTC time. Check the values you receive for each institution before you convert `transaction_date` to another time zone. > > Fintoc doesn't set `transaction_date` to the time it reads the movement. The value always comes from the bank. How reliable it is depends on the movement `type`: > > * For `transfer` movements, `transaction_date` usually matches the time the payment was made. > * For `other` movements, the bank might not report a time for each operation. The value can be the time of a bank batch or accounting process, so more than one movement can share the same timestamp. Don't present it as the time the payer made the transfer. Use `post_date` as the accounting date instead. > > `transaction_date` can also change when the bank updates the movement. See [Movements can change after creation](#movements-can-change-after-creation). > [!NOTE] > > **Pending checks** > > The bank can take up to 48 business hours to confirm a check. The bank can reverse a pending check, for example because of lack of funds. Fintoc marks these checks with the `pending` flag so you know that the bank hasn't cleared them yet. The `pending` flag doesn't change the movement's `status`. ### Movement status The `status` field indicates the current state of a movement. Most movements are `confirmed`. A movement can move to `processing` or `reversed` as Fintoc processes and validates the bank's data. By default, [List movements](/api/movements-api/movements/movements-list) returns only `confirmed` movements. Send `confirmed_only=false` to also get `processing` and `reversed` movements. | Status | Description | | :- | :- | | `confirmed` | The bank has confirmed the movement, but the movement can still change. This is the default status for all movements; see [Movements can change after creation](#movements-can-change-after-creation). | | `processing` | The movement is being evaluated and may change to `confirmed` or `reversed`. This is a transitory status that typically resolves within 12 hours. | | `reversed` | The movement was reversed by the bank. The original transaction has been undone. | ### `pending` and `status` `pending` and `status` are separate fields, and each one answers a different question: * `pending` applies only to checks. It is `true` while the bank has yet to clear the check. For any other type of movement, it is always `false`. * `status` applies to every movement. It tells you whether the movement is `confirmed`, `processing`, or `reversed`. A check can have `pending` set to `true` and `status` set to `confirmed`. Movements you stored earlier don't update on their own. Request the movement again to get its current `pending` and `status` values. ### Movements can change after creation The bank can update movements in the account statement after they first appear. These updates can arrive days or weeks after Fintoc first returns the movement. Fintoc keeps the same movement `id` when a movement changes. Fields that can change include: * `type`. For example, a check deposit can first appear with `type` set to `other` and later change to `check`. * `description`. * `status` and `pending`. A `confirmed` movement isn't guaranteed to be final. The bank can still reverse it. * Transfer data in `sender_account` and `recipient_account`. * `transaction_date`. For example, when a movement changes from `other` to `transfer`, `transaction_date` can change to a different time or back to `null`. To keep your records in sync: 1. Subscribe to the `account.refresh_intent.movements_modified` and `account.refresh_intent.movements_removed` events. See [Types of events](/api/main-resources/events-reference/types-of-events). 2. When you receive `movements_modified`, take the `id` of each movement in `movements_changed`. Request the movement with [Get a movement](/api/movements-api/movements/movements-get) and replace your stored copy with the response. 3. When you receive `movements_removed`, remove the movements whose `id` appears in `movements_removed` from your records. 4. Periodically list the current month's movements again and replace your stored copies by `id`. Use the movement `id` as the key for your stored records. Don't match on `type` or `description`, because they can change. ### Deposits with more than one check or document Fintoc reads movements from the bank account statement. When you deposit more than one check or document together, the bank lists the deposit as a single line. Fintoc returns that line as one movement for the total amount. The Movements API doesn't return a breakdown of the individual checks or documents in the deposit, and no field, parameter, or endpoint provides one. The `type` of a deposit depends on what you deposited: * Deposits of checks or documents have `type` set to `check`. * Cash deposits have `type` set to `other`. If you filter movements by `type`, include both values so you don't miss deposits. The bank can later split a deposit into its individual items. When Fintoc detects the split: 1. Fintoc changes the aggregated movement's `status` to `reversed` and sends an `account.refresh_intent.movements_removed` event with the aggregated movement's `id` in `movements_removed`. 2. Fintoc creates one movement for each individual item and counts them in the `new_movements` field of the `account.refresh_intent.succeeded` event. See [Types of events](/api/main-resources/events-reference/types-of-events). To reconcile deposits, match a deposit to the total amount of its items, not to each item. If the aggregated movement changes to `reversed`, remove the aggregated movement from your records and reconcile the individual movements instead. Keeping both records counts the same deposit twice. ### The Transfer Account object (within the Movement object) The Transfer Account object identifies the account on the other side of a transfer, and it appears in the `sender_account` and `recipient_account` fields of a `Movement`. | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Account owner's tax ID. In Chile, this value is a Chilean tax ID (RUT). | | `holder_name` | `string` | Name of the owner of the account | | `institution` | `object` | Institution to which the account belongs. It can be `null` | | `number` | `string` | Account number. Does not include hyphens nor prefixed zeros. It can be `null` | > [!WARNING] > > **Transfer data problems** > > Transfer data can be `null` or incorrect when the movement is not a transfer or when Fintoc cannot match the transfer to the bank statement. Always double-check transfer data before reconciling your movements. All other movement data is **always** reliable. Transfer data can change up to 5 days after Fintoc creates the movement. # Payment link Source: https://docs.fintoc.com/api/payments-api/payment-links/index A payment link is a reusable URL that takes your customers to a hosted payment page. You can share the same payment link with multiple customers. When a customer completes a payment through a payment link, you receive a [`payment_intent.succeeded`](/api/main-resources/events-reference/types-of-events) webhook event. Use this event to track payments made through payment links. Related guide: [Payment Links](/guides/payments/payment-links) # The Payment Link object Source: https://docs.fintoc.com/api/payments-api/payment-links/payment-link-object ## The Payment Link object The `PaymentLink` object represents a shareable `url` that lets a customer pay a fixed `amount` through a Fintoc-hosted page. It appears when you create a payment link, and its `status` field tracks the link as `active`, `expired`, `canceled`, or `completed`. ```json Payment Link Object theme={null} { "id": "plink_K2zwNNSxPyx8w3GZ", "object": "payment_link", "amount": 120900, "checkout": { "description": "Use this field to add a custom description of the product the customer is buying" }, "created_at": "2024-08-02T20:28:13Z", "currency": "MXN", "customer_email": "customer@example.com", "expires_at": "2024-08-02T21:28:13Z", "max_completed_sessions": null, "metadata": { "your_order_id": "10000" }, "mode": "test", "recipient_account": { "holder_id": "555555555", "institution_id": "cl_banco_de_chile", "number": "0000000000", "type": "checking_account" }, "status": "active", "url": "https://pay.fintoc.com/plink_K2zwNNSxPyx8w3GZ" } ``` | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the Payment Link. | | `object` | `string` | Type of the object. Always `payment_link`. | | `amount` | `integer` | Amount to charge, in the smallest currency unit. Must be greater than `0`. | | `checkout` | `object` | Checkout customization shown to your customers. You can add a custom description alongside the buy button. | | `created_at` | `string` | Payment Link's creation date, as an ISO 8601 datetime in UTC. | | `currency` | `string` | Three-letter ISO 4217 currency code, in uppercase. One of `CLP` or `MXN`. | | `customer_email` | `string` or `null` | Email address used for refund notifications. If you create a payment without `customer_email`, this field is `null` and the customer does not receive refund notifications by email. | | `expires_at` | `string` or `null` | Payment Link's expiration date, as an ISO 8601 datetime in UTC. If `null`, the payment link does not expire. | | `max_completed_sessions` | `integer` or `null` | Maximum number of completed checkout sessions. The only non-null value is `1`, which limits the Payment Link to one successful payment. If `null`, the Payment Link is reusable. | | `metadata` | `object` or `null` | Set of [key-value](/api/fintoc-api/metadata) pairs you can attach to the object, useful for storing additional structured information. If you create a payment without `metadata`, this field is `null` when receiving notifications about the final status. | | `mode` | `string` | Indicates whether the Payment Link is in `live` mode or in `test` mode. | | `recipient_account` | `object` | Optional and only available in Chile. Include the recipient account object if your organization uses [Direct Payments](/guides/payments/direct-payments). See [The Recipient object](#the-recipient-object-within-the-payment-link-object). | | `status` | `string` | Payment Link status. One of `active`, `expired`, `canceled`, or `completed`. `completed` means the Payment Link reached its `max_completed_sessions`. | | `url` | `string` | Public URL you can share with customers. | ## The Recipient object (within the Payment Link object) The Recipient object describes the bank account that receives the funds, returned in the `recipient_account` field when your organization uses Direct Payments in Chile. | Attribute | Type | Description | | - | - | - | | `holder_id` | `string` | Identifier of the account holder. In Chile, a Chilean tax ID (RUT); in Mexico, a Mexican tax ID (RFC) or unique population registry code (CURP). | | `institution_id` | `string` | Account's institution `id`. You can learn more about institutions and their `id`s in [Payment initiation countries and institutions](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). | | `number` | `string` | Account number. Does not include hyphens or prefixed zeros. | | `type` | `string` | Account type. One of `checking_account` or `sight_account`. | # Cancel a payment link Source: https://docs.fintoc.com/api/payments-api/payment-links/payment-links-cancel reference/main-api.json PATCH /v1/payment_links/{id}/cancel Cancels an active payment link. A canceled payment link stops accepting payments and cannot be reactivated. Only payment links matching the `live` or `test` mode of the API key can be canceled. # Create a payment link Source: https://docs.fintoc.com/api/payments-api/payment-links/payment-links-create reference/main-api.json POST /v1/payment_links Creates a payment link in the `live` or `test` mode of the API key used. The response includes the `url` of the page where your customer pays. Set `max_completed_sessions` to `1` to close the link after one successful payment. Otherwise, the link is reusable. You can also cancel the link or set `expires_after_seconds` to limit how long the link accepts payments. # Get a payment link Source: https://docs.fintoc.com/api/payments-api/payment-links/payment-links-get reference/main-api.json GET /v1/payment_links/{id} Retrieves a payment link by its `id`. Only payment links matching the `live` or `test` mode of the API key are visible. The API response can contain empty fields. # List payment links Source: https://docs.fintoc.com/api/payments-api/payment-links/payment-links-list reference/main-api.json GET /v1/payment_links Lists the payment links of your organization for the `live` or `test` mode of the API key used. The list is paginated: the `Link` and `X-Total-Count` response headers describe the pagination state. # Payment method object Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-method-object Reference for the Payment Method object, a stored customer payment instrument used to collect on-demand payments or power recurring subscription charges. ## The Payment Method object The `PaymentMethod` object represents a customer's stored payment instrument that you can charge on demand or attach to a subscription for recurring payments. It appears when you create a payment method or when a `CheckoutSession` with a `setup` flow completes. ```json Payment Method Object theme={null} { "id": "pm_4324qwkalsds", "object": "payment_method", "created_at": "2025-07-01T10:00:00.000Z", "customer": "cus_456789abcdef", "mode": "live", "pac": { "account_holder_id": "111111111", "account_number": "0000000000", "account_type": "checking_account", "institution": { "id": "cl_banco_santander", "country": "cl", "name": "Banco Santander" }, "status": "active" }, "type": "pac" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Payment Method. | | `object` | `string` | Type of the object. Always `payment_method`. | | `bank_transfer` | `object` | Present only when `type` is `bank_transfer`. Contains details specific to a bank transfer payment method. | | `card` | `object` | Present only when `type` is `card`. Contains details specific to a card payment method. | | `created_at` | `string` | ISO 8601 datetime in UTC when the payment method was created. | | `customer` | `string` | Customer ID associated with this payment method. | | `mode` | `string` | One of `live` or `test`. | | `mx_direct_debit` | `object` or `null` | Present only when `type` is `mx_direct_debit`. Contains the terms of the Mexican direct debit mandate. `null` when the mandate backing the payment method is no longer available. | | `pac` | `object` | Present only when `type` is `pac`. Contains details specific to a PAC payment method. | | `type` | `string` | Type of the payment method. One of `bank_transfer`, `card`, `mx_direct_debit`, or `pac`. The object includes an additional field named after this value (for example, `card`) with type-specific details. | ### The PAC object The PAC object holds the details of a Pago Automático de Cuentas (PAC), a recurring direct-debit authorization on the customer's bank account. Fintoc returns the PAC object in the `pac` field when the `PaymentMethod` `type` is `pac`. | Attribute | Type | Description | | :- | :- | :- | | `account_holder_id` | `string` | Account owner's tax ID. In Chile, a Chilean tax ID (RUT). | | `account_number` | `string` | Account number. Does not include hyphens or prefixed zeros. | | `account_type` | `string` | Account type. One of `checking_account` or `sight_account`. | | `institution` | `object` | Financial institution associated with the PAC. See [The Institution object](#the-institution-object-within-the-pac-object) below. | | `status` | `string` | PAC authorization status. One of `active` (available to charge), `pending` (awaiting confirmation), or `canceled` (no longer available). | ### The Institution object (within the PAC object) The Institution object identifies the bank that holds the account authorized for the PAC. Fintoc returns the Institution object in the `institution` field of the PAC object. | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Account's institution `id`. You can [learn more about institutions and their `id`s here](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). | | `country` | `string` | Two-letter ISO 3166-1 alpha-2 country code of the institution, in lowercase. For example, `cl` for Chile. | | `name` | `string` | Name of the financial institution. | ### The Card object The `Card` object holds the details of a stored card. Fintoc returns the `Card` object in the `card` field when the `PaymentMethod` `type` is `card`. | Attribute | Type | Description | | :- | :- | :- | | `active` | `boolean` | Whether you can currently charge the card. Fintoc deactivates expired cards automatically. Changes to `false` after you [cancel the payment method](/api/payments-api/payment-methods/payment-methods-cancel). | | `brand` | `string` | Card brand. For example, `visa` or `mastercard`. | | `country` | `string` | Display name of the issuing country, in English. | | `expiration` | `object` | Card expiration date with `month` and `year` strings. `month` uses two digits, and `year` uses four digits. Both values are `null` for cards enrolled through a wallet, such as Apple Pay or Google Pay, because wallets do not expose expiration dates. | | `kind` | `string` | Card kind. One of `credit` or `debit`. | | `last_four_digits` | `string` | Last four digits of the card number. | | `wallet` | `string` or `null` | Wallet used to enroll the card. One of `apple_pay`, `google_pay`, or `null` for cards entered manually. | A card enrolled through a wallet returns the wallet name in `wallet`, for example `apple_pay` or `google_pay`, and `null` values for `expiration.month` and `expiration.year`: ```json Card Payment Method theme={null} { "id": "pm_4324qwkalsds", "object": "payment_method", "card": { "active": true, "brand": "visa", "country": "Chile", "expiration": { "month": null, "year": null }, "kind": "credit", "last_four_digits": "4242", "wallet": "apple_pay" }, "created_at": "2025-07-01T10:00:00.000Z", "customer": "cus_456789abcdef", "mode": "live", "type": "card" } ``` ### The Bank Transfer object The Bank Transfer object holds the details of a bank account enrolled for bank transfer payments. Fintoc returns the Bank Transfer object in the `bank_transfer` field when the `PaymentMethod` `type` is `bank_transfer`. | Attribute | Type | Description | | :- | :- | :- | | `account_holder_id` | `string` | Account owner's tax ID. In Chile, a Chilean tax ID (RUT). | | `account_number` | `string` | Account number. Does not include hyphens or prefixed zeros. | | `account_type` | `string` | Account type. One of `checking_account` or `sight_account`. | | `institution_id` | `string` | Identifier of the financial institution associated with the bank transfer. | | `institution_name` | `string` | Name of the financial institution associated with the bank transfer. | | `mfa_type` | `string` or `null` | Type of multi-factor authentication associated with the account. `null` when the account has no multi-factor authentication. | | `status` | `string` | Status of the payment method. One of `active` (available to charge), `pending` (awaiting confirmation), or `canceled` (no longer available). | ### The MX Direct Debit object The MX Direct Debit object contains the account and mandate terms for Mexican direct debit. Fintoc returns it in `mx_direct_debit` when `type` is `mx_direct_debit`. Follow [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico) to enroll by API or Checkout Session and test the integration. | Attribute | Type | Description | | :- | :- | :- | | `account_holder_id` | `string` | Account holder's Mexican tax ID (RFC). | | `account_number_last4` | `string` | Last four digits of the enrolled bank account or debit card. | | `account_type` | `string` | `clabe` for an 18-digit standardized Mexican bank account number (CLABE), or `debit_card` for a debit card number. | | `consent_source` | `string` | Enrollment path. `api` when you submit consent documents, or `checkout` when your customer authorizes through a Checkout Session. Fintoc assigns this value. | | `error_reason` | `string` or `null` | Reason the mandate isn't `active`. See [MX Direct Debit error reasons](#mx-direct-debit-error-reasons). The field is `null` when the mandate is `active` or Fintoc recorded no reason. | | `institution` | `object` | Bank holding the enrolled account. Contains `id`, lowercase ISO 3166-1 alpha-2 `country`, and `name`. | | `interval` | `string` | Authorization period: `week`, `month`, or `year`. | | `max_amount` | `integer` | Authorized limit per mandate period, in MXN cents. `35000` means \$350.00 MXN. | | `status` | `string` | `pending` (awaiting approval), `active` (can be charged), `rejected` (approval refused), `expired` (approval deadline passed), or `canceled` (authorization ended). Only `active` permits charges. | ```json MX Direct Debit Payment Method theme={null} { "id": "pm_000000001", "object": "payment_method", "created_at": "2026-10-08T12:00:00Z", "customer": "cus_000000001", "mode": "test", "mx_direct_debit": { "account_holder_id": "AAAA010101AAA", "account_number_last4": "0015", "account_type": "clabe", "consent_source": "api", "error_reason": null, "institution": { "id": "mx_banco_bbva", "country": "mx", "name": "Banco BBVA" }, "interval": "month", "max_amount": 35000, "status": "pending" }, "type": "mx_direct_debit" } ``` #### MX Direct Debit error reasons The `error_reason` value depends on the mandate `status`: | `status` | `error_reason` | Description | | :- | :- | :- | | `rejected` | `account_verification_failed` | Fintoc couldn't verify the enrolled account. | | `rejected` | `identity_verification_failed` | Fintoc couldn't verify the holder's identity. | | `rejected` | `consent_document_invalid` | The signed mandate in the consent documents isn't valid. | | `expired` | `verification_expired` | The approval deadline passed while a mandate verification was still in progress. | | `canceled` | `mandate_revoked` | A charge failed because your customer or their bank canceled the mandate, or your customer asked their bank to stop the charges. | | `canceled` | `account_not_found` | A charge failed because the enrolled account doesn't exist or is closed. | | `canceled` | `account_locked` | A charge failed because the bank blocked the enrolled account. | | `canceled` | `account_not_chargeable` | A charge failed because the enrolled account doesn't accept direct debit charges. | | `canceled` | `chargeback` | Fintoc blocked the holder or the account for direct debit after a chargeback. | | `canceled` | `manual_block` | Fintoc manually blocked the holder or the account for direct debit. | Handle unknown values, because Fintoc can add new error reasons. # Cancel a payment method Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-methods-cancel reference/main-api.json POST /v2/payment_methods/{id}/cancel Cancels a payment method so the payment method can no longer be charged. The cancellation applies only to this payment method. The bank account, card, or mandate behind the payment method stays valid for any other payment method that uses the same account, card, or mandate. The canceled payment method reports the cancellation through its type-specific details: `pac.status`, `mx_direct_debit.status`, and `bank_transfer.status` become `canceled`; `card.active` becomes `false`. Fintoc sends a `payment_method.canceled` webhook after processing the cancellation. Canceling an already canceled payment method returns a `409 Conflict` error. If the customer registers the same bank account, card, or mandate again through a new checkout session, Fintoc reactivates the canceled payment method under the same `id`. # Create a payment method Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-methods-create reference/main-api.json POST /v2/payment_methods Enrolls a Mexican direct debit mandate and returns the payment method that represents the mandate. Send the request as `multipart/form-data`, with the mandate fields and the four documents under `mx_direct_debit[consent_documents]` in the same request. Fintoc registers the mandate with the account's bank and returns the payment method with its `mx_direct_debit` status set to `pending`. The account holder authorizes the mandate with their bank. The request is atomic. If a document is invalid, Fintoc creates nothing and returns a `422 Unprocessable Entity` error. A document is invalid if it is outside the 100 bytes to 10 MB range, or is not a PDF, JPEG, or PNG. # Get a payment method Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-methods-get reference/main-api.json GET /v2/payment_methods/{id} Retrieves a payment method by its `id`. Only payment methods of your organization matching the `live` or `test` mode of the API key are visible; anything else returns a `404 Not Found` error. The payment method exposes its details under a key named after its `type` (`bank_transfer`, `card`, `mx_direct_debit`, or `pac`); that key is `null` when the resource backing the payment method is no longer available. # List payment methods Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-methods-list reference/main-api.json GET /v2/payment_methods Lists the payment methods of your organization for the mode (`live` or `test`) of the API key used, sorted by most recently created first. Use `customer` to narrow the list to a single customer, and the cursor parameters (`starting_after`, `ending_before`) together with `limit` to paginate. The `Link` response header contains the URL of the next page. Each payment method exposes its details under a key named after its `type` (`bank_transfer`, `card`, `mx_direct_debit`, or `pac`). # Get a payment method mandate document Source: https://docs.fintoc.com/api/payments-api/payment-methods/payment-methods-mandate-document reference/main-api.json GET /v2/payment_methods/{id}/mandate_document Returns a temporary URL to download the signed mandate contract of a `mx_direct_debit` payment method. The payment method must belong to your organization and match the mode (`live` or `test`) of the API key used. The contract is available regardless of the mandate status, including while the mandate is `pending`. The URL expires 5 minutes after the request. The API never returns the consumer's identity documents. # Payout object Source: https://docs.fintoc.com/api/payments-api/payouts/payout-object ## The Payout object The `Payout` object represents a transfer of collected funds from Fintoc to your bank account. It appears in Payouts API responses and in payout webhook events, and its `status` field tracks the disbursal through `in_progress`, `succeeded`, `canceled`, and `returned`. ```json Payout Object theme={null} { "id": "po_6qMelax3udMp0bDR", "object": "payout", "amount": 49632342, "created_at": "2021-10-15T15:23:11.474Z", "currency": "CLP", "mode": "live", "recipient_account": { "holder_id": "111111111", "institution_id": "cl_banco_security", "number": "0000000", "type": "checking_account" }, "status": "succeeded", "succeeded_at": "2021-10-15T15:24:15.474Z", "updated_at": "2021-10-15T15:23:11.474Z" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the payout. | | `object` | `string` | Type of the object. Always `payout`. | | `amount` | `integer` | Payout amount in the smallest currency unit. Must be greater than `0`. | | `created_at` | `string` | Payout's creation date, using ISO 8601 format. | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html), such as `CLP` or `MXN`. | | `mode` | `string` | Indicates whether the `Payout` is in `live` mode or in `test` mode (for the sandbox). Payouts are only supported in `live`. | | `recipient_account` | `object` | Recipient bank account for the payout. See the Recipient Account object table below for its fields. | | `status` | `string` | Payout status. One of `in_progress`, `succeeded`, `canceled`, or `returned`. | | `succeeded_at` | `string` | Payout's object succeeded date, using ISO 8601 format. | | `updated_at` | `string` | Payout's object last updated date, using ISO 8601 format. | ### Payout statuses | Status | Description | | :- | :- | | `in_progress` | The payout is processing and should arrive to your bank account in the next business day. | | `succeeded` | The payout has been transferred successfully to your account. | | `canceled` | The transfer to your bank account failed, for example because the account details are invalid or the account reached its monthly deposit limit. Fintoc adds the amount to a later payout. See [Canceled payouts](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#canceled-payouts). | | `returned` | The payout has been returned. | ### The Recipient Account object (within the Payout object) The Recipient Account object describes the bank account that receives the funds, returned in the `recipient_account` field of the Payout. | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Account owner's tax ID. In Chile, this value is a Chilean tax ID (RUT). In Mexico, this value is a Mexican tax ID (RFC) or unique population registry code (CURP). | | `institution_id` | `string` | Account's institution `id`. You can learn more about institutions and their `id`s [here](/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions). | | `number` | `string` | Account number. Does not include hyphens or prefixed zeros | | `type` | `string` | Account type. It can be `checking_account` or `sight_account` | # Get a payout Source: https://docs.fintoc.com/api/payments-api/payouts/payouts-get reference/main-api.json GET /v1/payouts/{id} Retrieves a payout by its `id`. Only payouts matching the `live` or `test` mode of the API key are visible. # List payout resources Source: https://docs.fintoc.com/api/payments-api/payouts/payouts-resources-list reference/main-api.json GET /v1/payouts/{id}/resources Lists the resources that a payout disburses or discounts: payment intents, charges, or refunds. The response item schema depends on `resource_type`: `payment_intent` returns payment intents, `charge` returns charges, and `refund` and `refund_adjustment` return refunds. # The Refund object Source: https://docs.fintoc.com/api/payments-api/refunds/refund-object The `Refund` object represents a refund you create against a `PaymentIntent`. Fintoc returns the `Refund` object in Refunds API responses and refund webhook events. The `status` field tracks the refund from `created` to `in_progress`, then to `succeeded`, `failed`, or `canceled`. A `succeeded` refund can later move to `returned` if the recipient's bank returns the transfer. ```json Refund Object theme={null} { "id": "re_3MjTCxEhuqCR3lNz1NgprEoI", "object": "refund", "amount": 100, "created_at": "2021-10-15T15:23:11.474Z", "currency": "CLP", "failure_code": null, "metadata": {}, "mode": "live", "recipient_account": { "holder_id": "111111111", "holder_name": "Test Customer 1", "institution_id": "cl_banco_de_chile", "number": "0000000000", "type": "checking_account" }, "resource_id": "pi_3MjTCxEhuqCR3lNz1FLrtTeH", "resource_type": "payment_intent", "status": "succeeded", "updated_at": "2021-11-15T12:23:11.474Z" } ``` The `Refund` object has the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the refund. | | `object` | `string` | Type of the object. Always `refund`. | | `amount` | `integer` | Amount refunded, in the smallest currency unit. Greater than `0` and at most the original `PaymentIntent` amount. Defaults to the full `PaymentIntent` amount. | | `created_at` | `string` | ISO 8601 datetime in UTC when the refund was created. | | `currency` | `string` | Three-letter ISO 4217 currency code, in uppercase. One of `CLP` or `MXN`. Matches the currency of the original `PaymentIntent`. | | `failure_code` | `string` or `null` | Reason the refund failed. One of `fraud_risk` (blocked by Fintoc's fraud checks) or `insufficient_funds` (your organization has insufficient funds to cover the refund). `null` unless the refund failed. | | `metadata` | `object` | Set of [key-value](/api/fintoc-api/metadata) pairs you can attach to the refund, useful for storing additional structured information. | | `mode` | `string` | One of `live` or `test`. Always matches the original `PaymentIntent`. You cannot create a `test` refund for a `live` `PaymentIntent`, or the reverse. | | `recipient_account` | `object` or `null` | Bank account that receives the refunded funds. `null` for refunds not disbursed by bank transfer, such as card refunds. See [Recipient account](#recipient-account). | | `resource_id` | `string` | ID of the `PaymentIntent` being refunded. | | `resource_type` | `string` | Type of the refunded resource. Always `payment_intent`. | | `status` | `string` | Current status of the refund. One of `created`, `in_progress`, `succeeded`, `returned`, `failed`, or `canceled`. | | `updated_at` | `string` | ISO 8601 datetime in UTC when the refund was last updated. | ### Recipient account The `recipient_account` object has the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Tax ID of the account holder, without dots or hyphens. In Chile, a Chilean tax ID (RUT); in Mexico, a Mexican tax ID (RFC). | | `holder_name` | `string` | Name of the account holder. | | `institution_id` | `string` | Identifier of the account's institution. See [Chile institution codes](/api/fintoc-api/chile-institution-codes). | | `number` | `string` | Account number that receives the refunded funds. | | `type` | `string` | Type of the bank account. One of `checking_account` or `sight_account`. | ### Refund statuses The refund lifecycle includes the following statuses: | Status | Description | | :- | :- | | `created` | Fintoc created the refund. Processing starts at 18:00 on the closest business day. | | `in_progress` | The refund is processing. The funds arrive in your customer's bank account within 1 to 2 business days. | | `succeeded` | Fintoc transferred the refund to your customer's account. | | `returned` | The recipient's bank returned the transfer after the refund succeeded. This status is final. | | `failed` | Processing the refund failed. | | `canceled` | You canceled the refund before processing started. | # Cancel a refund Source: https://docs.fintoc.com/api/payments-api/refunds/refunds-cancel reference/main-api.json POST /v1/refunds/{id}/cancel Cancels a refund by its `id`. Only refunds in `pending` status can be canceled; once Fintoc starts disbursing the funds, the refund cannot be canceled. > [!WARNING] > > You can cancel refunds only when their status is `created`. > [!WARNING] > > **Refunds from e-commerce plugins** > > You can issue refunds directly from VTEX or Shopify. You cannot use the VTEX or Shopify dashboard to cancel refunds that you request through those platforms. > > To cancel a refund requested through VTEX or Shopify, use the [Cancel refund](/api/payments-api/refunds/refunds-cancel) endpoint or contact Fintoc support. The cancellation does not appear in the VTEX or Shopify dashboard. # Get a refund Source: https://docs.fintoc.com/api/payments-api/refunds/refunds-get reference/main-api.json GET /v1/refunds/{id} Retrieves a refund by its `id`. Only refunds matching the `live` or `test` mode of the API key are visible. # List refunds Source: https://docs.fintoc.com/api/payments-api/refunds/refunds-list reference/main-api.json GET /v1/refunds Lists the refunds of your organization for the `live` or `test` mode of the API key used. Use `since`, `until`, and `status` to filter the results. # Get a refund voucher URL Source: https://docs.fintoc.com/api/payments-api/refunds/refunds-voucher reference/main-api.json GET /v1/refunds/{id}/voucher_url Returns a presigned URL to download the PDF voucher of a refund. The URL expires 5 minutes after it is generated. Vouchers are available for succeeded refunds in `live` mode, disbursed by bank transfer or card. > [!WARNING] > > **Voucher URL storage migration** > > Starting **May 4, 2026**, the voucher endpoint returns a Google Cloud Storage presigned URL in the `url` field instead of an Amazon S3 URL. The API behavior and contract remain unchanged. # Setup intent error reason Source: https://docs.fintoc.com/api/payments-api/setup-intents/setup-intent-error-reason The `error_reason` values Fintoc sets when a setup intent fails, with what each error means and which setup methods it applies to: `bank_transfer`, `card`, or `pac`. When a setup intent fails, the `error_reason` attribute on the [Setup Intent object](/api/payments-api/setup-intents/setup-intent-object) identifies the cause. Fintoc uses the following `error_reason` values. Handle unknown values because Fintoc can add new error reasons. The following table maps each error to its setup method types (`bank_transfer`, `card`, or `pac`, an automatic recurring bank debit): | `error_reason` | Description | Setup method | | :- | :- | :- | | `account_type_not_permitted` | The selected account type is not allowed for this setup. | `pac` | | `authentication_failed` | Your customer failed the card issuer's authentication challenge. | `card` | | `authorization_timeout` | Your customer did not authorize the direct debit subscription in time. | `pac` | | `bank_connection_error` | Fintoc had a problem connecting with the selected bank. | `bank_transfer`, `pac` | | `bank_not_available` | The selected bank is temporarily unavailable. | `bank_transfer`, `pac` | | `card_declined` | The card issuer declined the setup. | `card` | | `insufficient_funds` | The account or card does not have enough funds to complete the setup. | `bank_transfer`, `card` | | `internal_error` | An unexpected error occurred while processing the setup. | `bank_transfer`, `pac` | | `invalid_amount` | The card processor did not accept the amount, for example because of a currency conversion overflow. Ask your customer to try another payment method. | `card` | | `invalid_card` | The card is invalid, or your business does not allow this card type. | `card` | | `invalid_card_credentials` | Your customer entered incorrect card details, such as the number, expiration date, or security code. | `card` | | `login_credentials_locked` | The bank locked your customer's credentials after too many failed attempts. | `bank_transfer`, `pac` | | `login_invalid_credentials` | The bank credentials your customer entered are incorrect. | `bank_transfer`, `pac` | | `mfa_authorization_timeout` | Your customer did not complete the bank's multi-factor authentication in time. | `pac` | | `mfa_unavailable` | The bank's multi-factor authentication is not available for your customer. | `pac` | | `password_change_required` | The bank requires your customer to change their password before continuing. | `bank_transfer`, `pac` | | `request_timeout` | The request to the bank timed out. | `bank_transfer`, `pac` | | `subscription_intent_expired` | The underlying subscription intent expired before your customer completed the setup. | `pac` | | `user_left` | Your customer left the widget before completing the setup. | `pac` | # The Setup Intent object Source: https://docs.fintoc.com/api/payments-api/setup-intents/setup-intent-object The `SetupIntent` object represents an attempt by your customer to set up a payment method for future charges without making a payment. A `CheckoutSession` created with the `setup` or `subscription` flow includes the setup intent in `setup_intent`. You can retrieve the setup intent with the [Get setup intent](/api/payments-api/setup-intents/setup-intents-get) endpoint. The object contains the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the `SetupIntent` object. | | `object` | `string` | Type of the object. Always `setup_intent`. | | `error_reason` | `string` or `null` | Error code explaining why the latest setup attempt failed. Returns `null` before an attempt fails and after the setup succeeds. See [Setup intent error reasons](/api/payments-api/setup-intents/setup-intent-error-reason) for the full list. | | `status` | `string` | Setup status with a value of `created`, `started`, `waiting_for_retry`, `succeeded`, or `failed`. The status starts as `created`, moves to `started` while setup is in progress, and moves to `waiting_for_retry` after a retryable failure. The status ends as `succeeded` or `failed`. | ```json Setup Intent Object theme={null} { "id": "seti_2cKoy3PEXAuvkr4ofXC1KdMvCgZ", "object": "setup_intent", "error_reason": "invalid_card", "status": "failed" } ``` # Get a setup intent Source: https://docs.fintoc.com/api/payments-api/setup-intents/setup-intents-get reference/main-api.json GET /v2/setup_intents/{id} Retrieves the setup intent with the given `id`. The setup intent must belong to your organization and match the `live` or `test` mode of the API key used. # The Subscription Item object Source: https://docs.fintoc.com/api/payments-api/subscription-items/subscription-item-object A `SubscriptionItem` represents a single priced line in a subscription. Each item links a price to a quantity and determines what the customer is billed each period. A subscription must always contain at least one item. ```json theme={null} { "id": "si_89abcdef0123", "object": "subscription_item", "price": { "currency": "CLP", "product": { "id": "prod_a7dkfnea", "object": "product", "created_at": "2025-08-01T00:00:00Z", "description": null, "image_url": null, "metadata": {}, "mode": "live", "name": "Pro Plan" }, "recurring": { "interval": "month", "interval_count": 1 }, "unit_amount": 15000 }, "quantity": 2 } ``` | Attribute | Type | Description | | - | - | - | | `id` | string | Unique identifier for the subscription item. | | `object` | string | String representing the object type. Always `subscription_item`. | | `price` | object | Price configuration for this item. | | `price.currency` | string | Three-letter [ISO 4217 currency code](https://www.iso.org/iso-4217-currency-codes.html). One of `CLP`, `MXN`, or `CLF`. Fintoc bills a Unidad de Fomento (UF, `CLF`) price inside a `CLP` subscription and converts it to `CLP` at the start of each billing period. | | `price.product` | object | Product associated with this price. | | `price.product.id` | string | Unique identifier for the product. | | `price.product.object` | string | String representing the object type. Always `product`. | | `price.product.created_at` | string | ISO 8601 timestamp of when the product was created. | | `price.product.description` | string | Description of the product. `null` if not set. | | `price.product.image_url` | string | URL of an image for the product. `null` if not set. | | `price.product.metadata` | object | Set of key-value pairs attached to the product. | | `price.product.mode` | string | `live` or `test`. | | `price.product.name` | string | Name of the product. | | `price.recurring` | object | Recurrence configuration for this price. | | `price.recurring.interval` | string | Billing interval. One of `month` or `year`. | | `price.recurring.interval_count` | integer | Number of intervals between billings. | | `price.unit_amount` | integer | Amount charged per unit in the smallest currency unit. For example, `15000` represents `15,000 CLP`; `35000` represents 3.5 UF, since `CLF` has four decimals. | | `quantity` | integer | Number of units included in each billing period. | # Create a subscription item Source: https://docs.fintoc.com/api/payments-api/subscription-items/subscription-items-create reference/main-api.json POST /v2/subscriptions/{subscription_id}/items Adds an item to an existing subscription. Fintoc creates a new price from `price_data`, referencing an existing product (`product`) or defining one inline (`product_data`). The new price must use a currency compatible with the subscription's existing items (a `CLF` price bills within a `CLP` subscription) and the same recurring `interval`. Fintoc bills the item starting from the subscription's next invoice and does not prorate the current billing period. # Delete a subscription item Source: https://docs.fintoc.com/api/payments-api/subscription-items/subscription-items-delete reference/main-api.json DELETE /v2/subscriptions/{subscription_id}/items/{id} Removes an item from a subscription and returns the deleted item. Fintoc stops billing the item from the subscription's next invoice, with no proration for the current billing period. A subscription must keep at least one item, so its last item cannot be deleted. # Update a subscription item Source: https://docs.fintoc.com/api/payments-api/subscription-items/subscription-items-update reference/main-api.json PATCH /v2/subscriptions/{subscription_id}/items/{id} Updates an item of a subscription. Pass `quantity` to change the number of units, and `price_data` to replace the item's price with a newly created one. When the subscription has other items, the new price must use a currency compatible with theirs (a `CLF` price bills within a `CLP` subscription) and the same recurring `interval`. You can replace the price of a subscription's only item with any currency. Changes take effect on the subscription's next invoice, with no proration for the current billing period. # The Subscription object Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscription-object Reference for the Subscription object, which bills customers on a recurring schedule, groups billable items, and tracks billing cycles and invoices. A subscription bills your customer on a recurring schedule. The subscription groups billable items, tracks the billing cycle, and generates an invoice for each period. The subscription reflects whether billing is active, in a trial, or canceled. ```json theme={null} { "id": "sub_456789abcdef", "object": "subscription", "billing_cycle_anchor": "2025-08-01T00:00:00Z", "collection_method": "charge_automatically", "created_at": "2025-08-01T12:00:00Z", "customer": "cus_01234567", "items": [ { "id": "si_89abcdef0123", "object": "subscription_item", "price": { "currency": "CLP", "product": { "id": "prod_a7dkfnea", "object": "product", "created_at": "2025-08-01T00:00:00Z", "description": null, "image_url": null, "metadata": {}, "mode": "live", "name": "Pro Plan" }, "recurring": { "interval": "month", "interval_count": 1 }, "unit_amount": 15000 }, "quantity": 1 } ], "metadata": {}, "mode": "live", "payment_method": "pm_2c4mDhAbCdEfGhIjKlMnOpQrStu", "reason": null, "status": "trialing", "trial_end": "2025-10-01T00:00:00Z" } ``` | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the subscription. | | `object` | `string` | Type of the object. Always `subscription`. | | `billing_cycle_anchor` | `string` | Reference point used to align future invoices. ISO 8601 datetime in UTC. | | `collection_method` | `string` | One of `charge_automatically` or `send_invoice`. With `charge_automatically`, Fintoc collects each invoice using the attached payment method. With `send_invoice`, Fintoc leaves each invoice open for you to collect. | | `created_at` | `string` | ISO 8601 datetime in UTC when the subscription was created. | | `customer` | `string` | ID of the customer this subscription bills. | | `items` | `array` | List of subscription item objects. See the Subscription Item attributes below. | | `metadata` | `object` | Set of [key-value](/api/fintoc-api/metadata) pairs you can attach to the subscription, useful for storing additional structured information. | | `mode` | `string` | One of `live` or `test`. | | `payment_method` | `string` or `null` | ID of the payment method used to charge this subscription automatically. `null` if no payment method is attached. | | `reason` | `string` or `null` | Why the subscription reports `inconsistent`. `split_amount_mismatch` means the `flat` split amounts don't add up to the items' total, or a `percentage` entry resolves to `0`. Fintoc can't finalize the next invoice until you update the split or the items. See [Split mismatches at finalization](/guides/payments/accept-recurring-payments/split-on-recurring-payments#split-mismatches-at-finalization). The value is `null` for every other status. | | `status` | `string` | One of `active`, `incomplete` (the first invoice payment has not yet succeeded), `trialing` (the trial period has not ended), `inconsistent` (the `split` no longer adds up to the items' total), or `canceled` (the subscription stopped generating invoices). With `send_invoice`, the subscription starts `active` because Fintoc does not start an automatic charge. With `charge_automatically`, the subscription starts `incomplete` and turns `active` once the first payment succeeds. | | `trial_end` | `string` or `null` | ISO 8601 datetime in UTC marking the end of the trial period. `null` if the subscription has no trial. | > [!WARNING] > > With `send_invoice`, Fintoc never contacts your customer. Collecting each invoice is your > responsibility, whether you send its payment link, charge it on demand, or take the money outside > Fintoc. An `active` subscription means Fintoc keeps generating invoices, not that your customer > keeps paying those invoices. Attaching a payment method to a subscription does not change how Fintoc collects its invoices. The collection method changes only through [Update a subscription](/api/payments-api/subscriptions/subscriptions-update). ## Subscription Item | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the subscription item. | | `object` | `string` | Type of the object. Always `subscription_item`. | | `price` | `object` | Price details for this item. See the Price object table below. | | `quantity` | `integer` | Number of units billed. | ### The Price object (within the Subscription Item) The `price` field holds the price configuration for the subscription item. | Attribute | Type | Description | | - | - | - | | `currency` | `string` | Three-letter ISO 4217 currency code. One of `CLP`, `MXN`, or `CLF`. Fintoc bills a Unidad de Fomento (UF, `CLF`) price inside a `CLP` subscription. | | `product` | `object` | Product details for this price. See the Product object table below. | | `recurring` | `object` | Billing recurrence configuration. See the Recurring object table below. | | `unit_amount` | `integer` | Amount charged per unit, in the smallest currency unit. CLP has no minor unit, so `15000` means 15,000 CLP. CLF has four decimals, so `35000` means 3.5 UF. | #### The Product object (within the Price object) The `product` field holds the product associated with the price. | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the product. | | `object` | `string` | Type of the object. Always `product`. | | `created_at` | `string` | ISO 8601 datetime in UTC when the product was created. | | `description` | `string` or `null` | Description of the product. `null` when not set. | | `image_url` | `string` or `null` | URL of an image for the product. `null` when not set. | | `metadata` | `object` | Set of key-value pairs attached to the product. | | `mode` | `string` | One of `live` or `test`. | | `name` | `string` | Name of the product. | #### The Recurring object (within the Price object) The `recurring` field holds the billing recurrence configuration for the price. | Attribute | Type | Description | | - | - | - | | `interval` | `string` | Billing frequency. Fintoc supports `month` only. | | `interval_count` | `integer` | Number of intervals between billings. | ## Prices in UF (`CLF`) To bill a plan indexed to UF, set the price's `currency` to `CLF`. Set `unit_amount` in the smallest UF unit, which has four decimals. For example, `unit_amount: 35000` prices the item at 3.5 UF. The subscription and its invoices stay in `CLP`. When Fintoc generates an invoice, Fintoc converts every `CLF` item to `CLP` using the UF value at the start of the billing period. The amount your customer pays follows the UF value for that day. Once Fintoc issues the invoice, the invoice amount no longer changes. A subscription can combine `CLP` and `CLF` items. Any other currency mix, such as an `MXN` item alongside a `CLP` item, returns an error, and Fintoc does not create the subscription. # Cancel a subscription Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-cancel reference/main-api.json POST /v2/subscriptions/{id}/cancel Cancels a subscription immediately. Canceled subscriptions stop generating invoices, and the cancellation does not affect invoices already issued. Canceling a subscription that is already canceled returns a `subscription_not_editable` error. # Create a subscription Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-create reference/main-api.json POST /v2/subscriptions Creates a subscription that bills a customer on a recurring cadence, in the `live` or `test` mode of the API key used. Each item defines its price through `price_data`, referencing an existing product (`product`) or defining one inline (`product_data`). All items must share a compatible currency (`CLF` items bill alongside `CLP`) and the same recurring `interval` and `interval_count`. A subscription can have up to 10 items. The `collection_method` decides how Fintoc collects every invoice the subscription generates. With `charge_automatically`, the default, Fintoc charges `payment_method` on every billing cycle, so the payment method is required. With `send_invoice`, Fintoc leaves each invoice open for you to collect, and `payment_method` is optional. A `payment_method` must be active and have a type of `pac` or `card`; subscriptions do not support `bank_transfer`. Without `trial_end` or `billing_cycle_anchor`, Fintoc anchors the billing cycle at the creation time and finalizes an initial invoice immediately. With `charge_automatically`, the subscription starts `incomplete` and becomes `active` once that first payment succeeds. With `send_invoice`, the subscription starts `active` and the initial invoice stays `open`. For a zero-amount subscription, Fintoc marks the initial invoice paid and the subscription starts `active`. With `trial_end`, the subscription's status is `trialing`. Fintoc sets the `billing_cycle_anchor` to the trial end and generates the first invoice when the trial ends. With `billing_cycle_anchor`, the subscription starts `active`. Fintoc issues no invoice until the anchor, then generates the first invoice for the full billing period that starts there. The anchor must be in the future and cannot be combined with `trial_end`. With `cancel_at`, Fintoc invoices every billing period that starts before `cancel_at`, with no proration, and cancels the subscription at that timestamp. To bill a fixed number of periods, set `cancel_at` to the start of the first period you do not want to bill. # Detach the payment method from a subscription Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-detach-payment-method reference/main-api.json DELETE /v2/subscriptions/{id}/payment_method Detaches the payment method from a subscription. The payment method stays available on the customer, so you can attach it again later. Only subscriptions with `collection_method` set to `send_invoice` can detach their payment method, because a subscription that collects automatically needs a payment method to charge. Fintoc also clears the `default_payment_method` of the subscription's draft and open invoices, so a later payment must name the payment method explicitly. This stops the automatic retries of an open invoice that Fintoc was still collecting. Paid and voided invoices keep their `default_payment_method` as a record of how Fintoc charged them. Fintoc sends a `subscription.payment_method_updated` event with `payment_method` set to `null`. Detaching a subscription that has no payment method does nothing, sends no event, and returns the subscription unchanged. # Get a subscription Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-get reference/main-api.json GET /v2/subscriptions/{id} Retrieves a subscription by its `id`, with its subscription items included. Only subscriptions of your organization matching the `live` or `test` mode of the API key used are visible. # List subscriptions Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-list reference/main-api.json GET /v2/subscriptions Lists the subscriptions of your organization for the `live` or `test` mode of the API key used, with their subscription items included. The list is paginated with cursors: use the `Link` response header or the `starting_after` and `ending_before` query parameters to navigate between pages. # Update a subscription Source: https://docs.fintoc.com/api/payments-api/subscriptions/subscriptions-update reference/main-api.json PATCH /v2/subscriptions/{id} Updates a subscription. Provide at least one of `trial_end`, `payment_method`, `collection_method`, `cancel_at`, or `split`. Provide `trial_end` to set when the trial ends and the first paid billing period begins. `trial_end` must be at least one day in the future. Fintoc aligns the subscription's `billing_cycle_anchor` to `trial_end` and sets its `status` to `trialing` until then. Provide `payment_method` to swap the payment method the subscription charges against. The payment method must belong to the subscription's customer, be a `pac` or `card`, and be active. After the swap, Fintoc charges every next payment against the new payment method, including any invoice that is already open. Swapping does not charge the subscription immediately. Provide `collection_method` to change the way Fintoc collects the invoices the subscription generates. Switching to `charge_automatically` requires a payment method Fintoc can charge, either in the same request or already associated. The change applies from the next billing cycle. Invoices that are already open keep their existing collection method. Provide `cancel_at` to schedule when Fintoc cancels the subscription, or `null` to remove a scheduled cancellation. Fintoc invoices every billing period that starts before `cancel_at`, with no proration, and cancels the subscription at that datetime. Provide `split` to replace the rules that divide every charge of the subscription between entities. The new rules apply to the invoices the subscription issues from then on. Invoices already created keep the rules they inherited, even if they are still `draft`. Canceled subscriptions cannot be updated. # Charge object Source: https://docs.fintoc.com/api/direct-debit-legacy/charges/charge-object Reference for the Charge object in Fintoc's direct debit API, including amount, currency, status, and how it tracks each collection against a subscription. ## The Charge object A `Charge` represents a single direct debit collection against the bank account tied to an active `Subscription`, with its `amount`, `currency`, and `status`. It is created when you charge a `Subscription`, and its `status` changes as the collection is processed. ```json Charge Object theme={null} { "id": "ch_m7N9rAWJS9dWDKEe", "object": "charge", "amount": 5000, "business_profile": { "category": "011210", "name": "Merchant Name", "tax_id": "777777777" }, "created_at": "2021-11-11T02:29:16Z", "currency": "CLP", "failure_code": null, "metadata": {}, "mode": "live", "recipient_account": { "holder_id": "111111111", "institution_id": "cl_banco_estado", "number": "123456789", "type": "checking_account" }, "status": "pending", "subscription_id": "sub_m7N9rAWJS9dWDKEe" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Charge | | `object` | `string` | Identifier for the type of object. Its value for `Charges` will always correspond to `charge` | | `amount` | `integer` | Amount to be charged from the subscribed account, [represented as an integer](/guides/home/currencies). This value must always be greater than 0. | | `business_profile` | `hash` | Optional object to identify multiple enrolled merchants for category-based pricing. | | `created_at` | `string` | `Charge`'s creation date, using ISO 8601 | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html). Fintoc currently only supports CLP | | `failure_code` | `string` | Short string with a brief explanation of the error. Its values can be `insufficient_funds`, `subscription_inactive`, `charge_amount_limit_exceeded` or `other`. It can be null | | `metadata` | `hash` | Set of [key-value](/api/fintoc-api/metadata) pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. | | `mode` | `string` | Indicates whether the `Charge` is in `live` mode or in `test` mode (for the sandbox) | | `recipient_account` | `object` or `null` | Destination account that receives the charged funds. Present only when the charge is routed to a recipient account. See the Recipient Account object table below. | | `status` | `string` | Charge status. Can be `pending`, `in_progress`, `succeeded`, `failed`. | | `subscription_id` | `string` | Unique identifier of the `Subscription` this charge belongs to. | ## The Business Profile object (within the Charge object) The `business_profile` field holds the enrolled merchant's information. | Attribute | Type | Description | | :- | :- | :- | | `category` | `string` | Identifier of the category of the enrolled merchant. In Chile, it corresponds to a 6 character SII activity code. | | `name` | `string` | Enrolled merchant's name. | | `tax_id` | `string` | Enrolled merchant's tax identifier. In Chile, it corresponds to a RUT. | ## The Recipient Account object (within the Charge object) The `recipient_account` field holds the account that receives the charged funds. | Attribute | Type | Description | | :- | :- | :- | | `holder_id` | `string` | Identifier of the owner of the account. In Chile, it corresponds to a RUT. | | `institution_id` | `string` | Identifier of the institution the account belongs to. | | `number` | `string` | Account number. Does not include hyphens nor prefixed zeros. | | `type` | `string` | Type of account. | # Cancel a charge Source: https://docs.fintoc.com/api/direct-debit-legacy/charges/charges-cancel reference/main-api.json POST /v1/charges/{id}/cancel Cancels a charge. Only charges with status `pending` can be canceled. Once the collection starts, the charge can no longer be canceled. # Create a charge Source: https://docs.fintoc.com/api/direct-debit-legacy/charges/charges-create reference/main-api.json POST /v1/charges Creates a charge on an active subscription. The charge starts with status `pending`, and Fintoc collects the charge from the subscription's bank account on the next collection cycle. In `test` mode, Fintoc simulates the collection and updates the charge status asynchronously after creation. # Update a charge Source: https://docs.fintoc.com/api/direct-debit-legacy/charges/charges-update reference/main-api.json PATCH /v1/charges/{id} Updates a charge. Only the `amount` and the `currency` can be updated, and only while the charge status is `pending`. Once the collection starts, the charge can no longer be updated. # Subscription object Source: https://docs.fintoc.com/api/direct-debit-legacy/direct-debit-subscriptions/direct-debit-subscription-object ## The Subscription object A `Subscription` represents an end user's enrolled bank account that authorizes direct debit collections, exposing the linked `account` and a `status`. Fintoc creates the `Subscription` when a `SubscriptionIntent` succeeds. To create charges through Fintoc, the `Subscription` must have `status` `active`. > [!WARNING] > > If your existing integration only enrolls bank accounts under your own bank agreement, the `status` does not determine the mandate's validity at your bank. Follow [Enrollment under your own bank agreement](#enrollment-under-your-own-bank-agreement) instead of waiting for activation through Fintoc. ```json Subscription Object theme={null} { "id": "sub_m7N9rAWJS9dWDKEe", "object": "subscription", "account": { "id": "acc_nMNejK7BT8oGbvO4", "object": "account", "balance": { "available": 530000, "current": 530000, "limit": 1530000 }, "currency": "CLP", "holder_id": "111111111", "holder_name": "Test Customer 1", "institution": { "id": "cl_banco_santander", "country": "cl", "name": "Banco Santander" }, "name": "Cuenta Corriente", "number": "0000000000", "official_name": "Cuenta Corriente Moneda Local", "type": "checking_account" }, "created_at": "2021-11-11T02:29:16Z", "mode": "live", "reference_id": null, "status": "active" } ``` | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the Subscription | | `object` | `string` | Identifier for the type of object. Its value for `Subscriptions` will always correspond to `subscription` | | `account` | `object` | Object that points to the bank account that can be charged with this subscription. | | `created_at` | `string` | `Subscription`'s creation date, using ISO 8601 | | `mode` | `string` | Indicates whether the `Subscription` is in `live` mode or in `test` mode (for the sandbox) | | `reference_id` | `string` | Merchant-provided ID that determines how the bank identifies the subscription in its portal. If omitted, Fintoc uses the end user's `holder_id`. Must be 1 to 15 characters. Available only for subscription clients. | | `status` | `string` | `Subscription` status in Fintoc. One of `pending`, `active`, `canceled`, or `expired`. You can charge only `active` subscriptions through Fintoc. For enrollment under your own bank agreement, confirm mandate validity with your bank instead. | > [!WARNING] > > **Subscription account balance** > > The `account.balance` field is only present when you receive a subscription through a `subscription_intent.succeeded` event. > > At other moments the account balance is `null`. ## Enrollment under your own bank agreement If you use Fintoc's legacy Subscriptions product only to enroll bank accounts, your bank handles subsequent collections under your agreement. Fintoc's enrollment flow ends when you receive `subscription_intent.succeeded`. Handle enrollment results on your backend: * Listen for `subscription_intent.succeeded` to confirm that your customer completed enrollment. Store the returned `subscription.id`, `subscription.account`, and `subscription.reference_id`. * Handle `subscription_intent.failed` and `subscription_intent.rejected` to notify your customer that Fintoc could not confirm successful enrollment. After successful enrollment, confirm mandate activation and collection readiness with your bank before creating debits under your agreement. A successful `SubscriptionIntent` does not confirm bank activation or a successful debit. The returned `Subscription` can remain `pending` after your bank activates the mandate. Do not use `subscription.activated`, `subscription.canceled`, or the `Subscription.status` to activate or deactivate mandates in your own-bank integration. A `subscription.canceled` event with `status` `expired` reports expiration of the `Subscription` in Fintoc, not confirmation of bank-side cancellation. Confirm the mandate's current state with your bank. # Subscription intent public error Source: https://docs.fintoc.com/api/direct-debit-legacy/subscriptions-intents/subscription-intent-error-reason Every `public_error` value Fintoc sets on a failed subscription intent, from invalid bank credentials to authorization timeouts, and what each means. When a subscription intent fails, the `public_error` attribute on the [Subscription Intent object](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) identifies the cause. Fintoc uses the following `public_error` values. Handle unknown values because Fintoc can add new errors. | `public_error` | Description | | :- | :- | | `account_type_not_permitted` | The selected account type is not allowed for this enrollment. | | `authorization_timeout` | Your customer did not authorize the direct debit enrollment in time. | | `bank_connection_error` | Fintoc had a problem connecting with the selected bank. | | `bank_not_available` | The selected bank is temporarily unavailable. | | `internal_error` | An unexpected error occurred while processing the enrollment. | | `login_credentials_locked` | The bank locked your customer's credentials after too many failed attempts. | | `login_invalid_credentials` | The bank credentials your customer entered are incorrect. | | `mfa_authorization_timeout` | Your customer did not complete the bank's multi-factor authentication in time. | | `mfa_unavailable` | The bank's multi-factor authentication is not available for your customer. | | `password_change_required` | The bank requires your customer to change their password before continuing. | | `request_timeout` | The request to the bank timed out. | | `subscription_intent_expired` | The subscription intent expired before your customer completed the enrollment. | | `user_left` | Your customer left the widget before completing the enrollment. | # Subscription intent object Source: https://docs.fintoc.com/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object Reference for the Subscription Intent object in Fintoc's direct debit API, covering the enrollment attempt, its status, and the resulting Subscription. ## The Subscription Intent object A `SubscriptionIntent` represents an attempt to enroll an end user's bank account for direct debit. The `status` field tracks the enrollment progress. A successful enrollment creates the `Subscription` referenced by `subscription`. > [!WARNING] > > For existing enrollment-only integrations under your own bank agreement, use `subscription_intent.succeeded` to confirm completed enrollment. Enrollment success does not confirm mandate activation or collection readiness at your bank. Do not use the returned `Subscription` object's `status` or its lifecycle webhooks as bank-state signals. See [Enrollment under your own bank agreement](/api/direct-debit-legacy/direct-debit-subscriptions/direct-debit-subscription-object#enrollment-under-your-own-bank-agreement). The following example shows a `SubscriptionIntent`: ```json theme={null} { "id": "si_m7N9rAWJS9dWDKEe", "object": "subscription_intent", "business_profile": { "name": "Merchant Name" }, "created_at": "2021-11-11T02:29:16Z", "customer_email": "customer@example.com", "mode": "live", "public_error": null, "reference_id": null, "status": "created", "subscription": null, "widget_token": "si_m7N9rAWJS9dWDKEe_sec_1y7o6DYLY299p7ePP7zevTEj" } ``` The `SubscriptionIntent` has the following attributes: | Attribute | Type | Description | | :- | :- | :- | | `id` | `string` | Unique identifier for the `SubscriptionIntent`. | | `object` | `string` | Object type. Always `subscription_intent`. | | `business_profile` | `object` or `null` | Profile of the enrolled merchant, with fields described in the Business Profile object table below. The widget displays the name as the "Recipient Company". Returns `null` when no merchant name is set. | | `created_at` | `string` | Creation date as an ISO 8601 datetime in UTC. | | `customer_email` | `string` or `null` | Email of the customer associated with the `SubscriptionIntent`. `null` when no email is set. | | `mode` | `string` | Environment for the `SubscriptionIntent`. One of `live` or `test`. The `test` mode targets the sandbox. | | `public_error` | `string` or `null` | Error code explaining why the enrollment failed. See [Subscription intent public errors](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-error-reason) for the full list. Returns `null` when no public error is available. | | `reference_id` | `string` or `null` | Identifier provided by the merchant that determines how the bank identifies the subscription on its portal. Defaults to the account `holder_id` if not provided. Available only to Subscriptions clients and limited to 15 characters. | | `status` | `string` | Current state of the enrollment. One of `created`, `in_progress`, `succeeded`, `failed`, or `rejected`. | | `subscription` | `object` or `null` | The `Subscription` created after successful enrollment. Returns `null` unless the enrollment succeeds. | | `widget_token` | `string` or `null` | Temporary token for configuring the widget. Returned only when creating the `SubscriptionIntent`. Subsequent responses return `null`. | ### The Business Profile object (within the Subscription Intent object) The `business_profile` field contains the following Business Profile attribute for the enrolled merchant: | Attribute | Type | Description | | :- | :- | :- | | `name` | `string` | Name of the enrolled merchant. Shown as the "Recipient Company" on the widget screens. | # Create a subscription intent Source: https://docs.fintoc.com/api/direct-debit-legacy/subscriptions-intents/subscription-intents-create reference/main-api.json POST /v1/subscription_intents Creates a subscription intent in the `live` or `test` mode of the API key used. The response includes the `widget_token` used to open the widget so the payer can authorize the subscription. # List subscription intents Source: https://docs.fintoc.com/api/direct-debit-legacy/subscriptions-intents/subscription-intents-list reference/main-api.json GET /v1/subscription_intents Lists the subscription intents of your organization for the `live` or `test` mode of the API key used. Results are paginated. `widget_token` is always `null` outside creation. # Get an invoice Source: https://docs.fintoc.com/api/fiscal-api/fiscal-invoices/fiscal-invoices-get reference/main-api.json GET /v1/invoices/{id} Retrieves an invoice by its `id`, using the link's `link_token` to authenticate the request. You can only retrieve invoices that belong to the link's fiscal account. For links created with the `income` product, you can only retrieve the fee receipts for professional services the account holder issued. # List invoices Source: https://docs.fintoc.com/api/fiscal-api/fiscal-invoices/fiscal-invoices-list reference/main-api.json GET /v1/invoices Returns a paginated list of the invoices of the fiscal link associated with the `link_token`, sorted by descending document date. For links created with the `invoices` product, Fintoc returns every document the fiscal authority reports. For links created with the `income` product, Fintoc returns only the fee receipts for professional services the account holder issued. # Invoice object Source: https://docs.fintoc.com/api/fiscal-api/fiscal-invoices/fiscal-invoices-object ## The Invoice object The `Invoice` object represents a tax document, such as an electronic invoice or a receipt for professional fees, registered for a fiscal account at its tax authority. One appears for each document the account's owner issues or receives. ```json Invoice Object theme={null} { "id": "inv_nMNejK7BT8oGbvO4", "object": "invoice", "currency": "CLP", "date": "2021-06-25T04:00:00.000Z", "institution_id": "cl_fiscal_sii", "institution_invoice": { "accepted_at": null, "common_use_vat": null, "confirmation_status": null, "construction_company_credit": 0, "container_deposit_guarantee": 0, "document_type": 34, "domestic_ticket_sales": 0, "exempt_amount": 0, "exempt_commissions": 0, "fixed_assets_net_amount": null, "fixed_assets_vat_amount": null, "free_zone_tax": 0, "has_note": false, "international_ticket_sales": 0, "invoice_status": "registered", "is_services_invoice": false, "net_commissions": 0, "non_credit_tax_amount": null, "non_refundable_vat_amount": null, "non_refundable_vat_code": null, "non_withheld_vat": 0, "other_taxes": { "other_taxes_detail": [ { "tax_amount": 400, "tax_code": 14, "tax_rate": "19" } ], "total_amount": 400 }, "out_of_time_vat": 0, "own_vat": 0, "partial_vat_withheld": 0, "receipt_reference_number": null, "received_at": "2021-06-25T19:27:04.000Z", "reference_number": null, "reference_type_code": null, "rejected_at": null, "services_invoice": null, "settlement_issuer_id": null, "third_party_vat": 0, "tobacco": { "cigarettes": 0, "cigars": 0, "processed_tobacco": 0 }, "total_documents": null, "total_vat_withheld": 0, "transaction_category": "Del Giro", "vat_amount": 123, "vat_commisions": null }, "issue_type": "received", "issuer": { "id": "111111111", "institution_tax_payer": null, "name": "Hooli SpA" }, "net_amount": 12000, "number": "135", "receiver": null, "tax_period": "06/2021", "total_amount": 12123 } ``` | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the Invoice | | `object` | `string` | Identifier for the type of object. Its value for `Invoices` will always correspond to `invoice` | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | `date` | `string` | Date of the document, using ISO 8601. For documents with code 39 and 41, corresponds to the last day of the tax period to which they correspond | | `institution_id` | `string` | Fiscal authority's `id`. You can read more about the available institutions [here](/guides/movements/overview-data-aggregation/products-and-institutions-movements) | | `institution_invoice` | `object` | `Institution Invoice` object | | `issue_type` | `string` | Indicates whether the document was issued or received by the account's owner. Its possible values are `issued` or `received` | | `issuer` | `object` | If the Invoice corresponds to a buy, this field indicates who issued the Invoice. Otherwise, this field is `null`. See the `Taxpayer` object to learn more. For documents that come in summary this field is `null` (codes 35, 38, 39, 41, 47 and 48) | | `net_amount` | `integer` | Net amount of the document [represented as an integer](/guides/home/currencies). | | `number` | `string` | For `cl_fiscal_sii`, it corresponds to the invoice folio. | | `receiver` | `object` | If the Invoice corresponds to a sell, this field indicates who received the Invoice. Otherwise, this field is `null`. See the `Taxpayer` object to learn more. For documents that come in summary this field is `null` (codes 35, 38, 39, 41, 47 and 48) | | `tax_period` | `string` | Tax period, with the format `mm/yyyy` | | `total_amount` | `integer` | Total amount of the document [represented as an integer](/guides/home/currencies). | ### The Tax Payer (Issuer or Receiver) object (within the Invoice object) The `TaxPayer` object identifies the counterparty of the document, appearing in the `issuer` field for `received` invoices and in the `receiver` field for `issued` invoices. | Attribute | Type | Description | | - | - | - | | `id` | `string` | The document issuer/receptor's Chilean tax ID (RUT), for the SII | | `institution_tax_payer` | `object` | The document issuer/receptor's fiscal data. Can be `null` | | `name` | `string` | The document issuer/receptor's name | ## 🇨🇱 Chile: Servicio Impuestos Internos (SII) ### The Institution Invoice object (within the Invoice object) If the fiscal authority is Servicio de Impuestos Internos (`cl_fiscal_sii`), the `institution_invoice` field corresponds to the following object: #### The SII Invoice object (as the Institution Invoice object) The `SIIInvoice` object holds the Servicio de Impuestos Internos (SII) tax data for the document, including its VAT breakdown, acceptance status, and document type. It populates the `institution_invoice` field when the fiscal authority is `cl_fiscal_sii`. | Attribute | Type | Description | | - | - | - | | `accepted_at` | `string` | Document's acceptance date, using ISO 8601. Can be `null` if the invoice is not `registered`. | | `common_use_vat` | `integer` | Common use VAT | | `confirmation_status` | `string` | Result of Chile's acceptance or claim process for received documents (SII's "acuse de recibo"). On receiving an electronic invoice, the taxpayer has 8 calendar days to acknowledge or claim it. If they do nothing, it is acknowledged automatically. One of `C` (**C**onforme: acknowledged by the recipient within the term), `A` (**A**utomático: acknowledged automatically, when the term lapsed without a claim), `P` (**P**ago al contado: paid in cash, no acknowledgment needed), `G` (**G**uía de despacho: acknowledged via dispatch guides from the previous month), `R` (**R**eclamado: claimed, i.e., rejected, by the recipient), or `null` (no event recorded yet, e.g. still within the 8-day term, a document type that doesn't use this flow (receipts, credit/debit notes, or vouchers), or an `issued` document awaiting the counterparty). | | `construction_company_credit` | `integer` | Construction company credit | | `container_deposit_guarantee` | `integer` | Container deposit guarantee | | `document_type` | `integer` | Code for the type of document. Its value is `null` if the document corresponds to a receipt for professional fees. Read the codes for the SII document types in the table below for more information | | `domestic_ticket_sales` | `integer` | Domestic ticket sales | | `exempt_amount` | `integer` | Tax exempt amount [represented as an integer](/guides/home/currencies). | | `exempt_commissions` | `integer` | Value exempt from commissions | | `fixed_assets_net_amount` | `integer` | Fixed assets net amount [represented as an integer](/guides/home/currencies). | | `fixed_assets_vat_amount` | `integer` | Fixed assets VAT-refundable amount [represented as an integer](/guides/home/currencies). | | `free_zone_tax` | `integer` | Free zone tax (Chilean Law 18211) | | `has_note` | `boolean` | Indicates whether the document has a credit or debit note associated | | `international_ticket_sales` | `integer` | International ticket sales | | `invoice_status` | `string` | SII tab where the invoice was obtained. One of `registered` (*REGISTRO*), `pending` (*PENDIENTES*), `cancelled` (*RECLAMADOS*), or `rejected` (*NO INCLUIR*). | | `is_services_invoice` | `boolean` | Indicates whether the document corresponds to a receipt for professional fees | | `net_commissions` | `integer` | Net value for the commissions | | `non_credit_tax_amount` | `integer` | Taxes without right to credit [represented as an integer](/guides/home/currencies). | | `non_refundable_vat_amount` | `integer` | Fixed assets non VAT-refundable amount [represented as an integer](/guides/home/currencies). | | `non_refundable_vat_code` | `integer` | Non VAT-refundable code | | `non_withheld_vat` | `integer` | Non withheld VAT | | `other_taxes` | `object` | Other taxes breakdown. See the `Other Taxes` table below to learn more | | `out_of_time_vat` | `integer` | Out of time VAT | | `own_vat` | `integer` | Own VAT | | `partial_vat_withheld` | `integer` | Partial VAT withheld | | `receipt_reference_number` | `integer` | Internal number: receipt reference number | | `received_at` | `string` | Document's reception date given by the SII, using ISO 8601. | | `reference_number` | `string` | Folio number for the reference document | | `reference_type_code` | `integer` | Code for the type of the reference document | | `rejected_at` | `string` | Document rejection date, using ISO 8601. Can be `null` if the invoice is not `rejected`. | | `services_invoice` | `object` | Contains specific information about the receipts for professional fees. Its value is `null` when the document doesn't correspond to a receipt for professional fees | | `settlement_issuer_id` | `string` | Settlement issuer's RUT. | | `third_party_vat` | `integer` | Third party VAT | | `tobacco` | `object` | Tobacco taxes breakdown. See the `Tobacco Taxes` table below to learn more | | `total_documents` | `integer` | Number of grouped documents. This field is valid for the documents that come in summary (codes 35, 38, 39, 41, 47 and 48). For every other document, corresponds to `null` | | `total_vat_withheld` | `integer` | Total VAT withheld | | `transaction_category` | `string` | Transaction category classification. One of `Money order`, `Supermarket`, `Real estate`, `Fixed asset`, `Common use VAT`, `Non-refundable VAT`, or `Do not include`. | | `vat_amount` | `integer` | VAT-refundable amount [represented as an integer](/guides/home/currencies). | | `vat_commissions` | `integer` | Value of the VAT for the commissions | #### The Other Taxes object (within the Institution Invoice object) The `OtherTaxes` object breaks down taxes on the document beyond VAT, appearing in the `other_taxes` field of the `SIIInvoice` object. | Attribute | Type | Description | | - | - | - | | `other_taxes_details` | `array` | Array of objects with `tax_amount`, `tax_code` and `tax_rate` | | `total_amount` | `integer` | Total amount of other taxes [represented as an integer](/guides/home/currencies). | #### The Tobacco Taxes object (within the Institution Invoice object) The `TobaccoTaxes` object breaks down the taxes on tobacco products in the document, appearing in the `tobacco` field of the `SIIInvoice` object. | Attribute | Type | Description | | - | - | - | | `cigarettes` | `integer` | Tobacco cigarettes | | `cigars` | `integer` | Pure tobacco cigars | | `processed_tobacco` | `integer` | Processed tobacco | #### The Services Invoice object (within the Institution Invoice object) The `ServicesInvoice` object holds the details specific to a receipt for professional fees, appearing in the `services_invoice` field of the `SIIInvoice` object when `is_services_invoice` is `true`. | Attribute | Type | Description | | - | - | - | | `is_professional_society` | `boolean` | Indicates whether the issuer taxpayer corresponds to a society of professionals or not | | `is_third_party` | `boolean` | Indicates whether the invoice was generated for a third party or not | | `issued_at` | `datetime` | Corresponds to the date in which the document was issued on the official SII website | | `issuer_withheld_amount` | `integer` | Corresponds to the withheld amount in case the issuer taxpayer handles the provisional payment of the taxes | | `receiver_withheld_amount` | `integer` | Corresponds to the withheld amount in case the recipient taxpayer handles the provisional payment of the taxes | | `status` | `string` | Corresponds to the invoice. Its possible values are: `VIG` (Valid), `ANUL` (Annulled), `ObR` (Observed), `VCA` (Valid with nullification request) | ### Codes for SII document types The `document_type` attribute corresponds to one of the codes that the SII determines within the guide named "[Formato Documentos Tributarios Electrónicos](https://www.sii.cl/factura_electronica/formato_dte.pdf)". The most used ones are: | Document Type | Description | | :- | :- | | 30 | Invoice | | 32 | Sales and services invoice exempt from VAT | | 33 | Electronic invoice | | 34 | Electronic invoice exempt from VAT | | 35 | Ballot | | 38 | Exempt ballot | | 39 | Electronic ballot | | 40 | Invoice settlement | | 41 | Electronic exempt ballot | | 43 | Electronic invoice settlement | | 45 | Purchase invoice | | 46 | Electronic purchase invoice | | 47 | Total of the month special electronic voucher | | 48 | Electronic payment | | 50 | Office guide | | 52 | Electronic office guide | | 55 | Debit note | | 56 | Electronic debit note | | 60 | Credit note | | 61 | Electronic credit note | | 103 | Settlement | | 110 | Electronic export invoice | | 111 | Electronic export debit note | | 112 | Electronic export credit note | # Get a tax return Source: https://docs.fintoc.com/api/fiscal-api/tax-returns/tax-returns-get reference/main-api.json GET /v1/tax_returns/{id} Retrieves a tax return by its `id`, using the link's `link_token` to authenticate the request. You can only retrieve tax returns that belong to the link's fiscal account. # List tax returns Source: https://docs.fintoc.com/api/fiscal-api/tax-returns/tax-returns-list reference/main-api.json GET /v1/tax_returns Returns a paginated list of the annual tax returns (F22 form) of the fiscal account associated with a link. Use the link's `link_token` to authenticate the request. Available for Chilean links connected to the Chilean tax authority (SII). # Tax return object Source: https://docs.fintoc.com/api/fiscal-api/tax-returns/tax-returns-object ## The Tax Return object The `TaxReturn` object represents an annual income tax return that a fiscal account's owner files with their tax authority. For the Servicio de Impuestos Internos (SII), it corresponds to the F22 form for a given `fiscal_year`, with the authority-specific amounts nested in `institution_tax_return`. ```json Tax Return Object theme={null} { "id": "taxret_nMNejK7BT8oGbvO4", "object": "tax_return", "currency": "CLP", "document_number": "12345", "fiscal_year": "2021", "institution_id": "cl_fiscal_sii", "institution_tax_return": { "due_amount": 0, "income": { "fees": 13123, "fees_with_retention": 234212, "fees_without_retention": 512334, "salary": 2313123, "withheld_fees": 42341 }, "refund_account": { "holder_id": "111111111", "holder_name": "Test Customer 1", "institution": { "id": "cl_banco_de_chile", "country": "cl", "name": "Banco de Chile" }, "number": "000000000" }, "refund_amount": 1000 }, "interval_unit": "annual", "period": "2021", "taxpayer": { "id": "777777777", "institution_tax_payer": { "activities": [ { "category": "1", "code": "0123", "description": "Servicios de tecnología", "iva": false, "started_at": "2020-04-16T04:00:00.000Z" } ], "addresses": [ { "apartment": null, "city": "Santiago", "code": "84345463", "commune": "PROVIDENCIA", "number": "2461", "region": "REGION METROPOLITANA", "street": "LOS CONQUISTADORES", "type": "DOMICILIO" } ], "authorized_documents": [ { "authorized_at": "2021-11-30T15:57:38.584Z", "code": "33", "description": "FACTURA ELECTRONICA", "max_documents": 414 } ], "email": "test@example.com", "phone": "999999999" }, "name": "Test Company 1" } } ``` | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the Tax Return | | `object` | `string` | Identifier for the type of object. Its value for `Tax Returns` will always correspond to `tax_return` | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | `document_number` | `string` | For `cl_fiscal_sii`, it corresponds to the declaration folio. For `mx_fiscal_sat`, it corresponds to the operation number | | `fiscal_year` | `string` | Year to which the tax return corresponds | | `institution_id` | `string` | Fiscal authority's `id`. You can read more about the available institutions [here](/guides/movements/overview-data-aggregation/products-and-institutions-movements) | | `institution_tax_return` | `object` | Either a `SIITaxReturn` or a `SATTaxReturn` object | | `interval_unit` | `string` | Its value corresponds to `annual` | | `period` | `string` | Period to which the tax return corresponds | | `taxpayer` | `object` | Taxpayer to whom the tax return corresponds. | ## 🇨🇱 Chile: Servicio de Impuestos Internos (SII) If the fiscal authority is Servicio de Impuestos Internos (`cl_fiscal_sii`), the tax return corresponds to the F22 declaration. The `taxpayer` and `institution_tax_return` fields correspond to the following objects, respectively: ### The Tax Payer object (within the Tax Return object) The `TaxPayer` object describes the account's owner to whom the tax return corresponds, and it appears in the `taxpayer` field of the `TaxReturn` object. | Attribute | Type | Description | | - | - | - | | `id` | `string` | The taxpayer's Chilean tax ID (RUT) | | `activities` | `array` | Array with the taxpayer's activities, profession or business | | `addresses` | `array` | Array with the taxpayer's addresses | | `authorized_documents` | `array` | Array with the taxpayer's authorized documents for emitting | | `email` | `string` | The taxpayer's email | | `name` | `string` | The taxpayer's name | | `phone` | `string` | The taxpayer's phone number | #### The Address object (within the Tax Payer object) The `Address` object describes a registered location of the taxpayer, and entries appear in the `addresses` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `apartment` | `string` | Apartment or office number | | `city` | `string` | City | | `code` | `string` | Branch code | | `commune` | `string` | Commune | | `number` | `string` | Building number | | `region` | `string` | Region | | `street` | `string` | Avenue, street, passage | #### The Activity object (within the Tax Payer object) The `Activity` object describes an economic activity, profession, or business that the taxpayer is registered for, and entries appear in the `activities` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `category` | `string` | Taxpayer's tributary category | | `code` | `string` | The taxpayer's [code of economic activity](https://www.sii.cl/ayudas/ayudas_por_servicios/1956-codigos-1959.html) | | `description` | `string` | Taxpayer's economic activity description | | `iva` | `boolean` | Indicates whether the economic activity is affected by IVA | | `started_at` | `datetime` | The taxpayer's start date of tax activities, using ISO 8601 | #### The Authorized Document object (within the Tax Payer object) The `AuthorizedDocument` object describes a type of tax document the taxpayer is authorized to issue, and entries appear in the `authorized_documents` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `authorized_at` | `datetime` | Date when the document issuance was authorized. | | `code` | `string` | Code for the type of document | | `description` | `string` | Name for the type of document | | `max_documents` | `integer` | Max number of folios to authorize for the type of document | ### The Institution Tax Return object (within the Tax Return object) When the fiscal authority is Servicio de Impuestos Internos (`cl_fiscal_sii`), the `institution_tax_return` field corresponds to the following object: #### The SII Tax Return object The `SIITaxReturn` object holds the income and refund amounts declared on the F22 form, and it populates the `institution_tax_return` field when the fiscal authority is `cl_fiscal_sii`. | Attribute | Type | Description | | - | - | - | | `due_amount` | `integer` | The taxpayer's tax to be paid | | `income` | `object` | The taxpayer's income, according to the F22 form | | `refund_account` | `object` | The taxpayer's account in which to deposit the tax returns. Corresponds to a `Transfer Account` object | | `refund_amount` | `integer` | The taxpayer's requested tax returns | #### The Income object (within the Institution Tax Return object) The `Income` object breaks down the taxpayer's declared income by source, and it appears in the `income` field of the `SIITaxReturn` object. | Attribute | Type | Description | | - | - | - | | `fees` | `integer` | Total amount of income from receipts for professional fees. It corresponds to the addition of `fees_with_retention` and `fees_without_retention`. Code 547 of the F22 form | | `fees_with_retention` | `integer` | Total amount from receipts for professional fees with retention. Code 461 of the F22 form | | `fees_without_retention` | `integer` | Total amount from receipts for professional fees without retention. Code 545 of the F22 form | | `salary` | `integer` | Salaries, pensions and other similar incomes. Code 1098 of the F22 form | | `withheld_fees` | `integer` | Total taxes withheld from receipts for professional fees. Code 492 of the F22 form | #### The Refund Account object (within the Institution Tax Return object) The `RefundAccount` object describes the bank account where the taxpayer's refund is deposited, and it appears in the `refund_account` field of the `SIITaxReturn` object. | Attribute | Type | Description | | - | - | - | | `holder_id` | `string` | The taxpayer's RUT | | `holder_name` | `string` | The taxpayer's name | | `institution` | `object` | The taxpayer's institution. Corresponds to an `Institution` object | | `number` | `string` | The taxpayer's account number | #### The Institution object (within the Refund Account object) The `Institution` object identifies the bank that holds the refund account, and it appears in the `institution` field of the `RefundAccount` object. | Attribute | Type | Description | | - | - | - | | `id` | `string` | The institution's ID | | `country` | `string` | The institution's country | | `name` | `string` | The institution's name | # Get a tax statement Source: https://docs.fintoc.com/api/fiscal-api/tax-statements/tax-statements-get reference/main-api.json GET /v1/tax_statements/{id} Retrieves a tax statement by its `id`, using the link's `link_token` to authenticate the request. You can only retrieve tax statements that belong to the link's fiscal account. # List tax statements Source: https://docs.fintoc.com/api/fiscal-api/tax-statements/tax-statements-list reference/main-api.json GET /v1/tax_statements Returns a paginated list of the monthly tax statements (F29 form) of the fiscal account associated with a link, ordered by year and period with the most recent first. Use the link's `link_token` to authenticate the request. Available for Chilean links connected to the Chilean tax authority (SII). # Tax statement object Source: https://docs.fintoc.com/api/fiscal-api/tax-statements/tax-statements-object ## The Tax Statement object The `TaxStatement` object represents a periodic tax statement that a fiscal account's owner files with their tax authority. For the Servicio de Impuestos Internos (SII), it corresponds to the monthly F29 form for a given `period`, with the authority-specific amounts nested in `institution_tax_statement`. ```json Tax Statement Object theme={null} { "id": "taxstmt_000000000", "object": "tax_statement", "currency": "CLP", "document_number": "123456", "fiscal_year": 2021, "institution_id": "cl_fiscal_sii", "institution_tax_statement": { "monthly_provisional_payments": null, "retention_fee": 6497, "salary_tax": 1870153, "total_credit": 403497, "total_debit": 1173692, "total_payment": 2646845 }, "interval_unit": "monthly", "period": "10", "status": "Vigente", "taxpayer": { "id": "777777777", "institution_tax_payer": { "activities": [ { "category": "1", "code": "0123", "description": "Servicios de tecnología", "iva": false, "started_at": "2020-04-16T04:00:00.000Z" } ], "addresses": [ { "apartment": null, "city": "Santiago", "code": "84345463", "commune": "PROVIDENCIA", "number": "2461", "region": "REGION METROPOLITANA", "street": "LOS CONQUISTADORES", "type": "DOMICILIO" } ], "authorized_documents": [ { "authorized_at": "2021-11-30T15:57:38.584Z", "code": "33", "description": "FACTURA ELECTRONICA", "max_documents": 414 } ], "email": "test@example.com", "phone": "999999999" }, "name": "Test Company 1" } } ``` | Attribute | Type | Description | | - | - | - | | `id` | `string` | Unique identifier for the Tax Statement | | `object` | `string` | Identifier for the type of object. Its value for `Tax Statements` will always correspond to `tax_statement` | | `currency` | `string` | [Currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | `document_number` | `string` | For `cl_fiscal_sii`, it corresponds to the declaration folio. For `mx_fiscal_sat`, it corresponds to the operation number | | `fiscal_year` | `string` | Year to which the taxes correspond | | `institution_id` | `string` | Fiscal authority's `id`. You can read more about the available institutions [here](/guides/movements/fiscal-links) | | `institution_tax_statement` | `object` | Either an `SIITaxStatement` or an `SATTaxStatement` object | | `interval_unit` | `string` | Its value corresponds to `monthly` | | `period` | `string` | Month of the year to which the taxes correspond | | `status` | `string` | Status of the Tax Statement | | `taxpayer` | `object` | Taxpayer to whom the tax statement corresponds. | ## 🇨🇱 Chile: Servicio de Impuestos Internos (SII) If the fiscal authority is Servicio de Impuestos Internos (`cl_fiscal_sii`), monthly taxes correspond to what's declared using the F29 form. The `taxpayer` and `institution_tax_statement` fields corresponds to the following objects, respectively: ### The SII Tax Statement object The `SIITaxStatement` object holds the credit, debit, and payment amounts declared on the F29 form, and it populates the `institution_tax_statement` field when the fiscal authority is `cl_fiscal_sii`. | Attribute | Type | Description | | - | - | - | | `monthly_provisional_payments` | `integer` | Monthly provisional payments | | `retention_fee` | `integer` | Retention fee over honoraria | | `salary_tax` | `integer` | Second category taxes | | `total_credit` | `integer` | Total amount of credit | | `total_debit` | `integer` | Total amount of debit | | `total_payment` | `integer` | Total amount of taxes to pay within the legal term | ### The Tax Payer object (within the Tax Statement object) The `TaxPayer` object describes the account's owner to whom the tax statement corresponds, and it appears in the `taxpayer` field of the `TaxStatement` object. | Attribute | Type | Description | | - | - | - | | `id` | `string` | The taxpayer's Chilean tax ID (RUT) | | `activities` | `array` | Array with the taxpayer's activities, profession or business | | `addresses` | `array` | Array with the taxpayer's addresses | | `authorized_documents` | `array` | Array with the taxpayer's authorized documents for emitting | | `email` | `string` | The taxpayer's email | | `name` | `string` | The taxpayer's name | | `phone` | `string` | The taxpayer's phone number | ### The Address object (within the Tax Payer object) The `Address` object describes a registered location of the taxpayer, and entries appear in the `addresses` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `apartment` | `string` | Apartment or office number | | `city` | `string` | City | | `code` | `string` | Branch code | | `commune` | `string` | Commune | | `number` | `string` | Building number | | `region` | `string` | Region | | `street` | `string` | Avenue, street, passage | ### The Activity object (within the Tax Payer object) The `Activity` object describes an economic activity, profession, or business that the taxpayer is registered for. Entries appear in the `activities` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `category` | `string` | Taxpayer's tributary category | | `code` | `string` | The taxpayer's [code of economic activity](https://www.sii.cl/ayudas/ayudas_por_servicios/1956-codigos-1959.html) | | `description` | `string` | Taxpayer's economic activity description | | `iva` | `boolean` | Indicates whether the economic activity is affected by IVA | | `started_at` | `datetime` | The taxpayer's start date of tax activities, using ISO 8601 | ### The Authorized Document object (within the Tax Payer object) The `AuthorizedDocument` object describes a type of tax document the taxpayer is authorized to issue. Entries appear in the `authorized_documents` array of the `TaxPayer` object. | Attribute | Type | Description | | - | - | - | | `authorized_at` | `datetime` | Date when the document issuance was authorized. | | `code` | `string` | Code for the type of document | | `description` | `string` | Name for the type of document | | `max_documents` | `integer` | Max number of folios to authorize for the type of document | # List movements Source: https://docs.fintoc.com/api/movements-api/movements/movements-list reference/main-api.json GET /v1/accounts/{id}/movements Returns a paginated list of the movements of an account, using the link's `link_token` to authenticate the request. By default the endpoint returns only confirmed movements; use `confirmed_only=false` to include every status. > [!NOTE] > > **Paginate movements with `per_page` and `page`** > > If a response does not include all expected movements, increase `per_page` to return more movements in each request. The default is `30`, and the maximum is `300`. > > If the account has more movements than `per_page` returns, use `page` to request the remaining pages. # Create a refresh intent Source: https://docs.fintoc.com/api/movements-api/refresh-intents/refresh-intents-create reference/main-api.json POST /v1/refresh_intents Creates a refresh intent for a link, using the link's `link_token` to authenticate the request. Unless the institution requires multi-factor authentication, the refresh starts asynchronously and Fintoc notifies the result through webhooks. Your organization needs the on demand refresh policy, and Fintoc rate limits consecutive refreshes (5 minutes between `only_last` refreshes, 60 minutes between `historical` ones). Fintoc updates your accounts and sends the results through the [webhook system](/guides/resources/webhooks-walkthrough).\ When Fintoc completes the update, you receive the [`account.refresh_intent.succeeded`](/api/main-resources/events-reference/types-of-events) event. You can then request the latest bank movements from the Fintoc API.\ When the update fails or the bank reports invalid credentials, you receive the `account.refresh_intent.failed` or `account.refresh_intent.rejected` event, respectively. Fintoc restricts how often you can request an *on-demand* update. You cannot create a refresh intent while another refresh intent is in progress. If `refresh_type` is `only_last`, wait **five** minutes between refresh intents. If `refresh_type` is `historical`, wait **sixty** minutes between refresh intents. # Changelog Source: https://docs.fintoc.com/changelog Latest releases, improvements, and breaking changes to the Fintoc API and products, including payments, transfers, recurring charges, and connections. **2026-10-30** Dashboard improvements ## Dashboard improvements * **Payment Links:** Click a link's row to open its new detail page. It shows the link's totals, details, and metadata, plus a **Payments** table with every payment made through the link. See [Payment Links](/guides/payments/payment-links#track-payments). * **Find a Payment Link's payments:** Filter your payment history by Payment Link ID. A payment's detail shows the Payment Link it came from. * **Payment history:** The list now starts with all statuses. It no longer preselects the **Succeeded** filter. * **Copy identifiers:** The movements, transfers, team, and entities tables now have copy buttons for IDs, account numbers, and tax IDs. Hover over a value to copy it in one click. * **Filters:** Transfers, Links, and Customers keep your filters when you go back from a detail page. * **Sign in again:** If your session expires and you sign back in within an hour, the Dashboard takes you back to the page and filters you had open. * **Transfers:** When creating a transfer fails, the Dashboard now shows the reason. * **Invoices:** The invoices export includes a **Currency** column. **2026-10-30** Bug fixes ## Bug fixes * **Unsupported card brands:** Fintoc only processes Visa and Mastercard cards. When your customer entered a card of another brand, the payment widget showed a generic connection error. The widget now asks for a Visa or Mastercard card right below the card number. * **Organization maximum amount error:** 🇲🇽 The error for a payment above your organization's maximum amount showed the limit formatted as CLP, even for MXN payments. Fintoc now formats the limit in the payment's currency. * **Empty Payment Links export:** Exporting Payment Links as XLSX with filters that matched no links downloaded a file Excel couldn't open. The file now has a sheet with the column headers. **2026-10-29** Account certificates in Mexico ## Account certificates in Mexico 🇲🇽 You can now download an account certificate (carátula) from the Dashboard. The certificate is a PDF that shows an account is open and active in its holder's name. * **What it shows:** The holder's legal name, Mexican tax ID (RFC), and fiscal address. It also shows the standardized Mexican bank account number (CLABE), the institution in the Electronic Interbank Payment System (SPEI), and the issue date. * **Where to download it:** Click **Account certificate** on an account's detail for its main CLABE, or **Download certificate** on another enabled CLABE's detail. * **When it's available:** In `live` mode, for active accounts whose holder has a legal name, RFC, and fiscal address on file. See [Download an account certificate](/guides/business-accounts/manage-accounts#download-an-account-certificate). **2026-10-28** Mexican direct debit mandate checks ## Mexican direct debit mandate checks 🇲🇽 Fintoc now checks more mandate data up front and tells you why a mandate was rejected. These checks apply in `test` and `live` mode. * **Customer contact required:** The mandate's customer must have an email address and a phone number. Otherwise, Fintoc responds with a `422 Unprocessable Entity` error with the code `customer_contact_required` and doesn't create the payment method. * **RFC validation:** Fintoc also checks the date and the check digit of the RFC. It rejects an invalid RFC with the code `invalid_rfc`, in the API and in the checkout. * **`max_amount` in Checkout Sessions:** Fintoc validates that the maximum amount is between `100` and `5000000` MXN cents when you create the Checkout Session, not when your customer authorizes the mandate. * **Rejection reason:** A rejected or canceled payment method includes the reason in `mx_direct_debit.error_reason`, in the API and in webhooks. The field is `null` when the mandate has no saved reason. See [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico). **2026-10-26** Recipients API ## Recipients API You can now manage recipients, the saved destination accounts of an entity, with the API in Chile and Mexico. * **Manage recipients:** Create, list, get, update, and delete recipients at `/v2/recipients`. * **Country rules:** In Chile, send the Chilean tax ID (RUT), `account_type`, and `holder_type`. In Mexico, Fintoc infers `account_type` from `account_number`. * **Filter the list:** Filter recipients by `entity_id`, `holder_id`, `account_number`, and other fields. * **Fixed account details:** You can't change `account_number`, `institution_id`, or `holder_id` after you create a recipient. See the [Recipient object](/api/business-accounts-api/recipients/recipient-object). **2026-10-23** Cancel payment methods with the API ## Cancel payment methods with the API You can now cancel a saved payment method with `POST /v2/payment_methods/{id}/cancel`. Fintoc stops charging a canceled payment method. * **Webhook:** Fintoc sends the `payment_method.canceled` event when you cancel a payment method. * **No new charges:** Fintoc rejects charges and Checkout Sessions that use a canceled payment method with a `422 Unprocessable Entity` error and the code `payment_method_canceled`. * **Cancel once:** Canceling a payment method that is already canceled returns a `409 Conflict` error with the code `payment_method_non_cancelable`. See [Cancel a payment method](/api/payments-api/payment-methods/payment-methods-cancel). **2026-10-23** Dashboard improvements ## Dashboard improvements * **Customers:** The customer detail page now lists the customer's subscriptions, with their recurrence, payment method, status, and amount. **2026-10-22** Client entities in Chile ## Client entities in Chile 🇨🇱 You can now create and onboard a client `Entity` in Chile from the Dashboard or through the API. Before, client entities were available in Mexico only. * **Onboard by API:** Create the entity with the company's Chilean tax ID (RUT), then send the `account_holder` onboarding with the Chilean `data` blocks and documents. * **Chilean checks on submit:** When `incorporation_type` is `one_day_company`, Fintoc verifies that the company is registered through Empresa en un Día and returns `not_one_day_company` if it isn't. * **Main account:** Fintoc creates the entity's main account in CLP when it approves the onboarding. See [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api). **2026-10-22** Bug fixes ## Bug fixes * **PAC enrollment with a company RUT:** 🇨🇱 The PAC enrollment widget showed a warning for a company RUT but still let your customer continue. The widget now blocks the login until your customer enters the RUT of a natural person. **2026-10-23** Transfer batches in the API ## Transfer batches in the API You can now create, get, and list transfer batches with the API, in Mexico and Chile. You still authorize every batch from the Dashboard. * **Create a batch:** Send up to 5,000 transfers in one request to `POST /v2/transfer_batches`. The batch starts in `pending_authorization`. * **Track the batch:** Fintoc sends the new `transfer_batch.*` webhook events each time a batch changes status. * **Read its transfers:** Filter `GET /v2/transfers` by `transfer_batch_id`. See [Batch transfers](/guides/business-accounts/outbound-transfers/batch-transfers) and the [Transfer batch object](/api/business-accounts-api/transfer-batches/transfer-batch-object). **2026-10-21** Refunds have a new returned status ## Refunds have a new returned status 🇲🇽 A refund now moves from `succeeded` to `returned` when the recipient's bank sends the transfer back after Fintoc disbursed it. Fintoc sends the new `refund.returned` webhook event. * **Not a failure:** `returned` means Fintoc disbursed the funds and the bank returned them afterward. A `failed` refund was never disbursed. * **Filter by status:** You can filter the refunds list by `returned`. * **Dashboard:** The Dashboard shows a `returned` refund as a failed refund. See [Refunds](/guides/payments/fintoc-collect-payments/payment-initiation-refunds) and the [Refund object](/api/payments-api/refunds/refund-object). **2026-10-22** Banco BTG Pactual and Tenpo Bank in Chile ## Banco BTG Pactual and Tenpo Bank in Chile 🇨🇱 Fintoc now supports Banco BTG Pactual (`cl_banco_btg_pactual`) and Tenpo Bank (`cl_tenpo_bank`). * **Settlement accounts:** You can use an account at either bank as your settlement account during onboarding. * **Dashboard:** Both banks appear in the Chilean institution lists. * **Tenpo Prepago:** `cl_tenpo` now shows as Tenpo Prepago. It stays a separate institution from Tenpo Bank. See [Chile institution codes](/api/fintoc-api/chile-institution-codes). **2026-10-22** Dashboard improvements ## Dashboard improvements * **Payment history:** Filter payments by customer email or failure reason. New **Failure reason** and **Email** columns are available, and exports include a **Customer Email** column. Card payments show the card brand in the payment header. * **Payouts:** The summary card shows your next payout and the total pending in `live` mode. You can also download a single payout from its row's three-dot menu. * **Payment Links:** Choose which columns to show in the table. A new **Successful payments** column counts the payments each link received. See [Payment Links](/guides/payments/payment-links). * **Invoices:** Export the invoices list as CSV or Excel. * **Customers:** The customer detail page has a new layout with saved payment methods, customer data, metadata, and recent activity. Expired cards show an **Expired** label. **2026-10-22** Mexican direct debit mandate limits and charge reference ## Mexican direct debit mandate limits and charge reference 🇲🇽 Two changes to Mexican direct debit (domiciliación): * **`max_amount` range:** `mx_direct_debit.max_amount` must be between `100` and `5000000` MXN cents (\$1.00 to \$50,000.00 MXN), inclusive. Fintoc rejects values outside this range with an invalid parameter error in `test` and `live` modes. Existing mandates are not affected. * **Charge reference:** Your customer's bank statement now shows your commercial name as the charge reference, up to 40 characters. See [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico#2-enroll-a-payment-method-by-api). **2026-10-20** Subscriptions can be paused ## Subscriptions can be paused Subscriptions have a new `paused` status. Fintoc pauses your subscriptions when your organization loses access to subscriptions. While a subscription is `paused`, Fintoc stops generating and charging its invoices. See [Get a subscription](/api/payments-api/subscriptions/subscriptions-get). **2026-10-22** Bug fixes ## Bug fixes * **Refund form:** 🇨🇱 The Dashboard refund form no longer offers savings accounts, which refunds don't support. * **Mexican bank holiday:** 🇲🇽 Fintoc now treats November 2, 2026 as a bank holiday. Direct debit charges, payouts, and cash payment processing scheduled for that day move to November 3. **2026-10-17** Batch transfers are available in Chile ## Batch transfers are available in Chile 🇨🇱 Chilean organizations can now send up to 5,000 outbound transfers from one file in the Dashboard, as Mexican organizations already could. * **Dashboard only:** Go to **Transfers → Batch Transfers** and download the Chile (CLP) template. * **Legacy Security setups:** These organizations can create batch transfers in `live` mode only. See [Batch transfers](/guides/business-accounts/outbound-transfers/batch-transfers). **2026-10-16** Deactivate Payment Links from the Dashboard ## Deactivate Payment Links from the Dashboard You can now deactivate an active Payment Link from the Dashboard, not only through the API. Open the link's three-dot menu, select **Deactivate**, and confirm. * **Permission required:** Only users who can manage payment links see the option. * **In-progress payments:** Payments already in progress can still complete. * **New `completed` status:** A single-use Payment Link that receives its payment now moves to `completed`. See [Cancel a Payment Link](/guides/payments/payment-links#cancel-a-payment-link). **2026-10-15** Admins can grant transfer approval to other Admins ## Admins can grant transfer approval to other Admins The Admin role does not include transfer approval. An Admin who can change user roles can now grant transfer approval and account creation to another Admin through account rules. * **Grant only:** Admin-to-Admin edits can add permissions but cannot remove or lower them. * **No self-edits:** You cannot edit your own permissions. See [Treasury permissions](/guides/home/dashboard/permission-roles#treasury). **2026-10-15** WooCommerce plugin 1.2.5 adds cash payments in Mexico ## WooCommerce plugin 1.2.5 adds cash payments in Mexico The Fintoc for WooCommerce plugin is now in the WordPress plugin directory and supports cash payments. * **Cash in Mexico:** 🇲🇽 Your customers get a voucher to pay at a store. The order stays **On hold** until they pay or the Checkout Session expires. * **Install and update from WordPress:** Install the plugin from **Plugins → Add New** in WordPress. WordPress offers new versions like any other plugin. * **Automatic title:** Leave **Title** empty and the checkout names the payment methods enabled for your organization. See [WooCommerce](/guides/payments/e-commerce-connectors/woocommerce#cash-payments-in-mexico). **2026-10-13** Schedule a subscription cancellation from Checkout Sessions ## Schedule a subscription cancellation from Checkout Sessions Send `subscription_cancel_at` when you create a `subscription` flow Checkout Session. Fintoc cancels the resulting subscription at that datetime. * **Exact time:** `cancel_at` on subscriptions now cancels at the exact timestamp you send, not at the start of that date. * **No extra invoices:** Fintoc issues no invoice for a billing period that starts at or after the cancellation. See [Create a Checkout Session](/api/payments-api/checkout-sessions/checkout-sessions-create) and [Update a subscription](/api/payments-api/subscriptions/subscriptions-update). **2026-10-14** Mexican account holder onboardings require an account purpose ## Mexican account holder onboardings require an account purpose 🇲🇽 Mexican `account_holder` onboardings now require `transactional_profile.account_purpose`. If you send `other`, also send `account_purpose_details`. See [Create an onboarding](/api/business-accounts-api/onboardings/entities-onboardings-create). **2026-10-13** Disputes can be canceled ## Disputes can be canceled Disputes have a new `canceled` status for disputes opened in error. You can filter the disputes list by `canceled`. See the [Dispute object](/api/payments-api/disputes/dispute-object) and [Disputes in the Dashboard](/guides/home/dashboard/disputes). **2026-10-17** Clearer API errors ## Clearer API errors Fintoc now returns more specific errors in these cases: * **Client entities:** Creating a client `Entity` returns `422 Unprocessable Entity` with `organization_without_operational_root_entity` if your organization has no root `Entity` in the API key's mode. See [Before you start](/guides/business-accounts/entities/onboard-an-entity-by-api#before-you-start). * **Refunds:** Refunding a payment method that doesn't support refunds returns `payment_method_not_refundable`. * **Invoices and subscriptions:** Organizations without access to these products get `403 Forbidden` with `product_access_required`. * **Card payments:** Payment and Setup Intents can fail with the `invalid_amount` error reason. See [Payment Intent error reasons](/api/payments-api/payment-intents/payment-intent-error-reason). **2026-10-09** Return inbound transfers in Chile and from the Dashboard ## Return inbound transfers in Chile and from the Dashboard 🇨🇱 You can now return a `succeeded` inbound transfer in Chile, not only in Mexico. You can also return transfers from the Dashboard. * **Same endpoint:** Use the existing return endpoint for Chilean transfers. Fintoc deducts the amount from your account balance. * **90-second wait for other banks:** If the transfer comes from another bank, wait 90 seconds after it reaches `succeeded`. Earlier requests return `409 Conflict` with the code `invalid_transfer_status`. * **Dashboard:** Open the transfer's options menu, select **Return**, and confirm with your authenticator code. See [Return a transfer](/guides/business-accounts/inbound-transfers/returning-an-inbound-transfer). **2026-10-09** Mark an invoice as uncollectible ## Mark an invoice as uncollectible `POST /v2/invoices/{id}/mark_uncollectible` writes off an `open` invoice you no longer expect to collect. The invoice keeps a record that your customer owed the amount. * **New status:** The invoice moves to `uncollectible`. * **New event:** Fintoc sends `invoice.marked_uncollectible`. See [Close an invoice you will not collect](/guides/payments/accept-recurring-payments/manage-invoices#close-an-invoice-you-will-not-collect) and the [Mark an invoice as uncollectible reference](/api/payments-api/invoices/invoices-mark-uncollectible). **2026-10-09** Enroll Mexican direct debit in Checkout Sessions ## Enroll Mexican direct debit in Checkout Sessions 🇲🇽 Your customers can now authorize a direct debit mandate (domiciliación) from the Fintoc-hosted checkout. Add `mx_direct_debit` to `payment_method_types` in `setup` and `subscription` sessions. * **Test mode first:** Checkout enrollment is available in `test` mode with `MXN` currency. * **Mandate terms:** In `setup` sessions, set `max_amount` and `interval` in `payment_method_options.mx_direct_debit`. Subscription sessions derive the terms from `line_items`. * **Know the source:** The payment method's `mx_direct_debit.consent_source` is `api` or `checkout`. See [Accept direct debit payments in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico#3-create-a-checkout-session). **2026-10-08** Upload multiple files to one onboarding document slot ## Upload multiple files to one onboarding document slot Some entity onboarding document slots now accept multiple files. Each uploaded file has its own `id` in the `documents` array. * **Add a file:** `POST .../documents/{slot_key}` adds a file to a multi-file slot. * **Remove a file:** `DELETE .../documents/{slot_key}/{document_id}` removes one file from any slot. * **Replace a file:** `PUT` still replaces the file in a single-file slot. See [Manage files in a slot](/guides/business-accounts/entities/onboard-an-entity-by-api#manage-files-in-a-slot). **2026-10-08** Payment intents list the invoices they pay ## Payment intents list the invoices they pay `PaymentIntent` objects and `payment_intent.*` webhooks now include an `invoices` field. The `invoices` field lists the IDs of the invoices the payment intent pays. The field is empty when the payment intent pays no invoice. * **Covers every invoice payment:** Automatic charges, their retries, and payments your customer makes from an invoice's `hosted_invoice_url` all list their invoice in `invoices`. * **Reach the subscription through the invoice:** Get the invoice to find the subscription that issued it. See [Reconcile payments with invoices and subscriptions](/guides/payments/accept-recurring-payments/manage-invoices#reconcile-payments-with-invoices-and-subscriptions) and the [Payment Intent object](/api/payments-api/payment-intents/payment-intents-object). **2026-10-06** Download the Mexican direct debit mandate contract ## Download the Mexican direct debit mandate contract 🇲🇽 `GET /v2/payment_methods/{id}/mandate_document` returns a signed link to the mandate contract of an `mx_direct_debit` payment method, in any mandate status. * **Short-lived link:** The `download_url` expires 5 minutes after the request. Request a new `download_url` each time. See [Download the mandate document](/guides/payments/accept-recurring-payments/direct-debit-mexico#7-download-the-mandate-document). **2026-10-06** Send cash vouchers by WhatsApp and remind customers to pay ## Send cash vouchers by WhatsApp and remind customers to pay 🇲🇽 Fintoc can now send the cash payment voucher by WhatsApp and remind your customer to pay. * **WhatsApp:** Send `customer_phone` in E.164 format, for example `+525511111111`. * **Choose channels:** Use `notification_preferences` to pick `email`, `phone`, or both, and to turn the voucher or reminders on or off. * **Reminders:** Fintoc sends up to 2 reminders per channel while the payment is pending. * **Checkout Sessions:** Pass the same fields when you create the session. See [Configure voucher notifications](/guides/payments/cash-payment-direct-api#configure-voucher-notifications). **2026-10-06** Manage your team, webhooks, and IP restrictions from the MCP server ## Manage your team, webhooks, and IP restrictions from the MCP server The Fintoc MCP server supports more operations. * **Team:** List users and roles, and invite users with a predefined role. Reconnect your client and grant the **Team** scope to use these operations. * **Webhooks:** Create and update webhook endpoints. * **IP restrictions:** Add an allowed IP range to your organization. * **Your Fintoc invoices:** List the invoices Fintoc issues to your organization. See [Model Context Protocol (MCP)](/guides/resources/building-with-ai/model-context-protocol-mcp). **2026-10-05** Widget connections no longer have a separate rate limit ## Widget connections no longer have a separate rate limit Fintoc no longer applies a separate rate limit to Widget connections. The API request and Business Accounts transfer limits still apply. See [API rate limits](/guides/home/api-rate-limits). **2026-10-01** Accept cash in Mexican Checkout Sessions and Payment Links ## Accept cash in Mexican Checkout Sessions and Payment Links 🇲🇽 Your customers can now pay in cash from the Fintoc-hosted checkout. They generate a reference and pay at more than 13,000 stores. * **Checkout Sessions:** Add `cash` to `payment_method_types` in an `MXN` session. You can offer it on its own or with `card` and `bank_transfer`. You can't combine `cash` with `installments`. * **Payment Links:** If your organization has cash enabled, every `MXN` Payment Link offers cash automatically. You do not need to send an additional parameter. * **Retry in cash:** If a card or bank transfer payment fails, your customer can retry in cash from the same checkout. See [Accept cash payments in Mexico](/guides/payments/cash-payment-direct-api). **2026-10-01** Price subscriptions in Unidad de Fomento (UF) ## Price subscriptions in UF 🇨🇱 You can now price subscription items in Unidad de Fomento (UF). Set the item's `currency` to `CLF` and keep the subscription in `CLP`. * **Converted every cycle:** Fintoc converts each `CLF` item to `CLP` using the UF value at the start of the billing period. Once Fintoc issues an invoice, its amount no longer changes. * **Four decimals:** `unit_amount` uses the smallest UF unit, so `35000` means 3.5 UF. * **Mix with CLP:** A subscription can combine `CLP` and `CLF` items. Other currency mixes return an error. See [Price a subscription in UF](/guides/payments/accept-recurring-payments#price-a-subscription-in-uf). **2026-10-01** Verify Mexican debit cards and mobile phone numbers ## Verify Mexican debit cards and mobile phone numbers 🇲🇽 Account verifications now accept a 16-digit debit card number, a 10-digit mobile phone number, or an 18-digit standardized Mexican bank account number (CLABE). Fintoc confirms the destination with a 0.01 MXN micro-deposit before you send a full payout. * **Send `institution_id`:** Debit cards and mobile numbers don't encode their bank, so include the bank's `institution_id`. Without it, the API returns `400 Bad Request`. * **New account types:** The verification's `account_type` is `clabe`, `debit_card`, or `mobile`. See [Verify Mexican accounts](/guides/business-accounts/outbound-transfers/verify-clabes#verify-a-debit-card-or-mobile-phone-number). **2026-10-01** Split Payments recipient onboarding updates ## Split Payments recipient onboarding updates Onboarding a Split Payments recipient now requires fewer fields, and `capabilities.settlement_recipient.status` exposes whether the recipient can receive splits. * **Capability status:** `Entity` objects now return `capabilities.settlement_recipient.status`. Use the capability status to check whether an `Entity` can receive splits. The top-level `status` reflects the `Entity` object's most advanced capability. * **Fewer fields for Chilean companies:** `business_activity`, `business_address`, and `phone` are now optional for Chilean company `Entity` objects. Mexican company `Entity` objects must still send them. * **Settlement accounts by country:** For Mexican `Entity` objects, send only an 18-digit CLABE as `account_number`. Fintoc derives the bank from the CLABE. See [Accept split payments](/guides/payments/accept-a-payment/accept-split-payments). **2026-10-01** Fintoc emails the cash payment voucher automatically ## Fintoc emails the cash payment voucher automatically 🇲🇽 Fintoc now sends the cash payment voucher to your customer automatically, so they get the reference and payment instructions without you sharing them. * **Cash payments created by API:** Fintoc sends the voucher as soon as the payment is created. * **Checkout sessions:** Fintoc sends the voucher when your customer moves from the payment instructions to the voucher. * **Email only:** Fintoc sends the voucher to the payment's `customer_email`. * **Respects your settings:** Fintoc doesn't send the voucher if you turned off voucher notifications in your preferences or if your account suppresses customer communications. * **Real messages in test mode:** Fintoc also sends real emails in `test` mode. See [Accept cash payments in Mexico](/guides/payments/cash-payment-direct-api#share-the-reference-and-instructions-to-pay-with-your-customer). **2026-09-30** Entity onboarding webhooks include the full onboarding ## Entity onboarding webhooks include the full onboarding The `entity.onboarding.approved` and `entity.onboarding.rejected` events now carry the full [`Onboarding`](/api/business-accounts-api/onboardings/onboarding-object) object. You can read the reviewed step data, documents, legal representatives, and shareholders straight from the webhook, without getting the onboarding from the API. * **New fields:** The payload adds `object`, `entity_id`, `type`, `source`, `data`, `legal_representatives`, `shareholders`, and `documents`. It omits `submittable`. * **Backward compatible:** The payload keeps `object_name: "onboarding_process"` and the `entity` summary, so existing handlers keep working. See the [Entity onboarding payload](/api/main-resources/events-reference/types-of-events#entity-onboarding-payload). **2026-09-22** Update invoice metadata ## Update invoice metadata `PATCH /v2/invoices/{id}` updates the `metadata` of an invoice in any status, including `paid` and `void`. Use this endpoint to store your own data on invoices that Fintoc generates from a subscription, without depending on the one-hour `draft` window. * **Replaces the full object:** The `metadata` you send replaces the invoice's existing `metadata`. If you omit `metadata`, the invoice keeps its current value. * **Metadata only:** The endpoint does not change amounts, collection dates, or line items. See the [Update an invoice reference](/api/payments-api/invoices/invoices-update). **2026-09-15** Send transfers over \$7,000,000 CLP in Chile ## Send transfers over \$7,000,000 CLP in Chile You can now create a Chilean outbound transfer for more than \$7,000,000 CLP. Some Chilean banks cap incoming transfers at \$7,000,000 CLP, so Fintoc splits larger transfers into parts of up to \$7,000,000 CLP and sends each part one after another. * **One transfer in the API.** You create and track a single `Transfer`, with one set of webhooks, one receipt, and one account movement. The parts do not appear in the API. * **Counterparty reconciliation suffix.** The counterparty receives one transfer per part. Fintoc appends `X de N` to each part's comment, so `Factura 1042` arrives as `Factura 1042 1 de 3`, `Factura 1042 2 de 3`, and `Factura 1042 3 de 3`. * **Transfers between Fintoc accounts stay whole.** A transfer to another Fintoc account settles immediately for the full amount, in one transfer. See [Large transfers in Chile](/guides/business-accounts/outbound-transfers#large-transfers-in-chile) for the statuses and how to send the rest of a partial transfer. **2026-09-10** Webhook events for Chilean outbound transfers that partially settle or reverse ## Webhook events for Chilean outbound transfers that partially settle or reverse Chilean outbound transfers now emit two new webhook events, so you can react to every terminal outcome the Centro de Compensación Automatizado can report. * **`transfer.outbound.partially_succeeded`:** 🇨🇱 Fintoc sends this event when only part of an outbound `Transfer` settles. The transfer's `status` is `partially_succeeded`. * **`transfer.outbound.reversed`:** 🇨🇱 Fintoc sends this event when an outbound `Transfer` that already settled is reversed. The transfer's `status` is `reversed`. Both events also fire in `test` mode, so you can confirm your handler for each outcome before going live. Mexican outbound transfers do not report these statuses. See the [Types of events reference](/api/main-resources/events-reference/types-of-events), the [Transfer data model](/guides/business-accounts/overview/transfer-data-model), and [Outbound transfers](/guides/business-accounts/outbound-transfers). **2026-09-09** WooCommerce orders stay in On hold while Fintoc validates the payment ## WooCommerce orders stay in On hold while Fintoc validates the payment Version `1.2.4` of the Fintoc for WooCommerce plugin keeps WooCommerce from canceling an order while Fintoc validates the payment for that order. A bank transfer can take hours or days to confirm. WooCommerce cancels unpaid orders once they are older than the **Hold stock (minutes)** setting, 60 minutes by default. Before this release, your store could show an order as canceled even after Fintoc had collected the money. * **Orders move to On hold.** When the Fintoc API reports that the payment is in validation, the plugin moves the order to **On hold**. WooCommerce excludes **On hold** orders from unpaid-order cleanup. The order reserves its stock during the wait, and your customer cannot start a second payment for the same order. * **Stock comes back when a payment fails.** A failed payment restores the stock the order had reserved, so the products do not stay held for an order nobody paid for. * **Polling fills webhook gaps.** Webhooks stay the primary signal. The plugin also fetches the payment from the Fintoc API on a schedule. The first retry runs after 15 minutes, then later retries back off to once a day. The plugin stops after 10 retries, about four days after the order moves to **On hold**. This lets the order resolve when Fintoc has the final payment status but the webhook never arrives. * **Duplicate payments surface.** A second payment succeeding for an order that is already paid now leaves an order note and emails the store admin, instead of only reaching the debug log. Refund the duplicate from the dashboard. Your customers receive WooCommerce's standard **Order on-hold** email when Fintoc starts validating their payment. To disable the email, go to **WooCommerce → Settings → Emails → Order on-hold**. Download `1.2.4` from the [Fintoc for WooCommerce page](https://woocommerce.fintoc.com/), and see [Accept payments with WooCommerce](/guides/payments/e-commerce-connectors/woocommerce) for what each order status means. **2026-08-27** Split one payment across multiple recipients ## Split one payment across multiple recipients Split Payments lets platforms and marketplaces divide the funds of a single Checkout Session payment across multiple recipients. Fintoc transfers each share to the recipient's own bank account, so you no longer reconcile or move the money yourself. Split Payments is available in Chile and Mexico. * **Each recipient is an `Entity`.** Create one with `POST /v2/entities`, then onboard it with the `settlement_recipient` type. The onboarding declares the bank account where Fintoc pays that recipient's share. * **Declare the rules on the Checkout Session.** Send a `split` array with 1 to 10 entries. Each entry names an `entity_id` and its share, as a `flat` amount or a `percentage` in basis points. The entries must add up to the payment amount exactly, and exactly one entry carries `charge_processing_fee`. * **Reconcile with events.** `checkout_session.finished` and `payment_intent.succeeded` include a `split_applied` array with the amount resolved for each recipient. `payout.*` events report each recipient's payout. See [Accept split payments](/guides/payments/accept-a-payment/accept-split-payments) for the end-to-end flow. **2026-08-27** Direct debit mandates expire after 7 days without confirmation ## Direct debit mandates expire after 7 days without confirmation A direct debit mandate that never receives bank confirmation no longer stays `pending` forever. When the bank does not confirm within 7 days, Fintoc expires the mandate and its status becomes `expired`. * **Mexico:** `mx_direct_debit.status` moves to `expired` and Fintoc sends `payment_method.canceled`. Enroll the customer again with a new payment method. Charging an expired mandate returns the `payment_method_inactive` error. * **Chile:** the direct debit subscription `status`, including `pac.status` on a payment method, gains the `expired` value. * **Test it:** in `test` mode, a Mexican mandate created with a CLABE ending in `8888` never receives confirmation, so Fintoc expires the mandate after 7 days. See [Direct debit in Mexico](/guides/payments/accept-recurring-payments/direct-debit-mexico) and the [Payment method object](/api/payments-api/payment-methods/payment-method-object). **2026-08-27** A clearer mx\_direct\_debit shape on the payment method ## A clearer mx\_direct\_debit shape on the payment method The `mx_direct_debit` details on the `PaymentMethod` object changed shape: * **`institution` replaces `institution_id`:** an object with the bank's `id`, `country`, and human-readable `name`. * **`account_number_last4` replaces `last_four_digits`.** * **`max_amount` replaces `max_amount_cents` and `max_amount_currency`:** the per-charge cap, in the smallest currency unit. * **New `account_holder_id`:** the account holder's tax identifier (RFC or CURP), without dots or hyphens. **Breaking:** the previous field names no longer appear in responses. Update any code that reads `institution_id`, `last_four_digits`, `max_amount_cents`, or `max_amount_currency`. See the [Payment method object](/api/payments-api/payment-methods/payment-method-object). **2026-08-27** Failure and reversal detail on Chilean transfers ## Failure and reversal detail on Chilean transfers Chilean transfers now tell you why and when a transfer did not settle: * **`error_reason`:** reason code for a failed transfer, such as `invalid_recipient_account`, `recipient_account_closed`, or `recipient_institution_timeout`. * **`reject_reason`:** reason code for a rejected transfer. One of `recipient_account_closed`, `recipient_account_credit_restricted`, and `unknown`. * **`failed_at`, `rejected_at`, and `reversed_at`:** ISO 8601 timestamps of each outcome. * **New event:** Fintoc sends `transfer.inbound.reversed` when an inbound Chilean transfer is reversed. Mexican transfers return these fields as `null`. See the [Transfer object reference](/api/business-accounts-api/transfers/transfer-object) and [Types of events](/api/main-resources/events-reference/types-of-events). **2026-08-27** Find account numbers without recent deposits ## Find account numbers without recent deposits `GET /v2/account_numbers` accepts a new `no_transfers_since` query parameter. Pass an ISO 8601 date, such as `2026-07-28`. Fintoc lists the account numbers whose last inbound transfer is earlier than that date, plus the account numbers that never received one. Use the filter to find idle account numbers you can disable or reassign. * **Mexico only:** the filter applies to Mexican account numbers. * **Errors:** an invalid date returns a `400 Bad Request` with the code `invalid_date`. See the [List account numbers reference](/api/business-accounts-api/account-numbers/account-numbers-list). **2026-08-26** Business Accounts is available in Chile ## Business Accounts is available in Chile Business Accounts runs in Chile on a Cuenta con Provisión de Fondos (CPF). You receive, send, and reconcile Chilean peso transfers over the Centro de Compensación Automatizado rail, with the same `Entity`, `Account`, and `Transfer` objects you already use in Mexico. Chile launches with accounts, Account Numbers, inbound and outbound transfers, account statements, `metadata` on an Account Number, and disabling an Account Number. Fintoc is working through the features Mexico has and Chile does not; the [availability matrix](/guides/business-accounts/overview#availability-by-country) names each one. * **Open accounts and Account Numbers with one call.** `POST /v2/accounts` opens an account, and `POST /v2/account_numbers` issues additional numbers on it. Assign one per customer or order, and attach `metadata` to reconcile each deposit against your records. Both actions also work from the dashboard. Senders select Fintoc as the destination institution, under the identifier `cl_fintoc`. * **Build against `test` mode before you move money.** Every Chilean endpoint runs with a `sk_test_` key. `POST /v2/simulate/receive_transfer` simulates a deposit from a Chilean sender through `counterparty_account_number`, `counterparty_account_type`, `counterparty_holder_id`, `counterparty_holder_name`, and `counterparty_institution_id`. * **The guides and the API reference now cover Chile.** Every Business Accounts page states what each country supports, so you can tell which calls apply where. See the [Business Accounts overview](/guides/business-accounts/overview) for the country availability matrix, and [Receive transfers](/guides/business-accounts/inbound-transfers) for the end-to-end flow. **2026-08-25** Enroll a Mexican direct debit mandate by API ## Enroll a Mexican direct debit mandate by API `POST /v2/payment_methods` enrolls a Mexican direct debit mandate and returns the payment method that represents it. Send the account details, mandate terms, and four consent documents under `mx_direct_debit[consent_documents]` as `multipart/form-data` in a single request. This lets you collect everything in your own UI instead of redirecting your customer to the Fintoc-hosted checkout. * **The request is atomic:** if a consent document is outside the 100 bytes to 10 MB range or is not a PDF, JPEG, or PNG, Fintoc creates nothing and returns `422 Unprocessable Entity`. * **Approval is asynchronous:** the mandate stays `pending` until the account holder authorizes it with their bank. Wait for `payment_method.activated` before you charge the account. See the [Create a payment method reference](/api/payments-api/payment-methods/payment-methods-create) and the [Payment method object](/api/payments-api/payment-methods/payment-method-object). **2026-08-21** Turn off the settlement email from the dashboard ## Turn off the settlement email from the dashboard The Communication tab in Settings now has a Settlement email toggle. Turn the toggle off to stop Fintoc from sending the email with the payout reconciliation report. Previously, the email arrived on every payout and only Fintoc could stop it. * **Covers payout emails:** Fintoc sends payout emails for bank transfers, cards, and the separate payout for recurring charges. Fintoc continues to send the daily summary email. * **Permission:** changing the toggle requires the Manage access level on Organization settings. See [Permission roles](/guides/home/dashboard/permission-roles). * **The email links to the toggle:** every settlement email now links to the Communication tab. See [Receiving payouts](/guides/payments/fintoc-collect-payments/payment-initiation-receiving-payouts#payout-notifications). **2026-08-19** Create an onboarding with type and data ## Create an onboarding with type and data `POST /v2/entities/{entity_id}/onboardings` now takes two required top-level fields. Set `type` to the kind of onboarding to create. The only accepted value is `account_holder`. Send the review data in `data`, which holds `company_information`, `legal_representatives`, `transactional_profile`, and `shareholders`. The `Onboarding` object and list summaries now return `type` as well. * **Breaking:** the previous flat body, with those four keys at the top level and no `data`, no longer works. Wrap the four keys in `data` and add `type`. * **Errors:** omitting `type` or `data` returns a `400 Bad Request` with the code `missing_parameter`. A `type` outside the accepted values returns a `400 Bad Request` with the code `invalid_enum`. * **Schema:** `data` varies by `type`, so the API reference describes it as a free-form object. See [Account holder onboarding](/guides/business-accounts/entities/account-holder-onboarding) for every field, enum value, and document slot of the `account_holder` type, and [Onboard an entity by API](/guides/business-accounts/entities/onboard-an-entity-by-api) for the full flow. **2026-08-14** Detach the payment method from a subscription ## Detach the payment method from a subscription `DELETE /v2/subscriptions/{id}/payment_method` removes the payment method from a subscription that collects with `send_invoice`. The payment method stays on the customer, so you can attach the payment method again later. Fintoc also clears the `default_payment_method` on the subscription's draft and open invoices. This change stops automatic retries on any open invoice. Paid and voided invoices keep the payment method as a record of how Fintoc charged each invoice. * **`send_invoice` only:** a subscription with `collection_method: charge_automatically` needs a payment method to charge, so Fintoc returns a `409 Conflict` on those. * **Canceled subscriptions:** Fintoc returns a `409 Conflict`. * **Idempotent no-op:** detaching a subscription that has no payment method returns the subscription unchanged and sends no event. * **Webhook:** Fintoc sends `subscription.payment_method_updated` with `payment_method` set to `null`. See the [Detach payment method reference](/api/payments-api/subscriptions/subscriptions-detach-payment-method). **2026-08-13** Filter entities by holder, status, and root ## Filter entities by holder, status, and root `GET /v1/entities` accepts three new query parameters so you can narrow the list without paging through the whole organization: * **`holder_id`:** find the entity by its owner's tax ID. Fintoc normalizes the value (strips dots, hyphens, leading zeros, and whitespace, then uppercases letters) before matching. * **`status`:** pass one or more of `draft`, `under_review`, `pending_signature`, `canceled`, `waiting_initialization`, `operational`, `rejected`, and `paused`. Fintoc returns every entity whose `status` matches any value you send. * **`is_root`:** set to `true` to return only the root entity of your organization, or `false` to return only the non-root entities. See the [List entities reference](/api/business-accounts-api/entities/entities-list). **2026-08-13** Reversal statuses on Chilean transfers ## Reversal statuses on Chilean transfers Chilean outbound transfers now expose two new lifecycle statuses: * **`reverse_pending`:** a reversal is in progress. * **`reversed`:** the transfer settled and was later reversed. `GET /v1/transfers` accepts both values in the `status` filter, so you can list the reversals your organization received. Mexican transfers keep the existing status set. See the [Transfer object reference](/api/business-accounts-api/transfers/transfer-object) and the [List transfers reference](/api/business-accounts-api/transfers/transfers-list). **2026-08-12** List accounts across every entity in your organization ## List accounts across every entity in your organization `GET /v1/transfers/accounts` now returns the accounts of every entity in your organization when you omit `entity_id`. Previously the endpoint returned only the accounts of the root entity, so you had to loop over `GET /v1/entities` to reach the rest. Pass `entity_id` to keep the previous scoped behavior. See the [List accounts reference](/api/business-accounts-api/accounts/accounts-list). **2026-08-11** Recover missed events with a step-by-step guide ## Recover missed events with a step-by-step guide A new guide walks you through fetching events Fintoc already sent and replaying them through your webhook handler after an outage. The guide covers choosing the recovery window and paginating with `starting_after` and `ending_before`. The guide also shows how to replay events oldest-first, process them in delivery order, and keep retries idempotent. See [Recover missed events](/guides/resources/webhooks-walkthrough/webhooks-recovering-events). **2026-08-10** Query the events Fintoc sent you ## Query the events Fintoc sent you `GET /v2/events` lists the events of your organization in the mode of the API key you use, most recent first. `GET /v2/events/{id}` returns one event by the `id` that arrives in every webhook you receive. Each event carries in `data` the same payload Fintoc delivered to your endpoint, so you can reprocess what your integration missed without waiting for a redelivery. * **Filters:** Use `type` for one event type and `resource_id` for every event about one resource. Use `since` and `until` for a time range. The range accepts a calendar date such as `2026-01-15` or an ISO 8601 datetime such as `2026-01-15T14:30:00Z`. * **Pagination:** the `starting_after` and `ending_before` cursors take an event ID, and `limit` returns up to 300 events per page, 30 by default. See the [List events reference](/api/main-resources/events-reference/events-list) and the [Get an event reference](/api/main-resources/events-reference/events-get) for every parameter. **2026-07-31** Collect invoices on your own with send\_invoice ## Collect invoices on your own with `send_invoice` Invoices and subscriptions accept a new `collection_method: send_invoice`. Fintoc does not charge the invoice on finalization. The invoice stays `open` with its `hosted_invoice_url`, so your customer can pay with the method they prefer or you can settle the invoice outside Fintoc. `charge_automatically` remains the default and does not change behavior. * **On one-off invoices:** `default_payment_method` is no longer required when you use `send_invoice`. The invoice stays open on finalization and moves to `paid` once you reconcile it. * **On subscriptions:** each cycle generates an invoice that stays `open` for you to collect. The subscription starts `active` instead of `incomplete`, even without a `payment_method`. See the [Create invoice reference](/api/payments-api/invoices/invoices-create) and the [Create subscription reference](/api/payments-api/subscriptions/subscriptions-create) for every parameter. **2026-07-31** Mark an invoice as paid outside Fintoc ## Mark an invoice as paid outside Fintoc `POST /v2/invoices/{id}/pay` accepts a new `external_payment` parameter. Send `true` when you collected the invoice through another channel (manual transfer, cash, another provider) and want it recorded as paid. Fintoc moves the invoice to `paid` right away, creates no `Payment`, and exposes `external_payment: true` on the object. * **Works on any `open` invoice:** Use `external_payment` on invoices Fintoc tried to charge and failed, so you can close the invoices manually without retrying the charge. * **Mutually exclusive with `payment_method`:** sending both returns `mutually_exclusive_params`. Choose between charging a specific method and recording an external payment. * **Not reversible:** Fintoc does not verify the amount you collected and the operation cannot be undone. See the [Pay an invoice reference](/api/payments-api/invoices/invoices-pay) for the full request shape. **2026-07-31** Business profile on invoices and subscriptions ## Business profile on invoices and subscriptions When you create an invoice or a subscription, you can declare the `business_profile` of the business you collect the payment on behalf of. You already use this field on `CheckoutSession` and `PaymentIntent`; the field is now available across the recurring flow. The field is required if your organization identifies a business profile per payment (aggregators). * **On one-off invoices:** Fintoc applies `business_profile` to the charge it issues when you finalize the invoice. * **On subscriptions:** Fintoc applies `business_profile` to every automatic charge the subscription generates. * **Fields:** `category` (six-character merchant category code), `name`, and `tax_id` of the business. See the [Create invoice reference](/api/payments-api/invoices/invoices-create) and the [Create subscription reference](/api/payments-api/subscriptions/subscriptions-create) for the full object. **2026-07-31** Retrieve a fiscal invoice by ID ## Retrieve a fiscal invoice by ID The Fiscal API exposes a new `GET /v1/invoices/{id}` endpoint. Get a Chilean Internal Revenue Service (SII) or Mexican Tax Administration Service (SAT) invoice by its `id`. Authenticate with the `link_token` of the fiscal `Link` that holds the invoice. The endpoint only returns invoices that belong to the `Link` you send. On `income` links, the endpoint only returns fee receipts the account holder issued. See the [Invoice object reference](/api/fiscal-api/fiscal-invoices/fiscal-invoices-object) for every field the endpoint returns. **2026-07-30** One payout for every payment method you collect with ## One payout for every payment method you collect with The payout Fintoc sends you in Chile now covers every payment method Fintoc collects with on your behalf: bank transfers, cards, installments, and payment buttons. Fintoc previously sent card payments in their own payout; card payments now arrive in the same transfer as the other payment methods. * **One transfer per cycle:** the payout amount is the net of every payment method for that cycle. Your payout schedule, its cut-off time, and the account that receives the funds do not change. * **One reconciliation report:** every transaction comes in the payout reconciliation report with `resource_type: payment_intent`, and `resource_subtype` tells you the method: `bank_transfer`, `credit_card`, `debit_card`, `prepaid_card`, `installment`, `pac`. Fintoc discontinued the separate card report. * **One payout event per cycle:** you receive one `payout.created` and one `payout.succeeded` instead of one pair per payment method. The `Payout` object does not change. If you collect with `charges`, that payout and its report stay separate. See the [reporting and reconciliation guide](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation#the-payout-reconciliation-report) for every column of the report. **2026-07-30** Recover a subscription when its payment method fails ## Recover a subscription when its payment method fails A subscription's charges can fail when an account closes, a card expires, or a Pago Automático de Cuentas (PAC) authorization is revoked. The failed payment method also blocks your customer's future charges. You can update the subscription's payment method without recreating the subscription from scratch. * **Send your customer a link:** create a `CheckoutSession` with `flow: setup` pointing at the subscription, and your customer enrolls a new method from that link. * **Update the payment method through the API:** if your customer has already authorized a payment method, associate that method with `PATCH /v2/subscriptions/{id}`. Changing the payment method never charges outstanding invoices. Collect outstanding invoices separately by sending your customer each invoice's `hosted_invoice_url`. Track the swap with the `subscription.payment_method_updated` and `subscription.payment_method_update_failed` events. See the [Subscription object reference](/api/payments-api/subscriptions/subscription-object) for details of PAC activation. See the [Events reference](/api/main-resources/events-reference/types-of-events) to check the status of a payment method update in progress. **2026-07-30** Simulate entity onboardings in test mode ## Simulate entity onboardings in test mode `Entity` onboardings in the Business Accounts API now work in test mode. When you submit an onboarding with an `sk_test_...` key, Fintoc runs an immediate simulated review instead of a real compliance review. You can exercise the approved and rejected paths without waiting. * **Trigger values for `business_activity`:** `illegal` forces `rejected` and emits `entity.onboarding.rejected`. `suspicious` leaves the onboarding in `submitted` with no event. Any other value forces `approved` and emits `entity.onboarding.approved`. Fintoc compares the exact string, including case and whitespace. * **Mode isolation:** `test` and `live` onboardings are separate objects. A `test` key cannot read or act on a `live` onboarding and vice versa; both cases return `404 Not Found`. See the [Onboard an entity by API guide](/guides/business-accounts/entities/onboard-an-entity-by-api#test-the-integration) for the full trigger table and webhook examples. **2026-07-23** Transferencia bancaria como método de pago reutilizable ## Transferencia bancaria como método de pago reutilizable El objeto `PaymentMethod` ahora acepta el tipo `bank_transfer`, además de `card` y `pac`. Cuando un cliente inscribe una cuenta bancaria como método de pago, guardas la cuenta una sola vez y la reutilizas en pagos y suscripciones sin volver a pedir credenciales. * **Nuevo objeto `bank_transfer`:** expone `account_holder_id`, `account_number`, `account_type` (`checking_account` o `sight_account`), `institution_id`, `institution_name`, `mfa_type` y `status` (`active`, `pending` o `canceled`). * **Referencia igual que otros tipos:** el campo `type` indica `bank_transfer` y los detalles quedan en un campo homónimo, siguiendo el mismo patrón que `card` y `pac`. Revisa la [referencia del objeto Payment Method](/api/payments-api/payment-methods/payment-method-object) para ver todos los campos. **2026-07-23** Más contexto en Charges, Movements, Refresh Intents y Subscriptions ## Más contexto en Charges, Movements, Refresh Intents y Subscriptions La API ahora expone campos adicionales en varios objetos para que reconcilies y depures con menos llamadas: * **`Charge`:** ahora incluye `subscription_id` para identificar la suscripción que originó el cobro. El objeto también incluye `recipient_account` con la cuenta que recibe los fondos (`holder_id`, `institution_id`, `number`, `type`). Revisa la [referencia del objeto Charge](/api/direct-debit-legacy/charges/charge-object). * **`Movement`:** ahora incluye `document_number` (número que asigna la institución al movimiento) y `transfer_id` (identificador que la institución asigna a la transferencia). Revisa la [referencia del objeto Movement](/api/movements-api/movements/movements-object). * **`RefreshIntent`:** nuevo campo `public_error` con el código de error cuando `status` es `failed`. `retryable_error` indica que puedes reintentar; `support_required_error` que debes contactar a soporte. Revisa la [referencia del objeto Refresh Intent](/api/movements-api/refresh-intents/refresh-intents-object). * **`Subscription`:** cada `line_item` ahora incluye el objeto `product` completo. El objeto incluye `id`, `object`, `created_at`, `description`, `image_url`, `metadata`, `mode` y `name`, en lugar de solo `name`. Revisa la [referencia del objeto Subscription](/api/payments-api/subscriptions/subscription-object). **2026-07-22** Acepta pagos en tu tienda WooCommerce con Fintoc ## Acepta pagos en tu tienda WooCommerce con Fintoc Publicamos el plugin de Fintoc para WooCommerce. Instálalo en tu tienda para aceptar pagos por transferencia bancaria y tarjeta en pesos chilenos (`CLP`) y pesos mexicanos (`MXN`) a través del Checkout Session alojado de Fintoc. Descarga el plugin desde la [página de Fintoc para WooCommerce](https://woocommerce.fintoc.com/), configura tu clave secreta y empieza a cobrar. * **Confirmación mediante webhooks:** el plugin confirma cada orden en segundo plano y verifica el estado del pago directamente contra la API de Fintoc, que es la fuente de verdad. No necesitas un secreto de webhook. * **Reembolsos desde WooCommerce:** emite reembolsos totales o parciales desde la pantalla de la orden. El plugin envía la solicitud a la API de reembolsos de Fintoc y los concilia con los eventos `refund.*`. Revisa la [guía de WooCommerce](/guides/payments/e-commerce-connectors/woocommerce) para ver la configuración paso a paso. **2026-07-16** Cobra facturas con un enlace de pago ## Cobra facturas con un enlace de pago Cada factura tiene su propia URL de pago, disponible en el campo `hosted_invoice_url`. Comparte el enlace por WhatsApp, email o el canal que uses. La factura queda al día en cuanto tu cliente paga. * **Recupera un cobro fallido:** cuando el cobro automático de una suscripción falla, Fintoc emite `invoice.payment_failed` y habilita `hosted_invoice_url` para esa factura. Envía el enlace a tu cliente para recuperar el pago. * **Concilia pagos automáticamente:** el enlace está asociado a la factura. Cuando tu cliente paga, la factura queda marcada como pagada y facilita la conciliación. Tu cliente paga con los métodos de pago configurados para tu organización. Revisa la [documentación de pagos recurrentes](/guides/payments/accept-recurring-payments/manage-invoices#recovering-a-failed-payment) para ver el detalle del flujo. **2026-07-06** Períodos de prueba y UF en suscripciones ## Períodos de prueba y UF en suscripciones Ampliamos la API de suscripciones con dos capacidades nuevas: * **Períodos de prueba (`trial_end`):** al crear una suscripción puedes definir la fecha en que termina la prueba (mínimo un día en el futuro). Durante la prueba la suscripción queda en estado `trialing` y Fintoc no emite factura. Fintoc alinea el `billing_cycle_anchor` al término del período y genera la primera factura cuando la prueba termina. * **Cobros en UF (`CLF`) dentro de suscripciones en CLP:** un ítem con precio en `CLF` es facturable dentro de una suscripción en `CLP`, útil para planes indexados a UF. Fintoc convierte el monto al facturar y valida la compatibilidad de monedas entre ítems. Además, el ciclo de vida de una suscripción ahora incluye el estado `incomplete`: la suscripción parte en `incomplete` y avanza a `active` cuando el primer pago se acredita. Fintoc cobra automáticamente usando el `payment_method` (`collection_method: charge_automatically`). Revisa la [documentación de suscripciones](/api/payments-api/subscriptions/subscription-object) y la [guía de pagos recurrentes](/guides/payments/accept-recurring-payments) para ver los ejemplos completos. **2026-07-06** Nombre y descripción en ítems de suscripción ## Nombre y descripción en ítems de suscripción Los `line_items` de suscripciones aceptan dos campos nuevos: * **`name`:** nombre visible del ítem tal como aparece en la factura. * **`description`:** detalle adicional del ítem, también visible en la factura. Puedes fijarlos al crear la suscripción y actualizarlos con `POST /v2/subscriptions/:id/items/:id`. Los cambios se reflejan en la próxima factura sin prorrateo. Revisa la [referencia de subscription items](/api/payments-api/subscription-items/subscription-item-object) para ver el detalle. **2026-07-06** Metadata de tarjeta en Payment Intents ## Metadata de tarjeta en Payment Intents Los pagos con tarjeta ahora exponen un objeto `card` dentro de `payment_type_options` del `PaymentIntent`, con los datos que necesitas para reconciliar y personalizar la experiencia post-pago: * `brand`, `kind` (`credit`, `debit`, `prepaid`) y `last_four_digits`. * `bank` y `country` de emisión. * `authenticated_with_3ds`: `true` cuando el titular completó 3-D Secure. * `wallet`: `apple_pay`, `google_pay` o `null` si la tarjeta se ingresó manualmente. El objeto está disponible únicamente para pagos con tarjeta. Los pagos por transferencia y en efectivo conservan el comportamiento existente. Revisa la [referencia del objeto Payment Intent](/api/payments-api/payment-intents/payment-intents-object) para ver todos los campos. **2026-07-06** Nuevos eventos de webhook para facturas ## Nuevos eventos de webhook para facturas Agregamos dos eventos al ciclo de vida de una factura: * **`invoice.payment_created`:** Fintoc lo envía cuando inicia el pago de una factura, antes de conocer el resultado. * **`invoice.voided`:** Fintoc lo envía cuando se anula una factura. Si ya tienes un endpoint suscrito a eventos de facturas, actualiza tu switch para manejar estos nuevos tipos. Revisa la [referencia de tipos de eventos](/api/main-resources/events-reference/types-of-events) y la [guía de webhooks](/guides/resources/webhooks-walkthrough) para más detalle. **2026-07-06** Filtrar clientes por Tax ID ## Filtrar clientes por Tax ID El endpoint `GET /v2/customers` acepta dos nuevos parámetros de query: * **`tax_id`:** RUT (con o sin puntos y guión) o RFC (en cualquier capitalización). * **`tax_id_type`:** `cl_rut` o `mx_rfc`. Si envías `tax_id` sin `tax_id_type`, Fintoc lo compara contra ambos formatos. Enviar `tax_id_type` sin `tax_id` devuelve todos los clientes con un tax ID en ese formato. Un `tax_id_type` no soportado retorna `400` con `code: invalid_enum`. Revisa la [referencia de list customers](/api/payments-api/customers/customers-list) para ver ejemplos. **2026-06-25** Luna aterrizó en tu dashboard ## Luna aterrizó en tu dashboard Ahora puedes gestionar tu operación de pagos en lenguaje natural desde el dashboard. Pregúntale a Luna qué está pasando con tus pagos o pídele que ejecute una tarea. Luna usa el contexto de tu cuenta: organización, país y vista actual del dashboard. También te ayuda a orientarte, encontrar lo que buscas y consultar la documentación de Fintoc sin abrir otra pestaña. ### Qué puedes hacer hoy * Preguntar qué está pasando en la pantalla donde estás. * Crear Claves Bancarias Estandarizadas (CLABE) o clientes desde el chat a partir de una lista de nombres. * Crear o cancelar reembolsos. * Analizar tus pagos, medios de pago y tasas de éxito según lo que es relevante para tu negocio. * Resolver dudas de integración con respuestas basadas en la documentación de Fintoc. ### Cómo empezar Luna ya está disponible en tu dashboard. Entra a tu [dashboard](https://dashboard.fintoc.com/login) para empezar a usarla. **2026-06-22** Crea nuevas razones sociales vía API o Dashboard ## Crea nuevas razones sociales vía API o Dashboard Ahora puedes dar de alta nuevos clientes como razones sociales (el objeto `Entity` en la API). Luego completas su verificación Know Your Business (KYB) desde la API o desde el Dashboard. Ya no necesitas coordinar el proceso verbalmente con Fintoc. Elige el flujo según cómo trabajas hoy: * **Desde el Dashboard:** da de alta a tus clientes manualmente, sin escribir código. * **Desde la API:** integra la API si ya tienes un proceso de onboarding con tus clientes. Incorpora los campos adicionales que pide Fintoc para mantener una experiencia uniforme para tus clientes. Fintoc revisa la verificación KYB y te notifica cuando la razón social queda lista para operar. Revisa la referencia de las APIs de [entidades](/api/business-accounts-api/entities/entities-create) y [onboarding](/api/business-accounts-api/onboardings/entities-onboardings-create) para ver el flujo completo. **2026-06-18** Reembolsos por transferencia en minutos ## Reembolsos por transferencia en minutos Los reembolsos por transferencia ahora se desembolsan apenas se crean, en lugar de esperar al payout diario. Antes podían tardar hasta cerca de un día en llegar a la cuenta de tu cliente; ahora se completan en minutos. ## Qué cambia para tu integración Nada. La mejora aplica del lado de Fintoc. Usas los mismos endpoints, recibes los mismos eventos (`refund.in_progress`, `refund.succeeded`, `refund.failed`) y los estados siguen siendo `created`, `in_progress` y `succeeded`. Lo único que cambia es que el reembolso llega a `succeeded` en minutos. ## Qué se mantiene igual * **Saldo insuficiente:** si tu saldo disponible no cubre el monto, el reembolso queda en `created` y Fintoc lo reintenta automáticamente. * **Expiración:** si el saldo no alcanza tras 5 días hábiles, el reembolso pasa a `failed`. * **Cancelación:** puedes cancelar un reembolso con `POST /v1/refunds/:id/cancel` solo mientras está en `created`. Con este cambio, un reembolso con saldo suficiente avanza a `in_progress` en segundos, por lo que la ventana para cancelarlo es más corta. Revisa la [documentación de reembolsos](/guides/payments/fintoc-collect-payments/payment-initiation-refunds) para ver el detalle del flujo. **2026-05-27** MCP de Fintoc ## MCP de Fintoc Lanzamos el **MCP de Fintoc**. Conéctalo a Claude, Cursor o ChatGPT y opera Fintoc en lenguaje natural, sin cambiar de pestaña ni escribir scripts. ## ¿Por qué usarlo? * **Tu operación financiera desde el chat que ya usas:** pregunta por un pago fallido, consulta tu próxima dispersión o confirma si llegó una transferencia específica. * **Docs en contexto:** el agente lee la documentación antes de proponer código, para ayudarte en base al producto real. * **Gratis e incluido con todos los productos Fintoc.** ## ¿Cómo usarlo? Agrega el servidor desde tu cliente MCP y completa el flujo OAuth en el browser: ```text theme={null} https://mcp.fintoc.com ``` Revisa la [guía completa del MCP](/guides/resources/building-with-ai/model-context-protocol-mcp) para ver la lista de tools disponibles y más detalle de la instalación. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/12fd59b69910ca599acaad8ad6dea399162cdc909ec754a2129fa7f8da28caa2-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=23731835288997bb0329f6840983e7a5) **2026-05-25** Métodos alternativos para pagos por transferencia ## Métodos alternativos para pagos por transferencia Ahora puedes ofrecer pagos directos desde BancoEstado, Banco de Chile, Santander y Mach en tu checkout. Tus clientes pagan desde la app o sitio de su banco, con límites más altos que TEF, y tú no tienes que tocar tu integración para activarlos. Cada nuevo método amplía la orquestación de pagos de Fintoc: en cada intento evaluamos disponibilidad, costo y límites entre los proveedores habilitados en tu cuenta, y enrutamos la transacción al camino óptimo. ### Ventajas: * **Integración directa con cada banco:** El cliente confirma el pago desde su app o sitio bancario habitual. * **Límites de transferencia más altos:** Aprovecha límites superiores a los de la transferencia electrónica de fondos tradicional. * **Acepta pagos de empresas**: Permite a tus clientes pagar con la cuenta bancaria de su empresa. * **Sin cambios en tu integración:** No necesitas modificar código ni desplegar nada para empezar a recibir pagos por estos canales. Contacta al equipo de Fintoc para activarlos. 📘 Revisa la [documentación](/guides/payments/alternative-payment-methods) para revisar los detalles. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/c34c2282354c609cd139bdc19a923a97e1f0e2e205750444fceb9b0fce3bb515-grabacion2.gif?s=b1ee62ef72a87d1dede2a863481e00b8) **2026-05-12** Múltiples API Keys en tu organización ## Múltiples API Keys en tu organización Múltiples Secret API Keys Ahora puedes crear hasta 10 Secret API Keys por organización. Asigna un nombre y, opcionalmente, una fecha de expiración a cada una. ## ¿Por qué usarla? * **Separa ambientes o servicios**. Una key dedicada por integración, sin compartir credenciales. * **Rota sin downtime**. Crea la nueva, migra tu integración, revoca la vieja. * **Revoca instantáneamente**. Si una key se filtra, la puedes dar de baja sin afectar al resto. * **Programa expiraciones**. Útil para accesos temporales o pruebas con terceros. Crea una nueva en Dashboard > Para desarrolladores > API Keys > Crear secret key. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/d5be603e2466c179d1d04acb55d46a2a9b66012e58a26885914a0f12ba713828-ScreenRecording2026-05-12at3.57.45PM-ezgif.com-optimize.gif?s=3ffc4a67a2a14e9e906ced2b64aa54a9) **2026-05-12** Fintoc CLI ## Fintoc CLI Lanzamos la **CLI de Fintoc**, una herramienta para que tú o tu agente IA puedan interactuar con la API directo desde la terminal. Crea recursos, lista pagos y recibe webhooks en `localhost` sin abrir el Dashboard ni levantar túneles. ## ¿Por qué usarla? * **Time-to-first-call más corto:** instala, autentícate y haz tu primer llamado en menos de un minuto. * **Itera más rápido durante la integración:** prueba payloads, lista recursos y crea webhooks sin armar requests a mano. * **Recibe webhooks en `localhost` sin túneles como ngrok.** ## ¿Cómo usarla? Instálala con Homebrew ```bash theme={null} brew install fintoc-com/tap/fintoc fintoc login ``` Recibe webhooks en tu server local: ```bash theme={null} fintoc webhooks listen --forward-to http://localhost:4242/webhooks ``` Y opera tus recursos con `fintoc `: ```bash theme={null} fintoc transfers create --amount 10000 --currency CLP --counterparty-account-number 00000000 fintoc charges list --status succeeded --since 2026-01-01 ``` Revisa la [guía completa de la CLI](/guides/resources/cli) para ver todos los comandos y flags disponibles. Si quieres saber más sobre la CLI, escribimos este [blog](https://fintoc.com/blog/presentando-la-cli-de-fintoc). **2026-05-12** Botón de Apple Pay para pagar con one-click en tu checkout ## Botón de Apple Pay para pagar con one-click en tu checkout Ahora puedes implementar un botón de Apple Pay directamente en tu página de checkout, sin redirigir al usuario. Tu cliente toca el botón, confirma con Face ID o Touch ID, y el pago se completa en segundos. ### Ventajas: * **Sin redirección:** El botón de Apple Pay se renderiza directo en tu página. El usuario nunca sale de tu sitio. * **Mayor conversión:** Face ID / Touch ID reemplazan formularios de tarjeta. Menos pasos, menos abandonos. * **Misma API:** Usa Checkout Sessions como siempre. Solo cambia el frontend para el botón. 📘 Revisa la [documentación](/guides/payments/accept-a-payment/accept-a-one-click-payment-with-apple-pay) para integrar el botón en tu checkout. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/d4d213f395fdde87ce349aef8e42199832d466b5619486678e9228f8438f7ddd-ScreenRecording_05-12-202616-21-05_1-ezgif.com-video-to-gif-converter.gif?s=510ccf9c923cc0f835ca2265eb8abe63) **2026-04-14** Estados de cuenta mensuales ## Estados de cuenta mensuales Tus cuentas Fintoc ahora generan estados de cuenta mensuales en PDF, listos para descargar desde el Dashboard o consultar por API. Cada documento resume los movimientos, balances, abonos y cargos del periodo, con la información que exige la regulación. Ya no necesitas armar esta información manualmente con planillas o copiando y pegando valores. Los estados de cuenta son retroactivos: si ya llevas meses operando, encontrarás los documentos de periodos anteriores disponibles automáticamente. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/7fea339cdc9f7c2a154166a5d509dcff5dfdf61c2c23dafaadb2f1410c3bb116-Screenshot_2026-04-14_at_6.09.11_PM.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=834f890e43f7dc20ea2bd70bfb2446d8) ## Ventajas * **Descarga los estados de cuenta:** Selecciona uno o varios estados de cuenta y descárgalos con un click. * **Envíalos por correo a varias personas:** Si tienes que enviar el estado de cuenta por email a una o más personas lo puedes hacer muy fácilmente. * **Desde el Dashboard y API:** Obtén los estados de cuenta que quieras con su link de descarga. * **Exporta movimientos:** Además de los PDFs, ahora puedes exportar el detalle de movimientos de cualquier cuenta en CSV, XLSX. ### Ejemplo de PDF ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/4e39c6ebd1705885baecbe44bf5c3b69e04fbdb6886d9f0f16b85253b52093a4-Screenshot_2026-04-14_at_6.11.13_PM.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=eb0e3d2be37cb09c20b7c3613b581b47) **2026-04-02** Busca y elimina CLABEs inactivas ## Busca y elimina CLABEs inactivas Ahora puedes [buscar fácilmente las CLABEs](/guides/business-accounts/inbound-transfers/manage-your-clabes) que no reciben transferencias hace un tiempo y luego [eliminarlas](/guides/business-accounts/inbound-transfers/manage-your-clabes) para liberar cuota para crear nuevas. **Importante:** Una vez eliminada, la CLABE entra en un periodo de espera antes de poder ser reasignada a otra organización. ## ¿Por qué usarlo? * **Libera cuota:** Cada CLABE eliminada reduce tu conteo de account numbers, permitiéndote crear nuevas. * **Identifica CLABEs inactivas:** El nuevo filtro `no_transfers_since` en `GET /v2/account_numbers` te permite encontrar CLABEs sin actividad desde una fecha específica. * **Reutilización limpia:** Las CLABEs eliminadas entran en un pool y pueden reasignarse a cualquier usuario de Fintoc en el futuro. Al reasignarse, su información y lógica asociada se reinician por completo. ## ¿Qué cambió? Principalmente cambios en la API: **Nuevos campos en el objeto [Account Number](/api/business-accounts-api/account-numbers/account-number-object):** * `deleted_at`: timestamp de eliminación (`null` si no ha sido eliminado). * `last_transfer_at`: timestamp del último pago recibido (`null` si nunca recibió uno). Ejemplo de response: ```json theme={null} { "id": "acno_3BkxMviliTqXkHnRfK9rPlmmlhJ", "account_id": "acc_3BkxMtA136XaUuVvYSp0Br2cDkC", "number": "000000000000000000", "created_at": "2026-04-01T12:33:44Z", "updated_at": "2026-04-01T12:33:44Z", "mode": "test", "description": null, "metadata": {}, "status": "enabled", "is_root": true, "options": { "min_amount": null, "max_amount": null }, "deleted_at": null, "last_transfer_at": "2026-04-02T12:33:44Z", "object": "account_number" } ``` **Nuevo [filtro](/api/business-accounts-api/account-numbers/account-numbers-list):** * `no_transfers_since` en [`GET /v2/account_numbers`](/api/business-accounts-api/account-numbers/account-numbers-list): filtra CLABEs que no han recibido transferencias desde una fecha. ```bash theme={null} curl --request GET \ --url 'https://api.fintoc.com/v2/account_numbers?no_transfers_since=2025-12-01' \ --header 'Authorization: sk_test_0000000000000000000000000000000000' \ --header 'accept: application/json' ``` **Nuevo [endpoint](/api/business-accounts-api/account-numbers/account-numbers-delete):** * [`DELETE /v2/account_numbers/{id}`](/api/business-accounts-api/account-numbers/account-numbers-delete): elimina un account number de forma permanente. ```bash theme={null} curl --request DELETE \ --url https://api.fintoc.com/v2/account_numbers/acno_3BkxMviliTqXkHnRfK9rPlmmlhJ \ --header 'Authorization: sk_test_0000000000000000000000000000000000' \ --header 'accept: application/json' ``` Disponible solo para México. Para más información, revisa la guía completa de [administración de tus CLABEs](/guides/business-accounts/inbound-transfers/manage-your-clabes) **2026-03-02** Guarda destinatarios y reutilízalos en tus transferencias ## Guarda destinatarios y reutilízalos en tus transferencias Ahora puedes crear y guardar destinatarios desde el Dashboard para reutilizar sus datos al momento de hacer transferencias. Ya no necesitas ingresar el número de cuenta, banco o nombre del beneficiario cada vez que quieras enviar dinero a un mismo destinatario. ### ¿Por qué usarlo? * **Menos errores en tus transferencias:** Al guardar los datos de un destinatario una sola vez, eliminas el riesgo de escribir mal los datos en transferencias recurrentes. * **Transferencias más rápidas:** Selecciona un destinatario guardado y transfiere en segundos, sin volver a llenar los datos de la cuenta destino. * **Gestión centralizada:** Consulta, busca y edita todos tus destinatarios desde la nueva pestaña Destinatarios en la sección de Transferencias. ### Para crear un destinatario 1. En **Transferencias > Destinatarios > Nuevo destinatario** ingresa los datos del beneficiario: nombre, número de cuenta, banco, y opcionalmente un correo y alias para identificarlo fácilmente. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/08d490bf4bc0b696293c548f691015a049878f193f75f990a963107d02760f94-Screenshot_2026-03-02_at_5.10.02PM_copy.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=2ff5b072fc6db37c4065992fc42038c6) ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/5dbe336c57fb318c840e30d2b9c9e17d7f13fad3e9c6b9b1066e81670aa86a17-Screenshot_2026-03-02_at_5.12.31PM.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=a8f4eee0f4880d7d6afc11212ddd83dd) 2. El destinatario aparecerá en tu **tabla de destinatarios**, donde podrás buscarlo por nombre, institución o número de cuenta. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/8a233da688f6721de1b54e41b21b07417c27f1095d2772d760c80eb7cefb60cd-Screenshot_2026-03-02_at_5.13.35PM_copy.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=e1bd96ac573dd7f951c8c26eb8c933d4) 3. En el detalle de cada destinatario puedes revisar su información, editarla o hacer clic en Transferir para enviarle dinero directamente. **2026-02-16** Define límites para rechazar transferencias automáticamente ## Define límites para rechazar transferencias automáticamente Ahora puedes definir límites mínimos y máximos al crear una CLABE, ya sea desde el Dashboard o vía API. Si una transferencia entrante no cumple con el rango establecido, el sistema la rechazará automáticamente. ### ¿Por qué usarlo? * **Reducción de costos operativos**: Elimina la carga de gestionar devoluciones manuales por montos incorrectos. El sistema filtra las operaciones por ti, ahorrando tiempo y recursos. * **Automatización de reglas de negocio**: Asegura que cada cuenta reciba solo lo que esperas, aplicando tus reglas de validación de forma inmediata y sin errores. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/18af005dd08b1d49882f046f635870d045201c01a87f5b3fdfa6679d9af6dcb5-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=e5c77c97e96da76117a9f8c550733e42) Revisa esta [guía](/guides/business-accounts/inbound-transfers/add-logic-to-clabes#set-inbound-transfer-amount-limits) para aprender más. **2026-02-09** Descarga comprobantes de transferencias ## Descarga comprobantes de transferencias Para usuarios de Business Accounts, ahora en el detalle de tus transferencias en el dashboard puedes descargar el comprobante Fintoc. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/905065d192c62f4793fe38ad9be4415024aed3dacf459e9c86e868533f80e8bd-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=d04a87e80b16cb5dd80265192307d291) Además, al crear transferencias desde el dashboard, podrás adjuntar hasta 5 direcciones de correo para enviar copias del comprobante. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/ab34f51277c07d7c02fd8414cc99b5b8fb7baffcfcc0abfbd1bb0ff1a7cddf35-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=50ebf7bc25704dfef673ca3c4421c35a) **2026-01-28** Apple Pay en Chile ## Apple Pay en Chile Ahora puedes ofrecer **Apple Pay** dentro del checkout de Fintoc, para que tus clientes paguen en segundos con Face ID/Touch ID, sin tener que ingresar los datos de su tarjeta. El pago por la billetera reduce fricción y errores, especialmente en móvil, y puede mejorar la conversión hasta en un 22%. Apple Pay viene habilitado por defecto en todos los checkouts con el método de pago por tarjetas, siempre que el dispositivo del usuario sea compatible con la billetera. 📘 Revisa la [documentación](/guides/payments/accept-a-payment) para crear un pago en sandbox y empezar a probar pagos con Apple Pay. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/a7848e5468ec71aca27c9783de7f8168b30b72cd03f6c1ad2a168e3a7b3cb3b5-697a10662fbb7af84bb77e6f_copy_6F5CAF30-FBF9-4D3C-9894-58EC488D1A26-ezgif.com-optimize_1.gif?s=9f9fa3708bec30e56b9e1f97bf61b577) **2026-01-27** Herramientas de visualización del dashboard ## Herramientas de visualización del dashboard Tenemos nuevas funcionalidades en el dashboard para que lo uses como te acomode más. Usa la navegación superior para: 1. Esconder y mostrar el menú lateral ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/2f4b216bd4a31f83ad8d62a95c6d7f0af6f89dad9113998465278fca1405d89a-sidebar_final.gif?s=f1aadbaa7af9fa334586065fbb0b7a7c) 2. Ver la configuración de tu perfil y cerrar sesión ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/b672b28fdde8b057917218f4e9b590ed2a37d320ef7d92ad2555be944b7634ee-profile_final.gif?s=95a013af795837f3916be578ff3648b2) 3. Moverte entre modo prueba y modo en vivo ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/f635501a7fb442cb3e24f5ff424b85e489f51c8d8a99c42086dc130e02377d2f-final_test_mode.gif?s=1b17cca0d01a5f2be548afa9c4392463) **2026-01-21** Pagos por Tarjetas en Chile ## Pagos por Tarjetas en Chile Ahora puedes aceptar pagos con tarjetas (crédito, débito o prepago) en Chile usando Fintoc, junto con transferencias bancarias. Así puedes ofrecer ambos métodos de pago para mejorar la conversión, con una sola integración, conciliación y reportería. Fintoc cuenta con certificación **PCI DSS Nivel 1** y soporta autenticación **3DS** cuando corresponde, para reducir el fraude y prevenir contracargos. 📘 Consulta la [la documentación](/guides/payments/accept-a-payment) para más detalles de la integración y empieza a probar el flujo de pago por tarjetas. Si te interesa conocer las condiciones comerciales y tarifas, [haz clic acá para conversar con un experto en medios de pago.](https://fintoc.com/cl/contacto) ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/6275e9fbdff786c06e5928ecd811790c2ebd591bf5db54d5ba15cbb862ee61b5-69714850ebff4ba0a48d2e2f_ScreenRecording_01-21-202618-33-38_1-ezgif.com-video-to-gif-converter.gif?s=ac19b0c74ad626c17117b4c741abfda2) Checkout Fintoc con las opciones de pago por transferencia y tarjetas **2026-01-15** Nueva navegación en el Dashboard ## Nueva navegación en el Dashboard Hicimos algunos cambios en la forma de navegar el dashboard, para que encuentres más rápido lo que estás buscando. 1. Reorganizamos la información y ahora tenemos 4 secciones principales: 1. **Iniciación de pagos**. Aquí encontrarás información y configuraciones sobre Pagos puntuales y recurrentes, hechos por tus usuarios a través del Checkout de Fintoc. 2. **Tesorería**. Aquí encontrarás Transfers y Accounts: herramientas e infraestructura para automatizar y tener control total del dinero de tu negocio. 3. **Conciliación** (Solo Chile 🇨🇱). Aquí encontrarás conexiones a cuentas de instituciones externas. 4. **Para desarrolladores**. Aquí podrás gestionar tus webhooks y obtener tus API Keys. 2. Ahora en modo "En vivo", sólo verás productos que ya tienes habilitados. En modo "Prueba" seguirás pudiendo probar todos los productos de Fintoc en nuestro Sandbox. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/2aeffc5967bafbbe7ae5791df8f77b9527f8751263271741e7281b85cc3b64a4-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=d97e92d5c1fb81d7201282bf1558a08e) **2026-01-08** Ask AI en nuestra documentación ## Ask AI en nuestra documentación Agregamos **Ask AI** a la documentación de Fintoc. Ahora, si tienes una duda técnica o necesitas encontrar un endpoint rápido, puedes preguntarle directamente al asistente integrado. Para probarlo, busca el botón **Ask AI** en la esquina superior derecha mientras navegas por los docs. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/a9b13a845e4b73a152c3f51a8a26c39baa80c813c861fdd8035f1c75832347ac-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=150cedd5447b4d81e75f0a89774d040f) **2025-12-11** Ahora puedes hacer payouts y recibir payins usando SPEI con Fintoc ## Ahora puedes hacer payouts y recibir payins usando SPEI con Fintoc Lanzamos el producto [Business Accounts](/guides/business-accounts/quickstart) en México, una forma de hacer payins y payouts, conectado directo al SPEI. Usando Business Accounts podrás: * Crear cuentas CLABE al instante * Verificación de CLABEs externas * Hacer payouts inmediatos * Recibir notificaciones en tiempo real de payins * Asociar metadata para agilizar tu conciliación * Hacer dispersiones masivas Todo esto y más está disponible 24/7 desde nuestro dashboard y vía [API](/api/business-accounts-api/transfers/transfers-create). ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/66cbe22ebe139c01a0daa1ccf046d98ce238db185c64172d262cb3937849abf2-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=44dffea128aeec179296d4c7447b70cf) **2025-12-04** Nuevo Widget de Débito Directo ## Nuevo Widget de Débito Directo Actualizamos por completo el widget de Débito Directo para hacerlo más rápido, más estable y visualmente alineado con los nuevos estilos de Fintoc. **Mejoras principales** * Nueva interfaz más limpia, moderna y fácil de usar. * Flujo más rápido, con tiempos de carga más cortos. * Menos errores en login y en los distintos métodos de autenticación (Mi Pass, SMS, coordenadas). * Mejor feedback visual durante el proceso y mensajes más claros para el usuario. * Pantalla de éxito renovada, con comprobante descargable y opción para compartir. **Qué cambia para los usuarios** El proceso de suscribir una cuenta ahora es más simple, más claro y funciona mejor, especialmente en bancos con MFA complejo. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/c3f01cb87819c859aa15260c9ab18b6197931164afaafcf6d4fbca3e1bd9baab-Screenshot_2025-12-04_at_1.16.01_PM.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=4abd9e232a376d26d73dc147566880df) **2025-10-14** Webhook de Cambios en los Movimientos ## Webhook de Cambios en los Movimientos Ahora puedes recibir notificaciones automáticas cuando un movimiento existente cambie alguno de sus atributos. Este nuevo webhook complementa al evento `account.refresh_intent.movements_removed`, permitiéndote detectar no solo movimientos eliminados, sino también movimientos modificados durante un refresh. **Tipo de evento** `account.refresh_intent.movements_modified` **Cuándo se activa** Se activa cuando el banco actualiza información de movimientos ya existentes, por ejemplo: * Cambio en la descripción del movimiento. * Cambio en el estado (`pending` → `confirmed`). * Cambio en los datos de transferencia para movimientos de tipo `transfer`. * Cualquier modificación de los atributos del movimiento entregados por el banco. **Ejemplo** ```json theme={null} { "id": "evt_L0zlW5YvC6oZDweQ", "type": "account.refresh_intent.movements_modified", "mode": "live", "created_at": "2025-10-14T19:42:42.486Z", "data": { "account_id": "acc_3gmPYoV3TrKbEp7q", "movements_changed": [ { "id": "mov_6EdV8pvHZz3YR50g", "type": "transfer", "amount": 110000, "status": "confirmed", "currency": "clp", "post_date": "2025-09-29T00:00:00Z", "description": "Abono Trf Desde Otro Banco en Linea test", "pending": false } ] }, "object": "event" } ``` **Activación** En tu dashboard debes ir a **Webhooks → Endpoints → Create + → Movements → Account refresh intents** y luego seleccionar el evento `account.refresh_intent.movements_modified` como se muestra en la imagen a continuación: ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/f5968c66a8094b6cc9f1479404ea71c45aaba1b3ae5b842da57aa0ee7fdab581-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=3a65f1a2e441b7b20161e0b80b6c3bfa) **2025-09-24** Errores de los Intentos de Suscripción ## Errores de los Intentos de Suscripción Ahora es más fácil entender por qué una suscripción falló. Agregamos visibilidad del error en tres lugares distintos: * **API**: El objeto `subscription_intent` ahora incluye el campo `public_error` cuando el status es `failed`. * **Webhooks**: En el webhook `subscription_intent.failed` también encontrarás el campo `public_error`. * **`OnExit` callback**: Ahora el callback recibe directamente el `errorReason`, que corresponde al mismo valor de `public_error`. **Tipos de `public_error`** * `login_invalid_credentials` * `login_credentials_locked` * `authorization_failed` * `authorization_timeout` * `request_timeout` * `subscription_intent_expired` * `internal_error` **Ejemplos** * Webhook `subscription_intent.failed`: ```json theme={null} { "id": "si_J4mE0vDPUevW3N2y", "mode": "live", "object": "subscription_intent", "status": "failed", "created_at": "2025-09-23T14:37:11Z", "public_error": "login_invalid_credentials", "reference_id": null, "subscription": null, "widget_token": null, "customer_email": null, "business_profile": null } ``` * `OnExit` callback: ```javascript theme={null} onExit: function onExit(errorReason) { console.log(errorReason); // ejemplo: "internal_error" } ``` * API: ```json theme={null} { "id": "si_KZJNzMNjUzlMeEa2", "status": "failed", "mode": "live", "created_at": "2025-09-23T21:29:15Z", "public_error": "internal_error", "object": "subscription_intent" } ``` **2025-09-15** Nueva Vista de Cuentas Bancarias ## Nueva Vista de Cuentas Bancarias Tenemos una nueva funcionalidad en el Dashboard de Links. Ahora, al seleccionar un Link en el Dashboard podrás ver: * Todas las cuentas bancarias asociadas a ese link. * El estado de cada cuenta (activa, conectando, inválida, etc.). * La última actualización y la próxima actualización a nivel de cuenta. Con esta nueva vista tendrás más visibilidad sobre la sincronización de tus cuentas, lo que te permitirá identificar de manera sencilla aquellas que requieran atención. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/b7e9cc3f5bc0244976f08e79d799aec2275fa0578ede893514dd28f50847326b-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=6eb37997718876c918db8aad8bd7f58c) **2025-08-25** Status de los Movimientos ## Status de los Movimientos Ahora puedes ver el status de los movimientos directamente en el endpoint List Movements. Antes solo se mostraban los movimientos confirmados, pero ahora tienes mayor visibilidad del ciclo de vida de cada movimiento y más control sobre la información que recibes. * Se agregó el campo `status` al recurso **[Movement](/api/movements-api/movements/movements-object)** en el endpoint **[List Movements](/api/movements-api/movements/movements-list)**. Consulta a continuación [**todos los posibles estados**](/api/movements-api/movements/movements-object#movement-status). * Nuevo *query param* `confirmed_only` que permite filtrar los movimientos: * `true`: Solo movimientos confirmados (default). * `false`: Todos los movimientos (incluye `confirmed`, `processing` y `reversed`). * El comportamiento por defecto de la API no cambia: si no envías el *query param*, solo verás los movimientos `confirmed`, tal como antes. **Request** ```http theme={null} GET https://api.fintoc.com/v1/movements?link_token=link_123&confirmed_only=false ``` **Response** ```json theme={null} { "id": "mov_BO381oEATXonG6bj", "object": "movement", "amount": 59400, "post_date": "2020-04-17T00:00:00.000Z", "description": "Traspaso de:Fintoc SpA", "transaction_date": "2020-04-16T11:31:12.000Z", "currency": "clp", "reference_id": "123740123", "type": "transfer", "pending": false, "status": "confirmed", "recipient_account": null, "sender_account": { "holder_id": "111111111", "holder_name": "Test Company 1", "number": "0000000000", "institution": { "id": "cl_banco_de_chile", "name": "Banco de Chile", "country": "cl" } }, "comment": "Pago factura 198" } ``` **2025-07-22** Intégrate más fácil con nuestro MCP Server ## Intégrate más fácil con nuestro MCP Server Acabamos de hacer que integrar Fintoc sea tan fácil como preguntarle a un amigo. Lanzamos nuestro MCP Server. Ahora tu herramienta de AI favorita puede conversar directamente con nuestra documentación, responder dudas y ayudarte a integrar Fintoc en pocas horas. Funciona con Cursor, Claude Code y cualquier herramienta de AI que soporte MCP. Se configura en menos de 30 segundos. Lo puedes [instalar desde acá](/guides/resources/building-with-ai/model-context-protocol-mcp). ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/f41936451a3e7aa65822fd5c30129fae2236d4abc06ad57a28a4786ec895d3ea-pretty_snap_2025_6_22_12_36.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=0248f3a62bd5f2cc2e17b846363b9690) **2025-06-30** Historial de Webhooks ## Historial de Webhooks Ahora puedes ver todos los *webhook events* que has recibido, cuántas veces se intentó el envío, el código y *payload* de la respuesta que Fintoc está recibiendo de tu servidor. Puedes encontrarlo en la nueva subsección **Eventos** en la sección de **Webhooks** en el Dashboard. Con esta información en tiempo real se vuelve simple y rápido entender y corregir errores de integración. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/1a981eb2b92f4e87de8f91dc543119ed332f3a86c4b7808d9cb356aa573a2175-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=2820b7060fcecc9c9a84649f7d310e0d) **2025-06-24** Notificación por correo al usuario ## Notificación por correo al usuario Millones de personas realizan pagos y suscripciones con Fintoc cada mes. Sabemos que muchas de ellas necesitan una confirmación y un registro claro de que la transacción fue realizada exitosamente, más allá del aviso visual en el widget. Ahora, Fintoc notifica al usuario por correo electrónico cuando hay una actualización sobre sus transacciones de pagos, reembolsos o suscripciones, incluyendo un enlace para contactar a nuestro Soporte por WhatsApp si necesita ayuda. El correo para recibir el comprobante puede ser proporcionado por el comercio mediante el parámetro `customer_email` al momento de crear la [Checkout Session](/guides/payments/accept-a-payment#create-a-session), o ingresado por el propio usuario en la pantalla de pago exitoso dentro del widget. ![Flujo para solicitar comprobante de pago exitoso por correo en el widget + ejemplo de correo enviado](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/c4511002d91b110f7e0ac0c08e04689e6dfdd05eb0d9de0503cd86d98337d385-Group_1171283198.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=3950b1c05d412338b403d5fd9873a2bf) Flujo para solicitar comprobante de pago exitoso en el widget + ejemplo del correo enviado **2025-06-24** Pagos por Efectivo en Mexico ## Pagos por Efectivo en Mexico Ahora puedes aceptar pagos en efectivo en México usando Fintoc. Con la integración a nuestra [Payment Intent API](/guides/payments/cash-payment-direct-api), puedes generar referencias de pago para que tus usuarios paguen en efectivo en más de 13.000 sucursales, como 7-Eleven, Walmart y farmacias. Al crear el pago desde la API, Fintoc responde con un número de referencia, un código de barras y un voucher con instrucciones para enviar al usuario. En el momento en que el pago se efectúa en la sucursal, Fintoc te notifica en tiempo real para que puedas avanzar en el flujo de entrega del producto o servicio. 📘 Consulta la [documentación de Cash Payments](/guides/payments/cash-payment-direct-api) para más detalles de la integración. ![Voucher con instrucciones para enviar al usuario](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/5d9f72655c9afc6174639611bcb148d817c3f6ad573b49efa855e730f98bfc8d-Precios_mas_bajos.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=8aff2d2179668c4c13a3fe201285c4d0) Voucher con instrucciones para enviar al usuario **2025-05-09** Entra a múltiples organizaciones con el mismo email ## Entra a múltiples organizaciones con el mismo email Sabemos que muchos de nuestros clientes optan por usar múltiples organizaciones para acomodar distintas razones sociales, recibir facturación separada, diferenciar el origen de los pagos y otras razones. Desde hoy es posible entrar a múltiples organizaciones usando un mismo email al iniciar sesión, facilitando el trabajo de quienes necesitan operar distintas organizaciones. Para empezar a usar esta funcionalidad, invita a los usuarios que necesites a todas las organizaciones donde necesiten estar. Una vez tengan acceso, podrán cambiarse usando el selector de organizaciones en la esquina superior izquierda del dashboard. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/571452ace126294eb821459d80bc8e225e685f6d9122b38d6efed58ea97a664f-Captura_de_pantalla_2025-05-09_a_las_19.02.03.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=0c1228699e5e2c8d7fb353a00475ba45) Desde el selector también se podrán crear nuevas organizaciones en caso de que tu empresa lo necesite. Al seleccionar la opción de crear una nueva organización te pediremos algunos datos y una persona del equipo de ventas te contactará para activar la nueva organización. **2025-04-14** Pagos via Redirect Page ## Pagos via Redirect Page ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/19d8fb812bd8f7927691cee5e160ee42a8f9b5fc984556f334a12c5dd2542b41-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=12fe9c0fdb7cb9e8a56364e8d91a33da) Ahora puedes habilitar un flujo de pagos mediante una **página de redirección para cargar el Fintoc Widget**. Esto te permite optar por una integración más simple, sin necesidad de implementar el widget directamente en tu frontend. Para usarlo, solo debes: 1. Crear un Checkout Session desde tu backend, incluyendo los parámetros `success_url` y `cancel_url`. 2. Recibirás en la respuesta un `redirect_url`, que debes usar para redirigir a tu cliente a la página de pago de Fintoc. 3. Una vez realizado (o cancelado) el pago, el cliente será redirigido automáticamente a la URL correspondiente. Además, recibirás el webhook con el resultado final del pago para continuar con procesos de confirmación o reintento. 📘 Para más detalles, consulta la [documentación para habilitar el flujo via Redirect page.](/guides/payments/accept-a-payment#redirect-the-customer-to-complete-the-payment) **2025-04-09** Error público ahora disponible en webhooks de Movements ## Error público ahora disponible en webhooks de Movements Los eventos `account.refresh_intent` incluyen un nuevo atributo `public_error` que representa el tipo de error de la actualización. Para cada evento relacionado hay distintos valores. * `account.refresh_intent.succeeded`: el valor siempre será `null` * `account.refresh_intent.rejected`: el valor siempre será `null` * `account.refresh_intent.failed`: hay dos valores * `support_required_error`: indica que la actualización falló por un error que requiere asistencia de nuestro equipo de soporte. * `retryable_error`: indica que la actualización falló por una intermitencia, por lo que se puede reintentar de inmediato. Este es un ejemplo de un webhook `account.refresh_intent.failed`: ```json theme={null} { "id": "evt_00000000", "type": "account.refresh_intent.failed", "mode": "test", "created_at": "2021-12-07T21:56:07.711Z", "data": { "object": "refresh_intent", "refreshed_object": "account", "refreshed_object_id": "acc_00000001", "status": "failed", "public_error": "retryable_error", "created_at": "2021-12-07T00:00:00.000Z", "type": "only_last", "new_movements": 0 }, "object": "event" } ``` > [!NOTE] > > **Valor de `public_error`** > > El valor de `public_error` puede variar según el tipo de error. En este ejemplo es `retryable_error`, pero también puede ser `support_required_error` o `null`. **2025-03-19** Payment Links ahora disponible para Direct Payments y Fintoc Reconciles ## Payment Links ahora disponible para Direct Payments y Fintoc Reconciles Hasta ahora nuestro producto de [Links de Pago](/guides/payments/payment-links) sólo estaba disponible en Chile para clientes que usan el modelo [Fintoc Collects](/guides/payments/fintoc-collect-payments). Desde hoy, empresas que usan [Direct Payments o Fintoc Reconciles](/guides/payments/direct-payments) también podrán crear links de pago a través de nuestra API. ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/94e5f097f2463dd5dd8e2b21d19435900a37df116b634ff2da80a81b25029fbf-Captura_de_pantalla_2025-03-19_a_las_11.43.54.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=933c16c49244f4a0247b8e51d9389505) El producto de links de pago es útil para mejorar tus flujos de venta, recuperar carritos abandonados o realizar cobros por whatsapp o mail. Puedes leer más sobre este producto [en nuestro blog](https://fintoc.com/blog/cobra-facil-con-un-link-de-pago), y si quieres activarlo, contacta a nuestro equipo de ventas enviando un mail a [sales@fintoc.com](mailto:sales@fintoc.com). **2025-02-19** Pagos por Transferencia Directa en Chile ## Pagos por Transferencia Directa en Chile ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/57f77082342e210d40179624ee97c043b7ee669ad40475c5ac659f850b001700-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=f06a1ace5f3d09c97a02470e39903a2f) Desde noviembre, es posible aceptar pagos de todos los bancos y wallets en Chile, incluso cuenta tipo empresa. Los usuarios pueden pagar transfiriendo manualmente el monto utilizando los datos de la cuenta. Una vez completada la transferencia, Fintoc detecta y valida automáticamente el pago. Para más información puedes [leer este blogpost.](https://fintoc.com/blog/recibe-pagos-desde-cualquier-cuenta-o-wallet-de-chile-incluso-empresas) **2025-02-19** Rediseño de las vistas de error para incentivar a reintentar ## Rediseño de las vistas de error para incentivar a reintentar ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/d03fb60b705c1c067430beb427be419c19d03f9c6eef0ea658aa7b60cc7fd7c6-Group_1171283153.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=a8ccaaa93844c9cd85ef196321258975) En el rediseño aplicamos mejoras para aumentar la conversión de que el usuario siga a finalizar su pago al recibir un aviso de error. Los errores reintentables ahora se muestran en azul con un icono de información. **2025-02-14** Seguridad en la API ## Seguridad en la API ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/aa5b375a1d8bac169ce62cb0aaf21721ef0051aed297ff5fcd69cb1e608c0587-67a637436edb67db9e8a3f86_ip_whitelisteada.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=ba40c8ec3016f84658f445d8db38703c) Implementamos medidas adicionales de seguridad a la API para que tú o tus clientes puedan operar Fintoc sin preocupaciones. Ahora puedes hacer esto: Whitelisting de IPs: restringir las direcciones IP desde donde nuestra API aceptará operaciones.\ Agregar una capa de seguridad extra a tus solicitudes a la API usando JSON Web Signature (JWS). **2025-02-14** Comunicando errores de conexión ## Comunicando errores de conexión ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/0b4002788356ec2990f83facee3047a34a76fcae929e5c015092dc088d71ca41-Screen_Error_links.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=4cffc2e40946bcc004a94d67aefedfc8) Para el producto de Conciliación Bancaria, hemos mejorado las vistas de errores de conexión. Ahora las personas que conectan sus credenciales podrán ver desglosado que cuentas se conectaron, cuáles no y que permisos necesitan habilitar en su banco para poder conectarla correctamente. **2025-02-13** Permisos - Ahora más granulares ## Permisos - Ahora más granulares ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/71f3541a9996f8b9ee68ab164b3ce2f0a3f20209d1a94e045a85ece13f59517d-67a636ebe9cd97f70d2b8560_persmisos.gif?s=f6cd8a2817cc3fe4b03053e020f29df3) Ahora puedes asignar permisos individuales a los usuarios en vez de roles predefinidos. Puedes decidir quién puede realizar acciones específicas, como ver pagos, procesar reembolsos o gestionar las API Keys, entre otros. Para simplificar la configuración, hemos creado roles sugeridos como Operaciones y Soporte, que puedes ajustar según tus necesidades. Este cambio no afecta los permisos actuales de los usuarios de tu organización. Todo seguirá funcionando de la misma manera. Conoce más sobre el [nuevo sistema de permisos](/guides/home/dashboard/permission-roles). **2025-02-13** Ve y descarga tus facturas ## Ve y descarga tus facturas [Usabilidad de Facturas en el dashboard de Fintoc](https://www.youtube.com/watch?v=zsRBmBQ890Q) Habilitamos la descarga de facturas y archivos de usabilidad desde el dashboard en la sección de ajustes. Con esto puedes ver tu histórico de facturas y a qué operaciones corresponde cada factura. Úsalo [acá](https://dashboard.fintoc.com/organization). **2025-02-07** Pagos con Face ID o huella ## Pagos con Face ID o huella ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/f7e0167d60bf4f84689d47c73d5572edfa239c7fc3cfbda41788baeba2adcb85-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=529875ff8b887676399e12eb5fd17873) ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/de6ecbc32ea4189d7e9163ab3a74f720e541ba4ccb0786a70a8b0a0466856e97-image.png?fit=max\&auto=format\&n=4VBGE3irVfHiwi6Y\&q=85\&s=be8db2cbecdd1b16c39f9be6dcf186a7) Desde diciembre, los usuarios pueden usar Face ID o huella en vez de escribir el RUT y contraseña cada vez que pagan con Fintoc. Usando passkeys (cifrado asimétrico) los usuarios pueden hacer login con su huella o Face ID, logrando un pago hasta 6 segundos más rápido. Para más información puedes [leer este blogpost](https://fintoc.com/blog/paga-con-face-id-en-fintoc). **2025-02-07** Analytics - Tus métricas de un vistazo ## Analytics - Tus métricas de un vistazo ![](https://mintcdn.com/fintoc-49b8bee8/4VBGE3irVfHiwi6Y/images/23eab5731e7c4772a18e3e38fa45913faa37946f8985ef6a58baeb2af4c9d2a0-analytics-gif.gif?s=4039876ffbbb5fbc456ef3349be1d32a) Además de recibir webhooks con toda la información relacionada a un pago (que requiere tiempo y recursos para procesar), ahora puedes tener de un **vistazo las métricas más importantes de tus pagos en el mismo dashboard**. Gana más visibilidad de tus operaciones en la [sección Resumen](https://dashboard.fintoc.com/analytics). Importante: esta función solo está disponible para clientes de Iniciación de Pagos. **2020-10-21** Welcome to Fintoc ## Welcome to Fintoc Welcome to the developer hub and documentation for Fintoc!