> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fintoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send transfers

> Initiate real-time payments using our outbound Transfers API

To create outbound transfers with Fintoc's Transfers API, complete the setup guide, then follow these steps:

1. Configure JSON Web Signature (JWS) signing keys and generate a JWS signature.
2. Add funds to the account's `root_account_number`.
3. From your backend, create a transfer 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.

<Frame>
  <img src="https://mintcdn.com/fintoc-49b8bee8/YQmOnq8Zegydl6oL/images/9ffbd4557c5c3486887b657a1c7f9651d9d1ea4630453e74b897c8e0a89cd679-image.png?fit=max&auto=format&n=YQmOnq8Zegydl6oL&q=85&s=7bc83c462682a768b75853602da128bd" width="2472" height="1092" data-path="images/9ffbd4557c5c3486887b657a1c7f9651d9d1ea4630453e74b897c8e0a89cd679-image.png" />
</Frame>

## Step 1: Configure JWS signing keys and generate a JWS signature

Every request to the Fintoc Transfers endpoints requires a JWS signature. JWS is a standard mechanism used to digitally sign a piece of data to ensure its integrity and authenticity.

To learn how to sign an API call, follow the steps in the [JWS Signature guide](/docs/transfers/transfers-setup/setting-up-jws-keys).

## Step 2: Add funds to Fintoc

To create transfers, fund your `Account` first by adding funds to the `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 examples below show successful transfer responses. To test unsuccessful results, use the terminal-status table in the [Test the integration](#test-the-integration) section below.

### Use an idempotency key

Fintoc supports [idempotency](https://en.wikipedia.org/wiki/Idempotence) to safely retry transfers without creating a duplicate transfer. When creating a transfer, use an idempotency key. If a connection error occurs, repeat the request safely.

To perform an idempotent request, provide an `Idempotency-Key` header to the request. [Learn more about idempotent request in this guide](/reference/fintoc-api/idempotent-requests).

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

```curl 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": "000000000000000000"
  },
  "metadata": {
  	"customer_id": "12050123"
   }
}
'
```

```node 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: '000000000000000000' },
  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": "000000000000000000"},
  metadata={"customer_id": "12050123"}
)
```

A successful request response looks like this:

```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": "000000000000000000",
    "account_type": "clabe",  
    "institution": {
      "id": "mx_bbva_mexico",
      "name": "BBVA Mexico",
      "country": "mx" 
     }
   },
  "account_number": {
    "id": "acno_Kasf91034gj1AD",
    "account_id": "acc_Jas92lf9adg94ka",
    "number": "111111111111111111",
    "created_at": "2024-03-01T20:09:42.949787176Z",
    "mode": "test",
    "description": null,
    "metadata": {},
    "object": "account_number"
  },
  "metadata": {
    "customer_id": "12050123"
  }
}
```

<Warning>
  **Currencies are represented as integers**

  For example, Fintoc represents **MXN \$10.29** as `1029`.

  You can [read more about currencies here](/docs/home/currencies).
</Warning>

<Info>
  **Remember to add the institution ID**

  When transferring to a standardized Mexican bank account number (CLABE), no counterparty institution ID is necessary. Fintoc deduces the institution from the CLABE number. If your counterparty is a **mobile phone number** or **debit card**, include the institution ID as a 5-digit number, as shown [here](https://www.banxico.org.mx/cep-scl/listaInstituciones.do). Otherwise, you get a `400 Bad Request` error.
</Info>

In Mexico, the `Counterparty` object requires one attribute:

| Parameter        | Description                                                                            |
| :--------------- | :------------------------------------------------------------------------------------- |
| `account_number` | The recipient's bank account number (🇲🇽 CLABE, mobile number, or debit card number). |

<br />

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

```curl 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": "000000000",
    "account_type": "checking_account",
    "institution_id": "cl_banco_de_chile"
  },
  "metadata": {
  	"customer_id": "12050123"
  }
}
'
```

```node 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: '000000000',
    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": "000000000",
    "account_type": "checking_account",
    "institution_id": "cl_banco_de_chile"
  },
  metadata={"customer_id": "12050123"}
)
```

A successful request response looks like this:

```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": "000000000",
    "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. You can see the [code for each institution here](/reference/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](/docs/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](/docs/resources/webhooks-walkthrough) to receive these events and run actions, such as sending a notification email to your customer or logging the transfer in your ERP.

We recommend handling the following events:

| Event                         | Description                                                                                                                                                                                                                                                                                                                                                        |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `transfer.outbound.succeeded` | Sent when the transfer is sent successfully.                                                                                                                                                                                                                                                                                                                       |
| `transfer.outbound.rejected`  | 🇲🇽 In Mexico, Fintoc sends this event when Banco de Mexico or the counterparty institution rejects the transfer. See the [rejection causes](/reference/transfers-api/transfers/spei-codes).<br /><br />🇨🇱 In Chile: Sent when the counterparty institution has rejected the transfer.<br /><br />`rejected` is a final state and undergoes no further changes. |
| `transfer.outbound.failed`    | Sent when the transfer has not been able to reach its destination account, due to an error during the process.                                                                                                                                                                                                                                                     |

<Danger>
  **Webhooks may arrive in disorder**

  For example: a `transfer.outbound.rejected` webhook event could arrive before the same transfer's `transfer.outbound.succeeded` webhook, even though the transfer first succeeded and then was rejected.
</Danger>

## Test the integration

Use your test **Secret Key** (`sk_test_...`) to run transfers in `test` mode without moving real money. Every response includes `"mode": "test"`.

In `test` mode, a transfer reaches the same terminal statuses as in production. The outcome is not forced by a predefined input. It depends on how the receiving party resolves the transfer. Use the 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`    |
