# API keys Source: https://docs.fintoc.com/guides/home/api-keys 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 **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 your API keys We recommend rotating your API keys at least once a year. You can rotate your API keys from the [Dashboard](https://dashboard.fintoc.com/api-keys). ## 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. ### 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. **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 and Widget requests, and how to handle `429 Too Many Requests` responses. Fintoc applies separate rate limits to API requests and Widget connections. This page explains both 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. **Widget connection rate limit:** Up to 100 requests per 130-second window for each organization across Widget connections. 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 Track changes and upgrades to the Fintoc API This page explains which API changes Fintoc treats as backwards compatible and how Fintoc versions changes that are not backwards compatible. Every API change to date has been 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. **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 | # 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. 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: By default, you see `live` mode. To switch, use the mode toggle to select `test` mode: 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: Secret keys start with `sk_`. Public keys start with `pk_`. **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. We recommend that you rotate your secret key for `live` mode at least once per year. Open the API keys page, then select the three-dot menu on the right side of the table. You can schedule the rotation or rotate the key immediately: # Permission roles Source: https://docs.fintoc.com/guides/home/dashboard/permission-roles Fintoc's dashboard contains sensitive information and lets your organization move money. Its permission system lets administrators control which information each user can view and which actions they can take. 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 an action that another team member started. Only transfers use this level, through a maker/checker flow. ## 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:** Every permission, including team management, billing, organization settings, and Internet Protocol (IP) restrictions. * **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. You cannot grant the Admin role from the dashboard. To assign it to a user, contact your Sales or Customer Success representative, or reach out through the 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 | ### Treasury No predefined role includes Treasury permissions; assign them to individual users. Transfers use a maker/checker flow. One user creates a transfer with the Manage level, and another approves or rejects it with the Authorize level. | Resource | Available access levels | | :------------------------------------------------- | :---------------------- | | Transfers | Read, Manage, Authorize | | Accounts | Read, Manage | | Standardized Mexican bank account numbers (CLABEs) | Read, Manage | | Entities | Read, Manage | ### Reconciliation This resource covers reconciliation: | Resource | Available access levels | | :------- | :---------------------- | | Links | Read, Manage | ### 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 management | Read, Manage | | Organization settings | Read, Manage | | Billing | Read, Manage | # 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 Accept and optimize online payments without writing code. Automate subscriptions and billing with automatic retries for failed charges. Initiate, receive, and reconcile money programmatically. Connect bank accounts to pull balances and movements. ## Start with a use case Embed the checkout widget and confirm payments via a webhook. Create a plan, save a payment method, and automate monthly billing. Move money through the Sistema de Pagos Electrónicos Interbancarios (SPEI), Transferencia Electrónica de Fondos (TEF), and standardized Mexican bank account numbers (CLABEs). Build retry flows with custom rules and notification logic. 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. ## 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) # Test your integration Source: https://docs.fintoc.com/guides/movements/data-aggregation-test-your-integration Use test credentials to try your integration. 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. ## 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 | **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**. # 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. **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: 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. # 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. ## 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 🇨🇱 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 ## 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 | # Fiscal product 🇨🇱 In Chile, the institution tasked with fiscal management is named **Servicio de Impuestos Internos (SII)**, and supports products for individuals as well as for companies | **Type** | **History** | **Products** | | :------------------------- | :---------- | :----------- | | Individual `cl_fiscal_sii` | 12 months | ✅ Invoices | **Make sure the linked account has the necessary permissions** In order to correctly update the movements in any of the mentioned types of accounts, make sure the credentials used to create the Link **have** all the permissions to review the balance and movements page, the historical statement, the provisional statement, the transfers statements and any other movement-related pages. **Foreign currency accounts refresh once a day** If you need your foreign currency accounts to refresh with the same frequency than the national currency accounts, contact our support team and specify which accounts need this behavior. # 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 **[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. **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**. ## 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. # 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. **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.checkoutSessions.create({ amount: 1000, currency: "CLP", payment_method_types: ["card"], recipient_account: { id: "acc_a1b2c3d4e5" }, // ...any other fields your flow requires }); res.json({ session_token: session.session_token }); }); ``` 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: *** ## 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`. 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. 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. | 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. 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 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: ## Optional: install the backend SDK 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 ``` 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": "11.111.111-1" }, "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: '11.111.111-1' }, 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': '11.111.111-1' }, '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", "updated_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": "11.111.111-1" } } } ``` | 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) **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) or `mx_rfc` for a Mexican tax ID (RFC). It also includes a `value` field that contains the tax identifier as a string.
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. | **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, echoing the `line_items` 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", "updated_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_data": { "currency": "CLP", "unit_amount": 350000, "product_data": { "name": "Annual subscription", "image_url": "https://merchant.com/images/annual-subscription.png" } } } ] } ``` ### 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": "11.111.111-1" }, "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: '11.111.111-1' }, 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': '11.111.111-1' }, '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`. | | `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", "updated_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": "11.111.111-1" } } } ``` **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. ### 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", "updated_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": "11.111.111-1" } } } ``` 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. **Client** ```javascript theme={null} window.location.assign(REDIRECT_URL_FROM_YOUR_BACKEND); ``` ## 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": "11.111.111-1" } }, "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": "11.111.111-1", "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 the payment's status. | | `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. | | `payment_intent.requires_action` | Sent when the payment related to a `Checkout Session` needs an action from the customer.
You receive this event when a `bank_transfer` payment from a business account requires approval from more than one representative. | Inform your customer of the action needed to approve the payment, based on the `next_action` field in the webhook event. | **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. In these cases, when you receive the `payment_intent.requires_action` event, inform the customer that the payment is pending approval. Once you receive either the `payment_intent.succeeded` or `payment_intent.failed` event, you should notify the customer of the final payment status as soon as it is confirmed. ## 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, "updated_at": "2026-03-16T19:41:17Z" } ``` 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", "card": null, "created_at": "2026-03-30T20:49:12Z", "customer": "cus_3B2bODrQFje7ZVkT69xyaTSDwXQ", "mode": "test", "metadata": {}, "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. | **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); ``` *** ### 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 recurring payments Source: https://docs.fintoc.com/guides/payments/accept-recurring-payments/index Enroll a customer into a fixed-amount recurring subscription with the Fintoc Checkout Session API, including how to handle billing cycles and webhooks. Build a subscription flow that enrolls a payment method and charges the customer automatically on a fixed schedule. To accept recurring payments with Fintoc, you complete three 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). 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 ## 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": "11.111.111-1" }, "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: '11.111.111-1' }, 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': '11.111.111-1', }, '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": "11.111.111-1" } }, "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`. | | `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), `direct_debit` (charges on bank accounts in 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) or `mx_rfc` for a Mexican tax ID (RFC), and `value` is the tax identifier as a string. 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 subscription. One of `CLP` or `MXN`. | | `unit_amount` | `integer` | **Required.** A positive integer representing the price per unit, 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). | | `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. | ## 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": "11.111.111-1" } }, "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. | Activate the subscription on your side based on the final status, and store the created ids (`subscription`, `payment_method`, `customer`). | | `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. | ## 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): `11.111.111-1` * 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 the Manage invoices section below. A successful charge emits `invoice.payment_succeeded`, `invoice.paid`, and `payment_intent.succeeded`. A failed charge emits `invoice.payment_failed` and `payment_intent.failed`. Test mode is not yet available for recurring payments in Mexico. ## Manage invoices When a subscription is created after a successful checkout enrollment, Fintoc automatically generates an `Invoice` for each billing cycle. An invoice represents the amount the customer owes for a given period. Fintoc attempts to collect payment for the invoice using the enrolled payment method. 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, the subscription becomes `active` and Fintoc creates the first invoice. From that point on, you should handle the following invoice-related events alongside the post-session events described above: | Event | Description | Action | | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `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.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. | **Month 1:** Right after the subscription is created, Fintoc generates the first invoice and attempts payment immediately. You'll receive `invoice.created`, followed by `invoice.finalized`, then `invoice.payment_succeeded`, `invoice.paid`, and `payment_intent.succeeded` on success. **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 attempts payment automatically. On success you receive `invoice.payment_succeeded` and `invoice.paid`. On failure, `invoice.payment_failed`. ### 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). 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. ### 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 Fintoc never charges on its own, `send_invoice` does not require a payment method. You can create the subscription with [Create a subscription](/api/payments-api/subscriptions/subscriptions-create) without sending your customer through a checkout enrollment. 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). ### Test invoice creation with status `draft` To test an invoice that is created 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 transitions to the next status. ## Update the payment method on a subscription 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 (user-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. Fintoc associates the payment method with the subscription 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 Call `POST /v2/subscriptions` and include `payment_method` along with `customer` and `line_items`. The payment method must belong to the customer and be active. **Server** ```bash theme={null} curl --request POST "https://api.fintoc.com/v2/subscriptions" \ --header "Authorization: YOUR_TEST_SECRET_API_KEY" \ --header "Content-Type: application/json" \ --data-raw '{ "customer": "cus_01234567", "line_items": [ { "price": "price_000000000001", "quantity": 1 } ], "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.create({ customer: 'cus_01234567', line_items: [ { price: 'price_000000000001', quantity: 1 } ], payment_method: 'pm_000000000001' }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') subscription = client.v2.subscriptions.create( customer='cus_01234567', line_items=[ { 'price': 'price_000000000001', 'quantity': 1, } ], payment_method='pm_000000000001', ) ``` Fintoc returns the created `Subscription` with the payment method already associated: ```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 } ``` ### 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. # 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 using the Fintoc Payment Intent API without another checkout. 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. Create charges against the saved payment method using the Payment Intent API. The following diagram shows how the setup flow works: *** ## 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": "11.111.111-1" }, "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: '11.111.111-1' }, 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': '11.111.111-1' }, '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": "11.111.111-1" } }, "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), `direct_debit` (Mexico), 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. | **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) or `mx_rfc` (Mexican tax ID, RFC), and `value` is the tax identifier as a string. 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": "11.111.111-1" } }, "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", "card": null, "created_at": "2021-10-15T15:22:11.474Z", "customer": "cus_NffrFeUfNV2Hib", "mode": "live", "metadata": {}, "pac": { "account_holder_id": "11.111.111-1", "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 you have a saved `payment_method`, charge it by creating a Payment Intent with the `payment_method` and `customer` IDs: **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", "customer": "cus_NffrFeUfNV2Hib", "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', customer: 'cus_NffrFeUfNV2Hib', 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', customer='cus_NffrFeUfNV2Hib', 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`. | | `customer` | `cus_NffrFeUfNV2Hib` | **Required.** ID of the `Customer` to charge. | | `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 Subscribe to the following events 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): `11.111.111-1` * 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 | 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. Test mode does not yet support saving a Payment Method in Mexico.
# 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`(only CLP for Installments Payments), `success_url`, `cancel_url` and `payment_methods: ["installments_payment"]`: ```bash theme={null} curl --request POST \ --url https://api.fintoc.com/v1/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_methods": ["installments_payment"] }' ``` ```javascript Node theme={null} const { Fintoc } = require('fintoc'); const fintoc = new Fintoc('YOUR_TEST_SECRET_API_KEY'); const checkoutSession = await fintoc.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_methods: ['installments_payment'] }); ``` ```python theme={null} from fintoc import Fintoc client = Fintoc('YOUR_TEST_SECRET_API_KEY') checkout_session = client.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_methods=['installments_payment'] ) ``` | 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` | A customer email linked to the Checkout Session.
**It is a required field** for a `installments_payment` method. | | `payment_methods` | `["installments_payment"]` | Payment methods available to the customer. `installments_payment` 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. | **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_methods": ["installments_payment"], "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 | | :------------- | :------------------------------------------------------------- | :----------------------------------------------------------------------------------- | | | Light button to use with the text "Paga en cuotas sin Tarjeta" | `` | | | Dark button to use with the text "Paga en cuotas sin Tarjeta" | `` | | | Light logos to use with the text + bank logos image | `` | | | Dark logos to use with the text + bank logos image | `` | | | Light text + bank logos to use with the logos | `` | | | Dark text + bank logos to use with the logos | `` | **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 by using the Payment Intent API. Customers pay by providing a reference (number or barcode) at any of the +13,000 locations available. Fintoc notifies you when the payment is completed. ## 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", "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', 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', 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. | | `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" } }, "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. | ### 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. Example of voucher based on the amount of the payment: If you want to show customized instructions to your customer, you can also use `barcode_url`, `reference_number` and images of the lists of locations: * [Complete list of locations](http://assets.fintoc.com/cash_assets/available_locations) * [List of locations for amount above 5,000.00 MXN](http://assets.fintoc.com/cash_assets/available_locations_without_amount_limit) We recommend prioritizing the barcode as the preferred method of presentation at the location, as it enables a faster payment process compared to dictating the reference number. **Maximum amount limit by location** Some locations only accept payments up to 5,000.00 MXN, while others have no maximum limit. You should display specific logos and a list of all locations based on the payment amount, as shown in the example voucher 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. ## 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* o *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} ``` **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 In case there are multiple payment options listed there are three options you can follow: #### Combination (Recommended) If you have more space available, we recommend supporting bank images with the full Fintoc logo. We provide you with a single image to reference for ease. Remember that the terminology should be *Paga con tu Banco*. | 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 | `` | | | Combination of text "Paga con tu banco" with light isotype and bank logos +12 | `` | | | Isotype and bank logos +12 | `` | | | Combination of text "Paga con tu banco" with light isotype and bank logos +16 | `` | | | 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. | 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 | `` | | | 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 | `` | ## Card payment button To ensure a good experience and understanding for your users, add the button to pay using credit or debit cards on your checkout using the images below depending on your configuration: | Image | Description | HTML | | -------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | | Horizontal logos to use with the text "Paga con tarjeta de Débito o Crédito" | `Fintoc and Card Brands Logos` | | | Vertical logos to use with the text "Paga con tarjeta de Débito o Crédito" | `Fintoc and Card Brands Logos` | Example of checkout button on light and dark modes following the guidelines: ## Other recommendations ### Pre-filling user's information Similar to preselecting your user's bank, if you have access to a user's payment information (like their RUT), you can pre-fill this information for users. This can either be editable or not. This is useful to avoid extra steps and to 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 Small errors will always be handled and mitigated by Fintoc within the widget but in the case that final state ones exist, you should react appropriately to each one in order to ensure a retrial of the process. Currently, failed payments include an error\_reason to indicate what caused the transaction to fail. You can check them out [here](/api/payments-api/payment-intents/payment-intent-error-reason). We highly recommend that for these you urge your user to retry the process with the proper modifications as well as indicate that no money was moved. ### 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 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, SPEI imagery, and terminology to present Fintoc bank transfer payments at your Mexican checkout, with ready-to-use asset URLs. ## Button guidelines **Accepted terminology:** *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI* **Supporting images:** SPEI logo To use our assets, you can directly use the URLs we provide, for example: ```html HTML theme={null} ``` **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. ## Button Use this if there are other buttons at the checkout. | | 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 | `` | ## Multiple payment options In case there are multiple payment options listed there are three options you can follow: ### Combination (recommended) If you have more space available, we recommend using the isotype with supporting bank images. We provide you with a single image to reference for ease. Remember that the terminology should be *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI*. Combo 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 are using the full logos of other brands, use the full Fintoc logo. The terminology should be *Paga con transferencia* or *Paga con SPEI* or *Paga con transferencia SPEI*. Logo Image | | Description | URL | | :---------------------------------------------------------------- | :------------- | :----------------------------------------------------------- | | ![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 you work with. We provide two URLs for you to embed within your website or app for this purpose. Leave the recommended safe space around our logo. | | 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 ## Other recommendations ## Pre-filling user's information If you have access to a user's payment information (like their telephone number), you can pre-fill this information for users, it will be editable by your user. This is useful to avoid 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 the customer to retry. See [Payment Intent Error Reason](/api/payments-api/payment-intents/payment-intent-error-reason) for the full list of reasons. Ask the customer to retry with the required changes. Tell the customer 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. # 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**. **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/v1/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": { "payment_intent": { "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. **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. **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. **Only available in Chile** Direct payments is only available in Chile. It's not available in Mexico yet. In direct payments, the money flows directly from your customer's bank account to the recipient account you specify. If you collect the money in a single bank account, you'll need to periodically download your bank statement, run a reconciliation process to track and match Fintoc payments and 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, while 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. # 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`. # Setup 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. **Direct payments availability** For now, direct payments is only available for Chile. ## 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/v1/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.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.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 will arrive directly in the bank account you specified. ## Available recipient banks Check our [Chile institution codes](/api/fintoc-api/chile-institution-codes) documentation to check the available 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. ## 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` | ## 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: # 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**. 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. 2. Use filters to search by order or transaction ID. 3. Click any transaction to view details and webhook logs. **You can issue refunds directly from Magento:** 1. Go to Sales → Fintoc → Refundable Orders, open the refund form, and submit. 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, create a new webhook. * Set the **URL** to `{STORE_URL}/fintoc/webhook` * Method `POST` 2. Copy the Webhook Secret and paste it into your Magento Fintoc settings (Stores → Configuration → Sales → Payment Methods → Fintoc → Basic Settings → Webhook Secret). 3. Test delivery in Fintoc and verify Magento responds with 200 OK.
### 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). **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 using Fintoc’s app in your Shopify store. This guide will walk you through the process of integrating Fintoc into your Shopify store. ## I. Install the Fintoc app on Shopify 1. Click on your country's link to begin: * 🇨🇱 [Fintoc App Chile](https://apps.shopify.com/fintoc) * 🇲🇽 [Fintoc App Mexico](https://apps.shopify.com/fintoc-mexico?locale=es) 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. **Chile:** * Business initiation certificate * RUT * Legal name and trade name * Address and district * Business activity * Bank account where you want to receive your payments **Mexico:** * Tax status certificate * Legal representative ID * Bank statement cover page * Company incorporation deed * RFC * Legal name and trade name * Tax address * 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. 🤘 ## FAQs If you have any questions, check out our [Shopify FAQ section](https://intercom.help/fintoc/es/articles/11825279-integracion-con-shopify). ## 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). 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. # VTEX Source: https://docs.fintoc.com/guides/payments/e-commerce-connectors/vtex Accept payments using Fintoc’s plugin in your VTEX store. This guide will help you integrate Fintoc's payment plugin into your VTEX store. With this plugin, you can effortlessly process payments, enabling your customers to complete their purchases without leaving your VTEX store. Follow these steps to begin accepting payments and boosting your sales in just a matter of minutes. # 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**. 4. Click on the "New Provider" button to add a new payment provider. 5. Look for **Fintoc** and choose it from the list. 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. 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**. **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 and card payments in Chilean pesos (CLP) and Mexican pesos (MXN). Set up Fintoc in your WooCommerce store to accept account-to-account **bank transfer** and **card** payments in **Chilean pesos (CLP)** and **Mexican pesos (MXN)** through Fintoc's hosted Checkout Session. 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). * 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 Download the latest plugin package from the [Fintoc for WooCommerce page](https://woocommerce.fintoc.com/), then install it: 1. Upload the `fintoc-for-woocommerce` folder to `/wp-content/plugins/`, or install the ZIP from **Plugins → Add New → Upload Plugin**. 2. Activate the plugin through the **Plugins** menu in WordPress. 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, for example, `Fintoc`. * **Description**: the text shown under the payment method at checkout. * **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, or both. Fintoc manages method enablement per organization. You cannot enable payment methods yourself. ### 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. ## Manage refunds You can issue full and partial refunds directly from the WooCommerce order screen. Open the order, click **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. 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. After testing each enabled payment method, disable **Test mode** so the gateway uses your `live` secret key. 2. 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 | ## 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. # 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/v1/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": { "payment_intent": { "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. **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 | Inform your client that if the payment succeeds, you will promptly refund their funds to their bank account within a reasonable timeframe. If you have Refunds integrated, you can request one automatically as soon as the payment transitions to a successful state. | | 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. **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)). # Fintoc collects Source: https://docs.fintoc.com/guides/payments/fintoc-collect-payments/index Learn how Fintoc collects payments on your behalf. 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 Set up your bank account to receive payouts. For you to receive funds, Fintoc makes payouts to your bank account. Payout availability can vary based on the country you’re operating in. Processing payouts happen 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 fees are calculated, take a look at 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. ### Updating your bank account information To update your account details, reach out to your Account Executive. ## 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. **Payout schedule time zones** All payments and payouts are processed according to local time zone. ### Chile 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, we support 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 By default, every time Fintoc makes a payout to your bank account, an email is sent to you with the [payout reconciliation report](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation#the-payout-reconciliation-report) for that batch. See the [reporting and reconciliation guide](/guides/payments/fintoc-collect-payments/payment-initiation-reporting-and-reconciliation) to learn more. ## Using the Dashboard You can see all past and future payouts from your [dashboard](https://dashboard.fintoc.com) by clicking on the Payouts tab located on the left side of the screen. ## 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 is canceled and will not be sent to your bank account. | # 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 payment. 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. **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**. # 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. # Issue refunds You can issue refunds from the [Dashboard](https://dashboard.fintoc.com) or by using the [Refunds API](/api/payments-api/refunds). Treat the refund as complete after it reaches the `succeeded` status. You can issue more than one refund against a payment, but you can't refund a total greater than the original payment amount. ## 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 }' ``` # 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. ## 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 treating the refund as complete. | | `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 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 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. ## 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 | **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. By default, every time Fintoc makes a payout to your bank account an email is sent to you with the payout reconciliation report for that batch. To see other available 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 semicolon-delimited CSV file in which the first row is column headers. The filename is `yyyy-mm-dd-fintoc-payout-.csv`. For example, if your `orgname` is "My Company" the filename will be `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` | The transaction's creation date, in ISO 8601 format. | | 3 | `amount` | `integer` | Gross amount of the transaction, in cents. In the case of refunds, this value will be displayed as negative unless a refund fails, in which case it will be shown as positive. | | 4 | `fee` | `integer` | Fees (in cents) paid for this transaction. If your account is configured to receive the payout full amount, then the `fee` is always `0`. | | 5 | `net_amount` | `integer` | Net amount of the transaction, in cents. | | 6 | `currency` | `string` | Transaction [currency ISO code](https://www.iso.org/iso-4217-currency-codes.html) | | 7 | `payout_holder_id` | `string` | Identifier of the owner of the bank account the payout was sent to. In Chile, it is a RUT and in Mexico it is an 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` | Whether the transaction is a `payment_intent`, a `charge` or a `refund`. | | 11 | `metadata` | `string` | A JSON string of the transaction [metadata](/api/fintoc-api/metadata). | #### Sample For an example of the included data and structure, [download a sample of the payout reconciliation report](https://drive.google.com/file/d/1HtGC06Ww51P-HqTSaNXi8Tti1-RBi1NA/view?usp=drive_link). ### 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). ## 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. For email and subject configuration, 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**. ## 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. *** **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, navigate to the API Keys tab. Make sure you are in Live mode by checking the toggle indicator in the bottom-left corner. Generate your Live Secret Key and set it up in your back end to make requests to the API in Live Mode **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.
* [ ] **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 has important effects on 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. # Overview Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/index 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). # Countries and institutions Source: https://docs.fintoc.com/guides/payments/overview-payment-initiation/payment-initiation-countries-and-institutions 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 con Cuenta (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 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-collect-payments/payment-initiation-receiving-payouts#billing) 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 **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 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 ``` 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`. **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", "updated_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. # 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. | **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 payments to test your integration. 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 For bank transfer payments, in test mode you use distinct test credential to simulate the payment flow and error types for each Multi-Factor Authentication (MFA) type: ### Available MFA types These are the different MFA that we have 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, the user must authorize the transaction from their *smartphone*. Fintoc detects that the transaction was authorized automatically. * **SMS**: the bank sends a code (generally a numeric code) to the user's phone so that it can be used to authorize the transaction. * **Coordinate card**: card that banks give their clients with a table with numbers. The user must insert the numbers located at the coordinates asked by the bank. You can read more about coordinate cards [here](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 with Fintoc test mode you can test every authorization flow that your user might follow. ### Chile 🇨🇱 In Chile, a payment has between two to three steps depending on the bank: 1. The user logs in to their bank account. 2. In some banks and specific cases, the user needs to authorize a new contact before authorizing the payment. 3. The user 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 The user might need to add the recipient's account before confirming the transaction. If you want the widget to ask for some kind of MFA that simulates that the user needs to add the recipient account of the Checkout Session as a new contact, you should **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`, the user will be asked to authorize the new contact using its **Security device**. You can see the list of specific digit combinations indicating what type of MFA corresponds to which last digits of the amount and which code to introduce. Introducing a different code will result in a failure of 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, the user won't be required to complete MFA to create a new contact and will go directly to confirm the bank transfer. #### MFA to confirm operation To choose which authorization method to use while in test mode to confirm the payment, you need to select a specific origin bank account number during the payment flow. The test mode environment will **always** show the same accounts. Here's a list of the test mode bank account numbers and which type of MFA corresponds to all of them, 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 allows you to 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` | #### Simulate Alternative Payment Methods You can test the payment flow for Alternative Payment Methods for bank transfers in Chile following the steps at the specific [guide](/guides/payments/alternative-payment-methods/alternative-payment-method-test-your-integration). The available methods are: * Banco Estado (Botón Compraquí) * Banco de Chile (Botón Banco de Chile) * Banco Santander (Botón Santander) * Mach ### Mexico 🇲🇽 In Mexico, a payment has only two steps: 1. The user enters their phone number to initiate the payment. 2. The user authorizes the payment in their bank mobile application. To simulate a successful or failed payment, you can use one of the following cellphone numbers when the widget asks you 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, you can use one of the following card credentials during the payment process: | 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 | ## Test webhooks To test webhooks, you have to perform actions in test mode that send legitimate events to your endpoint. For instance, to trigger the `checkout_session.finished` event, you can use a test account that produces a successful payment. ## Test refunds Using test mode you can simulate successful and failed refunds. The only difference with live mode is that in live mode refunds take 1 to 2 business days to process, while in test mode, depending on the refund amount, refunds are processed almost immediately. You can use the refund amount to simulate a successful or failed refund. You can simulate a total refund creating 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). | **Refund webhooks** In test mode you receive the same webhooks as you would receive 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" } }' ```
**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. | | `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", "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" }, "business_profile": { "name":"Merchant Name", "category": "009613", "tax_id": "222222222" } } ``` ## 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). In the case of payment links, we recommend you to only listen for `payment_intent.succeeded` events. You can also see successful payments using our [Dashboard](https://dashboard.fintoc.com/). ## Cancel a Payment Link You can 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, Transfers, 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 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 Let your AI agents interact with the Fintoc API through our MCP server. 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 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. **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**. You can enable MCP servers on ChatGPT with a Pro, Plus, Business, Enterprise, or Education account. Follow the OpenAI documentation 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. Add the following to your `~/.cursor/mcp.json` file. For configuration options, see the Cursor documentation. ```json theme={null} { "mcpServers": { "fintoc": { "url": "https://mcp.fintoc.com" } } } ``` Add the following to your `~/.vscode/mcp.json`. For configuration options, see the VS Code documentation. ```json theme={null} { "servers": { "fintoc": { "type": "http", "url": "https://mcp.fintoc.com" } } } ``` Run the following command: ```bash theme={null} claude mcp add --transport http fintoc https://mcp.fintoc.com ``` 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.** ## 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, email Fintoc's team at [mcp@fintoc.com](mailto:mcp@fintoc.com). The server exposes the following [MCP tools](https://modelcontextprotocol.io/docs/concepts/tools): | Resource | Tool | Required permission | API | | ---------------- | ------------------------- | :------------------------------ | ---------------------------------------------------------------------------------------- | | Account | `list_accounts` | `account:view` | [List accounts](/api/transfers-api/transfers-accounts/transfers-accounts-list) | | Account | `list_account_statements` | `account:view` | [List account statements](/api/transfers-api/account-statements/account-statements-list) | | Account Number | `list_account_numbers` | `account_number:view` | [List account numbers](/api/transfers-api/account-numbers/account-numbers-list) | | Account Number | `create_account_number` | `account_number:manage` | [Create an account number](/api/transfers-api/account-numbers/account-numbers-create) | | Bank Account | `list_movements_accounts` | `movement:view` | [List a link's accounts](/api/movements-api/accounts/accounts-list) | | Checkout Session | `list_checkout_sessions` | `payment:view` | [List checkout sessions](/api/payments-api/checkout-sessions/checkout-sessions-list) | | Customer | `list_customers` | `customer:view` | [List customers](/api/payments-api/customers/customers-list) | | Customer | `create_customer` | `customer:manage` | [Create a customer](/api/payments-api/customers/customers-create) | | Entity | `list_entities` | `entity:view` | [List entities](/api/transfers-api/entities/entities-list) | | Invoice | `list_invoices` | `billing:view` | [List invoices](/api/payments-api/invoices/invoices-list) | | Invoice | `create_invoice` | `invoicing_invoice:manage` | [Create an invoice](/api/payments-api/invoices/invoices-create) | | Invoice | `finalize_invoice` | `invoicing_invoice:manage` | [Finalize an invoice](/api/payments-api/invoices/invoices-finalize) | | Invoice | `void_invoice` | `invoicing_invoice:manage` | [Void an invoice](/api/payments-api/invoices/invoices-void) | | Link | `list_links` | `link:view` | [List links](/api/movements-api/links/links-list) | | Movement | `list_movements` | `movement:view` | [List movements](/api/movements-api/movements/movements-list) | | Payment Intent | `list_payment_intents` | `payment:view` | [List payment intents](/api/payments-api/payment-intents/payment-intents-list) | | Payment Method | `list_payment_methods` | `customer:view` | [List payment methods](/api/payments-api/payment-methods/payment-methods-list) | | Payout | `list_payouts` | `payout:view` | [List payouts](/api/payments-api/payouts/payouts-list) | | Payout | `list_payout_resources` | `payout:view` | | | Refund | `list_refunds` | `refund:view` | [List refunds](/api/payments-api/refunds/refunds-list) | | Refund | `create_refund` | `refund:manage` | [Create a refund](/api/payments-api/refunds/refunds-create) | | Refund | `cancel_refund` | `refund:manage` | [Cancel a refund](/api/payments-api/refunds/refunds-cancel) | | Subscription | `list_subscriptions` | `invoicing_subscription:view` | [List subscriptions](/api/payments-api/subscriptions/subscriptions-list) | | Subscription | `create_subscription` | `invoicing_subscription:manage` | [Create a subscription](/api/payments-api/subscriptions/subscriptions-create) | | Subscription | `update_subscription` | `invoicing_subscription:manage` | [Update a subscription](/api/payments-api/subscriptions/subscriptions-update) | | Transfer | `list_transfers` | `transfer:view` | [List transfers](/api/transfers-api/transfers/transfers-list) | | Webhook Endpoint | `list_webhook_endpoints` | `webhook_endpoint:view` | [List webhook endpoints](/api/main-resources/webhook-endpoints/webhook-endpoints-list) | An empty API column means the tool has no equivalent API reference endpoint. **Other tools** * `fetch_resource`: Looks up any Fintoc resource by its `id`. * `submit_feedback`: Reports a blocker or unexpected behavior to the Fintoc team. **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). 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. Add the following to your `~/.cursor/mcp.json` file. For configuration options, see the Cursor documentation. ```json theme={null} { "mcpServers": { "fintoc-docs": { "url": "https://docs.fintoc.com/mcp" } } } ``` Add the following to your `~/.vscode/mcp.json`. For configuration options, see the VS Code documentation. ```json theme={null} { "servers": { "fintoc-docs": { "type": "http", "url": "https://docs.fintoc.com/mcp" } } } ``` Run the following command: ```bash theme={null} claude mcp add --transport http fintoc-docs https://docs.fintoc.com/mcp ``` You can enable MCP servers on ChatGPT with a Pro, Plus, Business, Enterprise, or Education account. Follow the OpenAI documentation 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. 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. Install the CLI on macOS or Linux. Manage API keys and switch between them. 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" } ] ``` `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/transfers/transfers-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. ## 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 Libraries and tools for interacting with your Fintoc integration. 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 fintoc-python fintoc-node fintoc-ruby ### Frontend SDKs fintoc-js 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. sergiocampama/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/). **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. 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. ## Select your bank account Zapier displays every bank account associated with the `Link`. Select the account you want to connect and continue. ## 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. # 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 [Transfers](/guides/transfers/transfers-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 Source: https://docs.fintoc.com/guides/resources/webhooks-walkthrough/index 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. 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 [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. **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. ## 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. # 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 [Avoid event duplication](/guides/resources/webhooks-walkthrough/webhooks-good-practices#avoid-event-duplication). ### 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 Implement these best practices when using webhooks. This page covers practices that keep your webhook endpoint secure and your Fintoc integration reliable. You learn how to filter events, handle duplicate deliveries, 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. ## 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 ``` # 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. **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. **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. 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). 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} ``` **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()`. | **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. **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({ holderType, product, publicKey, webhookUrl, country, institutionId, linkToken, onSuccess, onExit, onEvent, }); ``` ### 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. Only `subscriptions` uses this parameter. | | `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. | **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. **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, }; ``` **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 Integrate the Fintoc Widget as a WebView in your mobile application. 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. **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 `subscriptions` product. | | `link_token` | `string` | Identifier of an existing `Link`. Include it to configure the Widget for a `Link` already created with the `movements` product. | 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&link_token=YOUR_LINK_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). | **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) } } ``` **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. | 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. | # Entity Source: https://docs.fintoc.com/guides/transfers/entities/entity-data-model Understand the `Entity` object in Fintoc's Transfers API: your root `Entity`, customer `Entity` objects, and when a Know Your Customer review applies. An `Entity` represents an organization with its own legal identity. An `Entity` is the parent of its `Account` objects. Each `Entity` can own more than one `Account`. ## 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 customers You can create `Entity` objects for customers when transfer receipts need to show each customer's legal name. For example, a marketplace can pay each seller under the seller's Mexican tax ID (RFC) or Chilean tax ID (RUT). Fintoc's compliance team performs a Know Your Customer review for each customer `Entity`. For Mexican entities, you can create the `Entity` and complete the review through the API. See [Onboard an Entity by API](/guides/transfers/entities/onboard-an-entity-by-api) for instructions. See [Create more accounts](/guides/transfers/manage-accounts/creating-more-accounts) for the dashboard flow. # Entities Source: https://docs.fintoc.com/guides/transfers/entities/index Learn the Entity data model in Fintoc's Transfers API and onboard a Mexican client Entity through the API to hold Account objects on your platform. An `Entity` is the legal account holder that owns `Account` objects. Your organization always has a root `Entity`. Platforms that hold balances for clients create one `Entity` per client. This section explains what an `Entity` represents and how to onboard one: * [The Entity data model](/guides/transfers/entities/entity-data-model): learn what an `Entity` represents, how the root `Entity` differs from a client `Entity`, and when a compliance review applies. * [Onboard an entity by API](/guides/transfers/entities/onboard-an-entity-by-api): create a Mexican `Entity` for your client and complete its compliance review through the API. To create `Account` objects under an `Entity` that is already approved, see [Create more accounts](/guides/transfers/manage-accounts/creating-more-accounts). # Onboard an entity by API Source: https://docs.fintoc.com/guides/transfers/entities/onboard-an-entity-by-api Create an Entity for your client and complete its Know Your Customer review through the Fintoc API without using the dashboard, for platforms and marketplaces. 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/transfers/manage-accounts/creating-more-accounts) instead. **Availability** Onboarding by API supports Mexican `Entity` objects. For entities outside Mexico, create the `Entity` from the dashboard. **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[Create accounts] F -->|entity.onboarding.rejected| B ``` ## 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. ## Step 1: Create the entity An `Entity` is the legal account holder. Create one for your client with their legal name and Mexican tax ID (RFC). Set `country_code` to `mx`, and set `holder_id` to the client's RFC. ```bash 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" } ``` Save the `Entity` ID (`ent_...`); every onboarding call uses this value. See [The Entity object](/api/transfers-api/entities/entity-object) for the full attribute list. ## Step 2: Create the onboarding The `Onboarding` holds the Know Your Customer review for one `Entity`. The review includes company information, the legal representatives, the transactional profile, and the shareholders. Create one onboarding per `Entity` and pass the structured data in the request. 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`. ```bash 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 ' { "company_information": { "business_activity": "Servicios financieros", "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_500000", "monthly_operations_range": "1_15000" }, "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", "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" } ] } ``` A block labeled `Response (abridged)` shows only the fields that the step changes, not the whole object. The response above also returns `data`, which echoes the company information and transactional profile you sent. Each legal representative and shareholder also carries the identity fields from the request. See [The Onboarding object](/api/transfers-api/onboardings/onboarding-object) for the full shape. Four details to note in the response: * `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. * Each legal representative has its own `documents` array with two slots. * Each shareholder has a single `document` slot. A `legal_entity` shareholder can include nested `children`. Every 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. Steps 3, 4, and 5 fill them. 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). See [The Onboarding object](/api/transfers-api/onboardings/onboarding-object) for every field. ## Step 3: Upload the company documents Upload one file to each company document slot in the `documents` array. Send the file as `multipart/form-data` in the `file` field. The maximum file size is 20 MB. Uploading to a slot that already has a file replaces the existing file. 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 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": [ { "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`. ## 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 `identification` slot accepts `application/pdf`, `image/jpeg`, and `image/png`. The `power_of_attorney` slot accepts `application/pdf` only. ```bash 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 `power_of_attorney` slot, and for every other legal representative you declared. ## Step 5: Upload each shareholder's document 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 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 can no longer be modified. ```bash 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", "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" } } ``` ## 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. Create a new onboarding to retry. | Subscribe to these events in the dashboard under **Developers → Webhooks**, or poll the onboarding directly: ```bash 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", "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: Create accounts once approved After the `Entity` is approved, create one or more `Account` objects under the `Entity`. 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/transfers/manage-accounts/creating-more-accounts) for account creation details. ```bash 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_8anBwgZktbZH6ydyHa6Tm0eM", "object": "account", "mode": "test", "description": "Client settlement account", "root_account_number": "000000000000000000", "root_account_number_id": "acno_0ujsswThIGTUYm2K8FjOOfXtY1K", "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 slot, and submit the onboarding. Confirm that `submittable` turns `true` only after every 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. ### 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 the `business_activity` value you sent in `company_information`. This mechanism works like a test card number: a magic value forces a specific outcome. Three cases drive the simulated review: | `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. 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 theme={null} { "id": "evt_2xK9mP4nQrStUvWxYz1234567", "object": "event", "type": "entity.onboarding.approved", "mode": "test", "created_at": "2026-01-16T09:00:00.000Z", "data": { "object_name": "onboarding_process", "id": "onbprc_0ujsswThIGTUYm2K8FjOOfXtY1K", "entity": { "id": "ent_2daFu0zqqDtZGJaSi2TGI2Mm1nN", "holder_id": "AAA010101AAA", "holder_name": "Test Entity 1", "nationality": "mx" }, "status": "approved", "submitted_at": "2026-01-15T15:00:00Z", "reviewed_at": "2026-01-16T09:00:00Z" } } ``` The webhook payload names the resource `onboarding_process` in `object_name`, which is the same object the API returns with `"object": "onboarding"`. The rejected event carries the same payload with `"type": "entity.onboarding.rejected"` and `"status": "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 * [Create more accounts](/guides/transfers/manage-accounts/creating-more-accounts) for an approved `Entity`. * Review [The Onboarding object](/api/transfers-api/onboardings/onboarding-object) and [the onboarding endpoints](/api/transfers-api/onboardings/entities-onboardings-create) in the API reference. # Add logic to Account Numbers Source: https://docs.fintoc.com/guides/transfers/inbound-transfers/add-logic-to-clabes Restrict which inbound transfers a Fintoc Account Number accepts by setting per-account rules such as expected amount, sender name, or acceptance status. In Mexico, a Fintoc Account Number uses the standardized Mexican bank account number (CLABE) format. You can 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 set minimum and maximum amount limits. These controls let Fintoc reject unwanted inbound transfers. ## 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 ```bash 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 theme={null} const accountNumber = await fintoc.v2.accountNumbers.update( "acno_test_a1b2c3d4e5f6", { status: "disabled" } ); ``` ```python theme={null} account_number = client.v2.account_numbers.update( "acno_test_a1b2c3d4e5f6", status="disabled" ) ``` The API returns the updated Account Number with its `status` set to `disabled`: ```json 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 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 ```bash 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 theme={null} const accountNumber = await fintoc.v2.accountNumbers.create({ account_id: "acc_test_b2c3d4e5f6g7", options: { min_amount: 30000, max_amount: 40000, }, }); ``` ```python theme={null} account_number = client.v2.account_numbers.create( account_id="acc_test_b2c3d4e5f6g7", options={ "min_amount": 30000, "max_amount": 40000, }, ) ``` The API returns the new Account Number with the amount limits under `options`: ```json 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/transfers-api/simulation/transfers-simulate-receive) endpoint to simulate inbound transfers in `test` mode. # Receive transfers Source: https://docs.fintoc.com/guides/transfers/inbound-transfers/index Receive real-time inbound transfers with Fintoc Account Numbers to automatically track and reconcile incoming payments against orders, invoices, or users. ## Inbound transfers in Mexico Complete the [transfers setup guide](/guides/transfers/transfers-setup) first. Then follow these steps to receive inbound transfers: 1. Use your secret key to create an `account_number`. This account number is a standardized Mexican bank account number (CLABE) used on the Sistema de Pagos Electrónicos Interbancarios (SPEI) rail. 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.
### Step 1: Create an account number (CLABE) An `AccountNumber` represents a CLABE. 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/transfers/transfers-overview/v2-transfers-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 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"} ) ``` The API returns the following response: ```json 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" } } ```
### 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. The `transfer.inbound.succeeded` event looks like this: ```json 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", "type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } }, "created_at": "2020-04-22T21:10:19.254Z", "mode": "test" } ``` ### 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 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", "type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } } ``` 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/transfers/transfers-setup/test-your-integration). ## Inbound transfers in Chile Complete the [transfers setup guide](/guides/transfers/transfers-setup) first. Then follow these steps to receive inbound transfers: 1. Identify your account and its `root_account_number`, which receives the transfer. See the [account data model](/guides/transfers/transfers-overview/v2-transfers-account-number-data-model) to learn how Fintoc provisions this account number. 2. Create a webhook endpoint to handle inbound transfer events. 3. Receive a transfer at your account and handle the webhook notification. The following diagram shows how Fintoc interacts with you and the counterparty that sends the inbound transfer. ### Step 1: Identify your account Each Chilean account has a `root_account_number` that receives inbound transfers. This value appears as `account_number` in the `transfer.inbound.succeeded` payload below. See the [account data model](/guides/transfers/transfers-overview/v2-transfers-account-number-data-model) to learn how Fintoc provisions this account number. ### 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. The `transfer.inbound.succeeded` event looks like this: ```json 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": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "11111111-1", "holder_name": "Test Customer 1", "account_number": "000000000", "type": "checking_account", "code": "01", "institution": { "id": "cl_banco_santander", "name": "Banco Santander", "country": "cl" } } }, "created_at": "2020-04-22T21:10:19.254Z", "mode": "test" } ``` ### Step 3: Receive a transfer at your account After you identify your account and its `root_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 your account's `account_number_id`. Also pass an `amount` in the smallest currency unit and an uppercase ISO 4217 `currency` code: ```bash 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=CLP ``` ```javascript Node theme={null} const transfer = await fintoc.v2.simulate.receiveTransfer({ account_number_id: 'acno_Kasf91034gj1AD', amount: 2864, currency: 'CLP', }); ``` ```python Python theme={null} transfer = client.v2.simulate.receive_transfer( account_number_id="acno_Kasf91034gj1AD", amount=2864, currency="CLP", ) ``` ```json Response theme={null} { "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": "111111111111111111", "created_at": "2024-03-01T20:09:42.949787176Z", "mode": "test", "metadata": { "id_cliente": "12343212" } }, "counterparty": { "holder_id": "11111111-1", "holder_name": "Test Customer 1", "account_number": "000000000", "type": "checking_account", "code": "01", "institution": { "id": "cl_banco_santander", "name": "Banco Santander", "country": "cl" } } } ``` 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/transfers/transfers-setup/test-your-integration). # Manage your Account Numbers Source: https://docs.fintoc.com/guides/transfers/inbound-transfers/manage-your-clabes Identify and delete inactive Fintoc Account Numbers so your organization keeps room in its quota as your integration grows in Mexico and other markets. 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 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 theme={null} const accountNumbers = await fintoc.v2.accountNumbers.list({ no_transfers_since: "2025-12-01", }); ``` ```python theme={null} account_numbers = client.v2.account_numbers.list( no_transfers_since="2025-12-01" ) ``` ```json theme={null} { "data": [ { "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 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 theme={null} await fintoc.v2.accountNumbers.delete("acno_test_a1b2c3d4e5f6"); ``` ```python theme={null} client.v2.account_numbers.delete("acno_test_a1b2c3d4e5f6") ``` ```json 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. This behavior applies to Mexico's Sistema de Pagos Electrónicos Interbancarios (SPEI) rail and Chile's Transferencia Electrónica de Fondos (TEF) 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/transfers/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/transfers/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 Transfers API and webhook events. **Only available in Mexico** 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/transfers-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.
## Trigger the return Call the [return transfer endpoint](/api/transfers-api/transfers/transfers-return) with the `transfer_id` and [`Fintoc-JWS-Signature`](/guides/transfers/transfers-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.returnTransfer({ transfer_id: "tr_2wlt3xRBaEstTGPezqIGXy6JUU8", }); ``` ```python Python theme={null} transfer = client.v2.transfers.return_transfer( 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", "type": "clabe", "institution": { "id": "40012", "name": "BBVA Mexico", "country": "mx" } } } ``` After a successful request, the API returns a transfer with `status` set to `return_pending`. After Fintoc processes the return, `status` changes to `returned`. ## 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. 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/transfers/transfers-setup/test-your-integration) for the steps to simulate both scenarios. # Get account statements Source: https://docs.fintoc.com/guides/transfers/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/transfers-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 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 SDK theme={null} const statements = await client.v2.accounts.accountStatements.list({ account_id: "acc_3AOIA4Hz09oHLeksYr9pYpBk3NS", since: "2026-03-01", until: "2026-03-31", }); ``` ```python Python SDK 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", "period": "2026-03", "since": "2026-03-01", "until": "2026-03-31", "download_url": "https://files.fintoc.com/account_statements/acst_8sFkj2mNpQ4rTvWx6yZ1bC3d.pdf?signature=000000000000", "created_at": "2026-04-01T00:00:00Z" } ] ``` ## 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: ## 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/transfers/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. ## Account activation Activation depends on which entity owns the account: * For your main entity, accounts activate immediately. * For a new entity, accounts stay in `pending` until Fintoc completes business verification. Verification takes up to 5 business days. ## 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/transfers-api/transfers-accounts/transfers-accounts-create) endpoint with your main entity's `entity_id`. To retrieve the `entity_id`, call the [List entities](/api/transfers-api/entities/entities-list) endpoint. You can also create the account from the [Dashboard](https://dashboard.fintoc.com/accounts). ```bash 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 SDK theme={null} const account = await fintoc.v2.accounts.create({ entity_id: "ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", description: "My main account" }); ``` ```python Python SDK theme={null} account = client.v2.accounts.create( entity_id="ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", description="My main account", ) ``` ```json Response theme={null} { "id": "acc_32ExjlGaPrvG2AiNSU2lAmNiXL8", "object": "account", "entity_id": "ent_32ExjlGaPrvG2AiNSU2lAmNiXL8", "description": "My main account", "status": "active", "balance": 0, "currency": "MXN" } ``` ## Create accounts for another entity (your clients) 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 Mexican tax ID (RFC). ### 2. Complete business verification Complete the business verification form for your new entity in the Dashboard. Fintoc's compliance team reviews your information within 5 business days and confirms when the entity is ready to use. ### 3. Start using Transfers After Fintoc completes business verification, you can: * Create `Transfer` objects from your new entity's main `Account`. * Receive transfers at your main account number or generate new 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/transfers-api/transfers-accounts/transfers-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/transfers/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 account. The pages in this section explain both tasks. # Batch transfers Source: https://docs.fintoc.com/guides/transfers/outbound-transfers/batch-transfers Load, authorize, and execute multiple transfers at once. Batch transfers are available only in the Fintoc Dashboard. ## Overview This page explains how to create, authorize, and track up to 5,000 transfers from one file in the Fintoc Dashboard. 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 country-specific template: * 🇨🇱 [Template Chile (CLP)](https://docs.google.com/spreadsheets/d/1Ngcl07HLR2LmQ97SERhL6qn4LddwGe1rbBE5oQpGGFA/edit?usp=sharing) * 🇲🇽 [Template Mexico (MXN)](https://docs.google.com/spreadsheets/d/12jCDW2K69eeZ-Rk-l6c4PQf7eVYKBID-9hBjIeoZPts/edit?usp=sharing) ### 2. Fill out the template Use these fields for each transfer row: | Field | Description | 🇨🇱 Required | 🇲🇽 Required | Notes | | ----------------------------- | -------------------------------------------------------------------------- | ------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `sender_account_number` | Account number that sends the money. | ✅ | ✅ | | | `counterparty_holder_id` | Destination account holder's Chilean tax ID (RUT) or Mexican tax ID (RFC). | ✅ | ❌ | | | `counterparty_name` | Destination account holder's name. | ❌ | ❌ | | | `counterparty_institution_id` | Institution that holds the destination account. | ✅ | ❌ / ✅ | 🇲🇽 Required if you do not provide a standardized Mexican bank account number (CLABE). Use a 5-digit code from [this list](https://www.banxico.org.mx/cep-scl/listaInstituciones.do).
🇨🇱 Use a code such as `cl_banco_bbva` from [this list](/api/fintoc-api/chile-institution-codes). | | `counterparty_account_number` | Destination account number. | ✅ | ✅ | CLABE for Mexico or account number for Chile. | | `amount` | Amount sent to the destination account. | ✅ | ✅ | CLP as an integer or MXN as a decimal with `.`. | | `comment` | Free-text note attached to the transfer. | ❌ | ❌ | Up to 40 characters. | | `reference_id` | Numeric reference. | ❌ | ❌ | Up to 7 digits. | | `meta/...` | Custom metadata columns. | ❌ | ❌ | You can add up to 50 metadata columns. For example, `meta/user_name` creates the custom column `user_name`. | In Chile, Fintoc splits any row with an amount over 7,000,000 CLP into multiple independent transfers. ### 3. Upload your file When you upload the file: * Fintoc supports **CSV** files. * Fintoc shows validation messages when it finds errors. If you see an error, correct your file and upload it again. Warnings, such as duplicate rows, do not block the upload. ### 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. Choose 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. ## 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. |
# Send transfers Source: https://docs.fintoc.com/guides/transfers/outbound-transfers/index Send real-time outbound transfers over SPEI in Mexico or TEF in Chile with Fintoc's Transfers API, and track each status change through webhook events. Complete the setup guide and these steps to send outbound transfers with Fintoc's Transfers API: 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. ## Step 1: Configure JWS signing keys and generate a JWS signature Every request to a Fintoc Transfers 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/transfers/transfers-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. ## 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`. ```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"} ) ``` A successful request returns this response: ```json 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, "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" } } ``` **Currencies are represented as integers** For example, Fintoc represents **MXN \$10.29** as `1029`. See [Currencies](/guides/home/currencies) for details. **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`. ```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"} ) ``` A successful request returns this response: ```json 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, "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). | ## Step 4: Monitor transfer status ### Transfer status flow A transfer's status is one of `pending`, `succeeded`, `failed`, `returned`, `return_pending`, or `rejected`. For more details on transfer statuses, see the [Transfers data model](/guides/transfers/transfers-overview/v2-transfers-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. We recommend handling the following events: | Event | Description | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `transfer.outbound.succeeded` | Sent when the transfer settles successfully. | | `transfer.outbound.rejected` | Sent when Banco de México or the recipient institution rejects a transfer in Mexico, or when the recipient institution rejects the transfer in Chile. See the [rejection causes](/api/transfers-api/transfers/spei-codes); `rejected` is a final status. | | `transfer.outbound.failed` | Sent when the transfer cannot reach the destination account because an error occurs during processing. | **Webhooks may arrive out of order** For example, a `transfer.outbound.rejected` event can arrive before the same transfer's `transfer.outbound.succeeded` event. The transfer still succeeded before it was rejected. ## 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 three terminal statuses to confirm your webhook handling: | Outcome | Resulting status | Webhook event | | :-------- | :--------------- | :---------------------------- | | Succeeded | `succeeded` | `transfer.outbound.succeeded` | | Rejected | `rejected` | `transfer.outbound.rejected` | | Failed | `failed` | `transfer.outbound.failed` | # Verify CLABEs Source: https://docs.fintoc.com/guides/transfers/outbound-transfers/verify-clabes Verify a Mexican CLABE and its account holder's name before sending a full payout with Fintoc's Transfers API, to avoid rejections and misdirected funds. Account verification confirms a Mexican bank account identified by its standardized Mexican bank account number (CLABE). Fintoc sends a 0.01 MXN micro-deposit from your account balance to the target CLABE. 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/transfers/transfers-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 } ``` ## 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": { "account_verification_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). # Transfers overview Source: https://docs.fintoc.com/guides/transfers/transfers-overview/index Use Fintoc's Transfers API to receive, send, and reconcile bank transfers in Chile and Mexico with `Entity`, `Account`, and `Transfer` objects. Cuentas de Pago con Fondos (CPF) in Chile (private preview) Fintoc CPF accounts let you receive, reconcile, and make transfers in Chile. CPF accounts are in private preview. To request access, contact your Fintoc sales representative. The Transfers 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 [Transfers API reference](/api/transfers-api/transfers/transfer-object). With the Transfers API, you can: * **Create accounts** and assign them to your orders or customers to reconcile inbound transfers against a known account. * **Receive** bank transfers and reconcile them using a unique standardized Mexican bank account number (CLABE) or the sender's details in Chile. * **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 (SPEI) in Mexico and Transferencia Electrónica de Fondos (TEF) in Chile. ## How it fits together A minimal integration has four objects: * **[`Entity`](/guides/transfers/entities)**: 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. Each `Account` can have more than one Account Number. * **`Transfer`**: a single money movement, inbound or outbound. ## Availability by country Transfers API capabilities vary by country: | Capability | Mexico 🇲🇽 | Chile 🇨🇱 | | :-------------------------- | :---------- | :-------------- | | Inbound transfers | ✅ | ✅ | | Outbound transfers | ✅ | ✅ | | Accounts | ✅ | Private preview | | Account Numbers | ✅ (CLABE) | Private preview | | Transfer returns | ✅ | Private preview | | Account Number verification | ✅ (CLABE) | Private preview | # Movements Source: https://docs.fintoc.com/guides/transfers/transfers-overview/movement 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/transfers-api/transfers-movements/transfers-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 Transfers `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/transfers-api/transfers-movements/transfers-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. # Account Source: https://docs.fintoc.com/guides/transfers/transfers-overview/v2-transfers-account-data-model 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/transfers-api/transfers-accounts/transfers-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 When Fintoc creates your root `Entity`, Fintoc also creates a **root `Account`** for your company's money. You can't modify or delete the 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/transfers/manage-accounts/creating-more-accounts). ## Account statements Fintoc generates a monthly statement for every `Account`. You can list and download statements using `GET /v2/accounts/{account_id}/statements`. See [Account statements](/guides/transfers/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/transfers/transfers-overview/v2-transfers-account-number-data-model 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 traditional bank account number. 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/transfers-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. See [Add logic to Account Numbers](/guides/transfers/inbound-transfers/add-logic-to-clabes). * **Retire Account Numbers.** Disable or delete Account Numbers you no longer need. See [Manage your Account Numbers](/guides/transfers/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/transfers/inbound-transfers/add-logic-to-clabes). * **Deleting an Account Number releases it.** Fintoc can reassign the Account Number to another Fintoc customer. See [Manage your Account Numbers](/guides/transfers/inbound-transfers/manage-your-clabes). ## Account Number quota By default, you can create up to 1,000,000 Account Numbers per organization. Deleting an 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. # Transfer Source: https://docs.fintoc.com/guides/transfers/transfers-overview/v2-transfers-data-model A `Transfer` represents one inbound or outbound money movement. Inbound transfers are associated with 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/transfers-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 ## Transfer limits The maximum amount per `Transfer` depends on the country:
Limit 🇲🇽 Mexico 🇨🇱 Chile
Maximum amount per transfer No limit \$7,000,000 CLP
## Rate limits The Transfers API accepts up to 10 requests per second per client 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, the [Centro de Compensación Automatizado](https://www.cca.cl/) can reject inbound or outbound `Transfer` objects. When the Centro de Compensación Automatizado rejects a `Transfer`, the status changes to `returned`, and Fintoc restores the funds to your account balance. ## Authorizing a transfer The Transfers API supports a single authorizer. When a person in your organization with permission to authorize transfers confirms a `Transfer`, Fintoc pays out the `Transfer` immediately. # Send your first transfer Source: https://docs.fintoc.com/guides/transfers/transfers-quickstart Send your first Fintoc test transfer end to end, from generating API keys to subscribing to webhook events, using the Transfers 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`. ## 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/transfers/transfers-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`. Fetch it 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: ```json JSON 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" } } ] ``` ### 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/transfers/transfers-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 cURL 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" } ' ``` The response is the simulated inbound `Transfer` that funds your `Account`: ```json JSON theme={null} { "id": "tr_7HbN2kPq9wZ4xR1s", "object": "transfer", "amount": 59013, "currency": "MXN", "status": "succeeded", "direction": "inbound", "account_number_id": "acno_Kasf91034gj1AD", "comment": "Simulated inbound transfer" } ``` **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/transfers/transfers-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. ```bash cURL 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" } }' ``` The response is the outbound `Transfer` you created: ```json JSON 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" } } ``` ## 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/transfers/transfers-setup/index Configure signing keys, test your integration, and review the 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/transfers/transfers-setup/setting-up-jws-keys): generate and register the key pair that signs your transfer requests. * [Test your integration](/guides/transfers/transfers-setup/test-your-integration): simulate inbound and outbound transfers and verify webhook delivery. * [Review security controls](/guides/transfers/transfers-setup/security-controls): learn how Fintoc uses authentication, signing, and audit controls to protect transfers. # Security controls Source: https://docs.fintoc.com/guides/transfers/transfers-setup/security-controls Fintoc applies six security controls when you create payouts with the Transfers API. These controls restrict money movement to authorized parties, protect requests from tampering in transit, and let you review and audit payout 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 payout 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/transfers/transfers-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 IP allowlisting is enabled: * 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 allowlisting](/guides/home/api-keys#ip-allowlisting) *** ## 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 payouts with idempotency To avoid accidental duplicate payouts, Fintoc supports idempotency keys when creating payouts. When you send an idempotency key: * Retried requests do not create duplicate transfers. * You can retry requests after network timeouts without creating duplicate transfers. When you retry a request with the same idempotency key, Fintoc returns the original payout instead of creating a second one. 📚 [Use an idempotency key](/guides/transfers/outbound-transfers#use-an-idempotency-key) *** ## 6. Audit API usage All interactions with the Fintoc API are traceable and auditable. This includes: * API-key-based identification of the calling organization. * Timestamped requests for sensitive operations. * Logged transfer creation and state changes. These records help you: * Monitor and review payout 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 payout requests | Payload tampering, request forgery, replay attacks | | IP allowlisting | Credential leakage, unauthorized infrastructure access | | Webhook signature verification | Forged or manipulated webhook events | | Idempotent payout creation | Duplicate payouts 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 for payouts created through the Fintoc API. # Generate JWS keys Source: https://docs.fintoc.com/guides/transfers/transfers-setup/setting-up-jws-keys Sign Transfers API calls that move money with a JSON Web Signature. Set up a public-private key pair to sign protected Transfers API requests. Transfers 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/transfers-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 ``` This generates 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----- ``` **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 Transfers 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) ``` **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/transfers-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/transfers/transfers-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/transfers/inbound-transfers#step-1-create-an-account-number-clabe). 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" } ```
**Simulate endpoint** The `/simulate/*` endpoints simulate production behavior and are available only in `test` mode. ### Test returning an inbound transfer The simulated inbound transfer's `amount` determines the return outcome 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: | 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
`type`: Any type
`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
`type`: Any type
`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
`type`: Any type
`institution_id`: Any institution ID | # Collect payments with dedicated Account Numbers Source: https://docs.fintoc.com/guides/transfers/transfers-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). 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 Transferencias Electrónicas 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/transfers/inbound-transfers). 2. **Handle the webhook.** Subscribe to `transfer.inbound.succeeded`; read `data.account_number.metadata`. See [Receive transfers → Webhook payload](/guides/transfers/inbound-transfers) for the payload reference. 3. **Enforce business rules.** Set `options.min_amount` and `options.max_amount` to reject incorrect amounts automatically. Disable the Account Number after receiving payment. See [Add logic to Account Numbers](/guides/transfers/inbound-transfers/add-logic-to-clabes). 4. **Clean up unused Account Numbers** when customers leave or orders close. See [Manage your Account Numbers](/guides/transfers/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/transfers/transfers-use-cases/index Choose a Fintoc Transfers pattern for five business scenarios, from dedicated Account Numbers to bulk payouts. 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/transfers/inbound-transfers) and [Send transfers](/guides/transfers/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/transfers/transfers-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/transfers/transfers-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/transfers/transfers-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/transfers/transfers-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/transfers/transfers-use-cases/verify-a-clabe-before-paying-out) | User-entered destinations, peer-to-peer payments, onboarding | ## Availability in Chile The following reconciliation features are available only in Mexico: dedicated Account Numbers per customer, `options.min_amount`, `options.max_amount`, CLABE verification, and inbound transfer returns. In Chile, inbound transfers arrive at the default Account Number for the `Account`. Reconcile inbound transfers using `counterparty.holder_id` and `comment`. Each use case page identifies the steps that apply in each country.
# Wallet for end users Source: https://docs.fintoc.com/guides/transfers/transfers-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. Only your root `Entity` is onboarded. ```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. ### 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/transfers/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. Create one or more `Account` objects under the `Entity` by sending `POST /v2/accounts` with the `Entity`'s `entity_id`. Each `Account` has its own balance and root Account Number. A client `Entity` can hold more than one sub-account, as in Pattern B. 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 Mexican tax ID (RFC). This pattern supports onboarding Mexican `Entity` objects through the API without dashboard steps. For other countries, create the `Entity` from the dashboard. ## 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/transfers/transfers-use-cases/run-payroll-or-bulk-payouts If you pay the same recipients every cycle, use Batch Transfers in the Dashboard. You can review and authorize one payout run instead of calling the API once per employee, supplier, or seller. ## Why batch Batch Transfers includes these safeguards: * Fintoc validates one CSV of up to 5,000 rows before moving funds. * You review the total before approving the run. * You authorize the run through multi-factor authentication (MFA). * Each row triggers the same `transfer.outbound.*` webhooks as an API-created transfer, so your reconciliation code stays the same. ```mermaid theme={null} flowchart LR CSV[CSV up to 5,000 rows] --> Upload[Upload + validate] Upload --> 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/transfers/outbound-transfers/batch-transfers). # Send payouts to users or suppliers Source: https://docs.fintoc.com/guides/transfers/transfers-use-cases/send-payouts-to-users-or-suppliers Send payouts from your Fintoc Account to third-party bank accounts over SPEI in Mexico or TEF in Chile, and track every status change with webhooks. ## 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 use the Transferencia Electrónica de Fondos (TEF) 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 TEF (CL). 3. Webhook fires: transfer.outbound.succeeded / .rejected / .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 / TEF You->>Fintoc: POST /v2/transfers Fintoc-->>You: Transfer pending Fintoc->>Rail: Submit Rail-->>Fintoc: Settled / rejected Fintoc->>You: transfer.outbound.succeeded · .rejected · .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/transfers/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/transfers/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/transfers/transfers-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/transfers/outbound-transfers) for status semantics. # Verify a CLABE before sending a payout Source: https://docs.fintoc.com/guides/transfers/transfers-use-cases/verify-a-clabe-before-paying-out Mexico only. ## What you'll build Before sending 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. ## 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 CLABEs](/guides/transfers/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 CLABEs](/guides/transfers/outbound-transfers/verify-clabes) for the full payload. See [Test your integration](/guides/transfers/transfers-setup/test-your-integration) for the available test CLABEs. # Chile institution codes Source: https://docs.fintoc.com/api/fintoc-api/chile-institution-codes Use these Fintoc institution IDs when you specify a Chilean institution: | Institution name | Fintoc institution 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` | # 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/transfers-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. **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. Fintoc returns an error if the parameters differ. 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 Add custom data to your Fintoc objects 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/transfers-api/transfers/transfer-object), and [Account Numbers](/api/transfers-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`. **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 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/transfers-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) | # Types of events Source: https://docs.fintoc.com/api/main-resources/events-reference/types-of-events Reference list of all webhook event types Fintoc emits for payments, charges, links, refresh intents, invoices, and other API resources. This is a list of all the event types Fintoc currently sends. Fintoc may add more at any time, so your implementation should not assume these are the only types that exist. Events follow a pattern in their naming: `resource.event`. You cannot subscribe to the `link.created` event with a webhook endpoint. To receive it, pass your backend URL when you [configure the widget](/guides/resources/widget/web-integration). | Event type | `data.object` | Description | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account.refresh_intent.succeeded` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when an `Account` is updated with the latest available movements from the bank | | `account.refresh_intent.failed` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when an update of the movements of a specific `Account` fails. **Only available for "Refresh On Demand" plans** | | `account.refresh_intent.rejected` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when an update of the movements of a specific `Account` fails because the `Link` credentials are invalid. **Only available for "Refresh On Demand" plans** | | `account.refresh_intent.movements_removed` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when the Link's bank deletes transactions.
To enable these notifications, activate them from your [dashboard](https://dashboard.fintoc.com/webhook-endpoints). | | `account.refresh_intent.movements_modified` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when the Link's bank modifies transactions.
To enable these notifications, activate them from your [dashboard](https://dashboard.fintoc.com/webhook-endpoints). | | `account_verification.succeeded` | [`account_verification`](/api/transfers-api/account-verification/account-verification-object) | Triggers when the target account holder information has been retrieved successfully. | | `account_verification.failed` | [`account_verification`](/api/transfers-api/account-verification/account-verification-object) | Triggers when the target account holder information could not be retrieved. | | `account_number.deleted` | [`account_number`](/api/transfers-api/account-numbers/account-number-object) | Triggers when an account number is deleted. Mexico only. | | `charge.succeeded` | [`charge`](/api/direct-debit-legacy/charges/charge-object) | Triggers when a charge is validated as successful. | | `charge.failed` | [`charge`](/api/direct-debit-legacy/charges/charge-object) | Triggers when a charge fails due to insufficient funds, the charged amount being higher than the authorized amount, or the user disabling the authorization. | | `checkout_session.finished` | [`checkout_session`](/api/payments-api/checkout-sessions/checkout-session-object) | Triggers when a customer has completed a payment. The webhook contains information about the Payment including its final status. | | `checkout_session.expired` | [`checkout_session`](/api/payments-api/checkout-sessions/checkout-session-object) | Triggers when a customer leaves the payment flow before finishing | | `invoice.created` | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice is created | | `invoice.finalized` | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice is finalized and ready to be paid | | `invoice.paid` | [`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.payment_created` | [`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_failed` | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice payment attempt fails | | `invoice.payment_succeeded` | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice payment attempt succeeds | | `invoice.voided` | [`invoice`](/api/payments-api/invoices/invoice-object) | Triggers when an invoice becomes void and Fintoc disables its `hosted_invoice_url` | | `link.created` | [`link`](/api/movements-api/links/link-object) | Triggers when a `Link` is created | | `link.credentials_changed` | [`link`](/api/movements-api/links/link-object) | Triggers when the credentials corresponding to a `Link` change and the `Link` needs to be reconnected | | `link.refresh_intent.succeeded` | [`refresh_intent`](/api/movements-api/refresh-intents/refresh-intents-object) | Triggers when a `Link` has been completely updated. For now, it is only triggered for electronic invoices | | `payment_intent.succeeded` | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a `Payment Intent` finishes successfully | | `payment_intent.rejected` | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a user rejects a `Payment Intent` | | `payment_intent.expired` | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a user doesn't complete a `Payment Intent` | | `payment_intent.failed` | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when a `Payment Intent` fails | | `payment_intent.pending` | [`payment_intent`](/api/payments-api/payment-intents/payment-intents-object) | Triggers when the final status of the payment is not available yet. A future webhook will be sent with the final status once it's determined. | | `payout.created` | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when a `Payout` is created and starts processing | | `payout.succeeded` | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when a `Payout` is successfully transferred to your bank account | | `payout.canceled` | [`payout`](/api/payments-api/payouts/payout-object) | Triggers when a `Payout` is canceled and will not be sent to your bank account | | `payout.returned` | [`payout`](/api/payments-api/payouts/payout-object) | **Mexico only**
Triggers when a previously successful `Payout` is returned from your bank account. Resources included in such payout should typically be included in the next one | | `refund.in_progress` | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when a `Refund` starts processing. | | `refund.succeeded` | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when a `Refund` is successfully processed | | `refund.failed` | [`refund`](/api/payments-api/refunds/refund-object) | Triggers when a `Refund` fails | | `subscription_intent.succeeded` | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when a subscription intent is validated as successful. The `subscription_intent` includes the resulting `subscription` object. | | `subscription_intent.failed` | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when a subscription intent fails due to a problem with the bank or Fintoc. | | `subscription_intent.rejected` | [`subscription_intent`](/api/direct-debit-legacy/subscriptions-intents/subscription-intent-object) | Triggers when a subscription intent is rejected by the user. This may happen when the user rejects the MFA step or if it is entered incorrectly. | | `subscription.activated` | [`subscription`](/api/direct-debit-legacy/direct-debit-subscriptions/direct-debit-subscription-object) | Triggers when the bank has confirmed that the subscription is ready to accept charges. | | `subscription.canceled` | [`subscription`](/api/direct-debit-legacy/direct-debit-subscriptions/direct-debit-subscription-object) | Triggers when the bank informs Fintoc that the subscription has been canceled. | | `subscription.payment_method_updated` | [`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; check the payment method's `pac.status` to confirm it is chargeable. | | `subscription.payment_method_update_failed` | [`subscription`](/api/payments-api/subscriptions/subscription-object) | Triggers when the bank rejects activation of a new payment method mandate. The subscription keeps the new, failed payment method with no automatic rollback, and open invoices stay collectible through each invoice's `hosted_invoice_url`. | | `transfer.outbound.succeeded` | [`transfer`](/api/transfers-api/transfers/transfer-object) | Triggers when the **Transfer** successfully settles. | | `transfer.outbound.returned` | [`transfer`](/api/transfers-api/transfers/transfer-object) | 🇲🇽 In Mexico: Triggers when either Banco de Mexico or the counterparty institution has rejected the transfer.
🇨🇱 In Chile: Triggers when the counterparty institution has rejected the transfer. | | `transfer.outbound.failed` | [`transfer`](/api/transfers-api/transfers/transfer-object) | Triggers when the **transfer** has not been able to reach its destination account, due to an error during the process. | | `transfer.inbound.succeeded` | [`transfer`](/api/transfers-api/transfers/transfer-object) | Triggers when a **Transfer** is successfully **received** in your account. | | `transfer.inbound.returned` | [`transfer`](/api/transfers-api/transfers/transfer-object) | 🇲🇽
Triggers when an **Inbound Transfer** has been **returned** by the recipient. | | `transfer.inbound.rejected` | [`transfer`](/api/transfers-api/transfers/transfer-object) | 🇲🇽
Triggers when an **Inbound Transfer** has been **rejected** before being credited to your account. | ## 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. # Institutions Source: https://docs.fintoc.com/api/main-resources/institutions/index 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. | | `payment_method_types` | `array` | Payment method types your customer can use to pay the session. One or more of `bank_transfer` (one-time bank transfer), `installments` (pay in installments), `card` (credit or debit card), and `pac` (automatic recurring bank debit). | | `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. In Chile, a Chilean tax ID (RUT); in Mexico, a Mexican tax ID (RFC). 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) or `mx_rfc` (Mexican RFC). | | `tax_id.value` | `string` | Tax identifier without dots or hyphens. | # 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. At least one of `email` or `tax_id` must be provided; every other field is optional. If a `tax_id` is provided, both its `type` and `value` are required. Values are normalized before being stored: `email` and `address.country` are lowercased, dots and hyphens are stripped from RUTs, and RFCs are uppercased. # 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 card payment your customer has contested with their issuer, also known as a chargeback. Fintoc returns it in Disputes API responses and in dispute webhook events. The `status` field tracks the dispute from `waiting_documentation` through `in_review` to a final `won`, `lost`, or `expired`. | 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` | ISO 8601 datetime in UTC for the documentation submission deadline before the dispute is lost by default. | | `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`. | | `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`, or `won`. | | `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", "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 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" } ], "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. | | `status` | `string` | Current state of the invoice. One of `draft`, `open`, `paid`, or `void`. | | `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. | 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. # 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. # 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. # 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 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 maximum amount available to transfer was reached. | 🇨🇱 | | `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 maximum number of transfers for new contacts was reached. | 🇨🇱 | | `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 will only appear for pending payments that could not be validated 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_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. | 🇨🇱/🇲🇽 | ## 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` ### `bank_connection_error` ### `bank_not_available` ### `amount_limit_reached` ### `insufficient_funds` ### `login_credentials_locked` ### `login_invalid_credentials` ### `maximum_amount_error` ### `mfa_authorization_timeout` ### `mfa_invalid_authorization` ### `mfa_locked` ### `mfa_unavailable` ### `new_contact_amount_limit_reached` ### `new_contact_transfer_number_limit_reached` ### `recipient_account_not_allowed` # 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 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. | | `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`, or `pac` (automatic recurring bank debit). 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). | | `subscription` | `string` or `null` | Unique identifier of the subscription that generated this Payment Intent. `null` when the payment is not part of a subscription. | | `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, "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", "subscription": null, "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). | # 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`, or `canceled`. ```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", "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. | | `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`, or `canceled`. | | `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. The payment link accepts payments until you cancel it or, when `expires_after_seconds` is sent, until it expires. # 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`. | | `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`, 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 con Cuenta (PAC), a recurring direct-debit authorization on the customer's bank account, returned in the `pac` field when the Payment Method `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, returned 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 the card can currently be charged. Fintoc deactivates expired cards automatically. | | `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 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` or `null` for cards entered manually. | A card enrolled through a wallet such as Apple Pay returns `apple_pay` in `wallet` 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). | # 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`, 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`, or `pac`). # 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 payout has been canceled. | | `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`. The final status is `succeeded`, `failed`, or `canceled`. ```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`, `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. | | `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. You can cancel refunds only when their status is `created`. **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. **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 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_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. # Document types Source: https://docs.fintoc.com/guides/movements/fiscal-links/document-types Document types brought from your financial institutions ## Electronic fiscal documents The List Invoices endpoint allows you to retrieve a variety of electronic fiscal documents. Below is a table outlining the types of documents available, along with their corresponding codes used by the SII: | 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 | # Fiscal Links Source: https://docs.fintoc.com/guides/movements/fiscal-links/index Access electronic invoices and the buy and sell register of your users through Fintoc's Fiscal API and reconcile tax documents with the List Invoices endpoint. ## Electronic invoices Electronic fiscal documents can be useful to make invoice reconciliation and more. With Fintoc, you can access your users buy and sell register through the [List Invoices](/api/payments-api/invoices/invoices-list) endpoint. The API for electronic invoices returns the complete information about the amounts and taxes associated to each invoice. You can check the [Invoice Object](/api/payments-api/invoices/invoice-object) and its attributes on the Fiscal section of our API Reference. ## Sample response Here you can see what a response from the Fintoc API looks like. Read the Fiscal API reference to see more details. ```json theme={null} { "id": "fi_nMNejK7BT8oGbvO4", "object_name": "invoice", "number": "135", "institution_id": "cl_fiscal_sii", "issuer": { "id": "111111111", "name": "Hooli SpA", "institution_tax_payer": null }, "receiver": null, "issue_type": "received", "date": "2021-06-25T04:00:00.000Z", "total_amount": 12123, "net_amount": 1231, "currency": "CLP", "tax_period": "06/2021", "institution_invoice": { "received_at": "2021-06-25T19:27:04.000Z", "accepted_at": null, "confirmation_status": null, "exempt_amount": 0, "document_type": 34, "total_documents": null, "vat_amount": 123, "fixed_assets_net_amount": null, "fixed_assets_vat_amount": null, "non_refundable_vat_amount": null, "non_refundable_vat_code": null, "non_credit_tax_amount": null, "total_vat_withheld": 0, "partial_vat_withheld": 0, "non_withheld_vat": 0, "own_vat": 0, "third_party_vat": 0, "common_use_vat": null, "out_of_time_vat": 0, "reference_type_code": null, "reference_number": null, "construction_company_credit": 0, "free_zone_tax": 0, "container_deposit_guarantee": 0, "domestic_ticket_sales": 0, "international_ticket_sales": 0, "receipt_reference_number": null, "settlement_issuer_id": null, "vat_commisions": null, "net_commissions": 0, "exempt_commissions": 0, "has_note": false, "is_services_invoice": false, "services_invoice": null, "transaction_category": "Del Giro", "invoice_status": "registered", "other_taxes": { "total_amount": 400, "taxes": [ { "tax_code": 14, "tax_rate": "19", "tax_amount": 400 } ] }, "tobacco_taxes": { "cigars": 0, "cigarettes": 0, "processed_tobacco": 0 } } } ``` # 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** 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. **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_`. **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** 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). # 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: Select the option to create a `Link`. This example creates a personal `Link`, but the same steps apply to a business `Link`: 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: The Fintoc widget opens. Select **Continue**: Select the bank that holds the account you want to associate with the `Link`: Enter your bank credentials, then select **Continue**: Fintoc creates and connects the `Link`, then displays a confirmation screen. Select **Finish**: The dashboard displays the Link Token in a modal: 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. # 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. 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. 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 `refresh_intent.succeeded` webhook event. Otherwise, open the widget so your user can complete multifactor authentication. The response then includes the 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 ## 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" } } ``` 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" } } ``` 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. 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. # Wait for the results using a Webhook Endpoint Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-webhook 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. **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. **Invalid credentials** Sometimes, banks say a set of credentials are invalid when they are not. That's why we allow you to retry the Refresh Intent after a `rejected` status. If the credentials are in fact invalid, you should re-connect the Link through the widget. # Open the widget for Refresh Intents Source: https://docs.fintoc.com/guides/movements/refresh-intents-walkthrough/refresh-intents-widget **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. # UX Guidelines Source: https://docs.fintoc.com/guides/movements/ux-guidelines-1 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 | `` | If you have any questions on how to implement these recommendations, contact our team. # 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`. It is created when a `SubscriptionIntent` succeeds. Only a `Subscription` with `status` `active` can be charged. ```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. Can be `pending`, `active`, `canceled`. Only `active` subscription can be charged. | **Subscription account balance** Currently, subscriptions' account balance is only present when subscriptions are created. Specifically, when subscriptions are received via `subscription_intent.successful` events. At other moments the account balance is `null`. Only **subscriptions** created by Direct Debit merchants can be charged and have status `active`. **Subscriptions** created by Subscriptions merchants will always have status `pending`. # 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`. 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 exposed when `status` is `failed`. One of `login_invalid_credentials`, `login_credentials_locked`, `authorization_failed`, `authorization_timeout`, `request_timeout`, `subscription_intent_expired`, or `internal_error`. 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. # 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 | # 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 | 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`. **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 the bank accounts of the `Link` are being updated or not | | `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. **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. **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. **Important** Fintoc bills you only for active `Link` objects. # 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. **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.
# 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 confirmation by the bank is pending. If the movement isn't a check, this attribute is `false` | | `post_date` | `string` | Movement's accounting date, using ISO 8601 | | `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` | Shows the status of the movement. Its values can be `confirmed`, `processing`, `reversed` and `duplicated`. The `processing` status is transitory until a movement is defined with other status. | | `transaction_date` | `string` | Date and time in which the Movement was made, using ISO 8601. It can be `null`when the movement is not a transfer | | `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` | **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`. **Pending checks** Checks take some time to be confirmed by the bank. This can take as long as 48 business hours. Pending checks can be reversed for several reasons (for example, lack of funds). Fintoc marks pending checks with the `pending` flag so you know that the movement isn't yet confirmed by the bank. ### Movement Status The status field indicates the current state of a movement. Movements are initially confirmed, but may transition to other statuses as bank data is processed and validated. | Status | Description | | :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | | `confirmed` | The movement has been confirmed and is considered final. This is the default status for all movements. | | `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. | ### 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` | **Transfer data problems** Transfer data can sometimes be `null` or wrong. This can be due to the movement not being a transfer or because of matching problems with the banks statements. Always double check the transfer data before reconciliating your movements. On the other hand, movement data is **always** reliable. The transfer data can change up to 5 days after the movement was created. # 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. # 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). | | `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` for \$15,000 CLP). | | `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", "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. | | `status` | `string` | One of `active`, `incomplete` (the first invoice payment has not yet succeeded), `trialing` (the trial period has not ended), 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. | 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. Fintoc supports CLP only. | | `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. | #### 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. | # 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`, Fintoc sets the `billing_cycle_anchor` to 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. # 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`, or `collection_method`. 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. Canceled subscriptions cannot be updated. # Account number object Source: https://docs.fintoc.com/api/transfers-api/account-numbers/account-number-object Account numbers enable you to receive and track realtime Inbound Transfers using the Transfer API. ## 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. Transfers exceeding this threshold are automatically rejected. Amount is specified in the base 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. Transfers below this threshold are automatically rejected. Amount is specified in the base 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/transfers-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. Available only for Mexico account numbers, which are standardized Mexican bank account numbers (CLABEs). # Delete an account number Source: https://docs.fintoc.com/api/transfers-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/transfers-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`. 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/transfers-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/transfers-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/transfers-api/account-statements/account-statement-object Account Statements are a monthly PDF document that summarizes all movements for a given account during a specific period. ## 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 of when the account statement was generated. | | `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/transfers-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/transfers-api/account-verification/account-verification-object Confirms ownership of a counterparty bank account by issuing a verification transfer from one of your accounts. 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/transfers-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/transfers-api/transfers/spei-codes) for each code and the recommended action. | # Create an account verification Source: https://docs.fintoc.com/api/transfers-api/account-verification/account-verifications-create reference/core-api.json POST /v2/account_verifications Verifies the ownership and details of a counterparty account by issuing a verification transfer from one of your accounts. The verification uses the `live` or `test` mode of the API key. Requires a JSON Web Signature (JWS). # Get an account verification Source: https://docs.fintoc.com/api/transfers-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/transfers-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. # Create an entity Source: https://docs.fintoc.com/api/transfers-api/entities/entities-create reference/core-api.json POST /v2/entities Creates an entity in your organization for the mode (`live` or `test`) of the API key used. An entity is a legal holder of accounts. Returns the created entity. # Get an entity Source: https://docs.fintoc.com/api/transfers-api/entities/entities-get reference/core-api.json GET /v2/entities/{id} Returns details for the entity with the specified `id` in your organization. # List entities Source: https://docs.fintoc.com/api/transfers-api/entities/entities-list reference/core-api.json GET /v2/entities Lists the entities of your organization for the mode (`live` or `test`) of the API key used. An entity is a legal holder of accounts and defines ownership and identity in Transfers. 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. # The Entity object Source: https://docs.fintoc.com/api/transfers-api/entities/entity-object A legal holder of accounts. Entities define ownership and identity in Transfers. 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" } ``` # Create an onboarding Source: https://docs.fintoc.com/api/transfers-api/onboardings/entities-onboardings-create reference/main-api.json POST /v2/entities/{entity_id}/onboardings Starts an onboarding process for the entity using the company information, legal representatives, transactional profile, and shareholders provided in the request. Further requests upload documents and submit the onboarding, whose country is taken from the entity. # Get an onboarding Source: https://docs.fintoc.com/api/transfers-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/transfers-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/transfers-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. 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/transfers-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/transfers-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 20 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/transfers-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 must be a PDF, JPEG, or PNG and cannot exceed 20 MB. 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/transfers-api/onboardings/onboarding-object The Know Your Customer review of an Entity, from company information to shareholders and documents. An `Onboarding` holds the Know Your Customer review of an `Entity`: company information, legal representative, transactional profile, shareholders, and documents. 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. | | `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`. | | `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. | ## 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`. | | `document` | object | Identification document slot for the shareholder. See the `OnboardingDocument` object. | | `holder_id` | string | Mexican tax ID (RFC) of the shareholder. `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 | | :------------ | :----- | :------------------------------------------------------------------------------------------------- | | `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": { "legal_name": "Test Company 1" } }, "documents": [ { "filename": "csf.pdf", "slot_key": "tax_registration_certificate", "status": "uploaded", "uploaded_at": "2026-01-15T14:30:00Z" } ], "entity_id": "ent_8anBwgZktbZH6ydyHa6Tm0eM", "reviewed_at": null, "shareholders": [ { "id": "onbsh_0ujsswThIGTUYm2K8FjOOfXtY1K", "object": "onboarding_shareholder", "document": { "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 } ``` # Simulate receiving a transfer Source: https://docs.fintoc.com/api/transfers-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. # Account object Source: https://docs.fintoc.com/api/transfers-api/transfers-accounts/transfers-account-object Accounts let you track your available balance and send outbound transfers. ## The Account object An `Account` represents funds held for an entity. 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. Root accounts are created automatically and 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/transfers-api/transfers-accounts/transfers-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. # List accounts Source: https://docs.fintoc.com/api/transfers-api/transfers-accounts/transfers-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/transfers-api/transfers-accounts/transfers-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/transfers-api/transfers-accounts/transfers-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`. # The Movement object Source: https://docs.fintoc.com/api/transfers-api/transfers-movements/transfers-movement-object A single change to the balance of one of your accounts, recorded whenever money enters or leaves the account. 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/transfers-api/transfers-movements/transfers-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/transfers-api/transfers-movements/transfers-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. # SPEI codes Source: https://docs.fintoc.com/api/transfers-api/transfers/spei-codes # 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` | An attempt was made to use an additional payment type not supported by the receiving bank. |

# Transfer object Source: https://docs.fintoc.com/api/transfers-api/transfers/transfer-object A movement of funds into or out of one of your accounts, inbound or outbound over the bank rail. ## 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, and you create one 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, "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/transfers-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. In Chile, transfers cannot be over `7000000` CLP. | | `comment` | `string` | A comment or reference describing the transfer. For outbound transfers, you provide it; for inbound transfers, you see what the sender wrote. Up to 40 characters. | | `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 [SPEI return codes](/api/transfers-api/transfers/spei-codes). | | `status` | `string` | The status of the transfer. One of `pending`, `succeeded`, `rejected`, `failed`, `returned`, `return_pending`, or `reject_failed`. | | `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, and it 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/transfers-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/transfers-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/transfers-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/transfers-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. # 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. ## 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. ## 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. ## 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. ## 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. ## 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. ## Simulate entity onboardings in test mode `Entity` onboardings in the Transfers 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/transfers/entities/onboard-an-entity-by-api#test-the-integration) for the full trigger table and webhook examples. ## 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. ## 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). ## 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. ## 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#recovering-a-failed-payment) para ver el detalle del flujo. ## 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. ## 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. ## 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. ## 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. ## 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. ## 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. ## 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/transfers-api/entities/entities-create) y [onboarding](/api/transfers-api/onboardings/entities-onboardings-create) para ver el flujo completo. ## 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. ## 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.
## 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.
## 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. ## 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). ## 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. ## 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. ## 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
## Busca y elimina CLABEs inactivas Ahora puedes [buscar fácilmente las CLABEs](/guides/transfers/inbound-transfers/manage-your-clabes) que no reciben transferencias hace un tiempo y luego [eliminarlas](/guides/transfers/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/transfers-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/transfers-api/account-numbers/account-numbers-list):** * `no_transfers_since` en [`GET /v2/account_numbers`](/api/transfers-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/transfers-api/account-numbers/account-numbers-delete):** * [`DELETE /v2/account_numbers/{id}`](/api/transfers-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/transfers/inbound-transfers/manage-your-clabes) ## 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. 2. El destinatario aparecerá en tu **tabla de destinatarios**, donde podrás buscarlo por nombre, institución o número de cuenta. 3. En el detalle de cada destinatario puedes revisar su información, editarla o hacer clic en Transferir para enviarle dinero directamente. ## 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. Revisa esta [guía](/guides/transfers/inbound-transfers/add-logic-to-clabes#set-inbound-transfer-amount-limits) para aprender más. ## Descarga comprobantes de transferencias Para usuarios de Transfers, ahora en el detalle de tus transferencias en el dashboard puedes descargar el comprobante Fintoc. Además, al crear transferencias desde el dashboard, podrás adjuntar hasta 5 direcciones de correo para enviar copias del comprobante.
## 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. ## 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
2. Ver la configuración de tu perfil y cerrar sesión 3. Moverte entre modo prueba y modo en vivo
## 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) ## 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.

## 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.


## Ahora puedes hacer payouts y recibir payins usando SPEI con Fintoc Lanzamos el producto [Transfers](/guides/transfers/transfers-quickstart) en México, una forma de hacer payins y payouts, conectado directo al SPEI. Usando Transfers 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/transfers-api/transfers/transfers-create).
## 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. ## 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:
## 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" } ```
## 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.
## 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`, `pending` 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" } ```
## 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). ## 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. ## 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 ## 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 ## 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. 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. ## Pagos via Redirect Page 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) ## 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" } ``` **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`. ## 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. 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). ## Pagos por Transferencia Directa en Chile 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) ## Rediseño de las vistas de error para incentivar a reintentar 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. ## Seguridad en la API 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). ## Comunicando errores de conexión 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. ## Permisos - Ahora más granulares 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). ## Ve y descarga tus facturas 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). ## Pagos con Face ID o huella
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).
## Analytics - Tus métricas de un vistazo
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.
## Welcome to Fintoc Welcome to the developer hub and documentation for Fintoc!