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

# Money Transfer

> Execute a money transfer to any phone number

## Overview

Execute a money transfer from your merchant account to any phone number in supported countries. This endpoint processes the actual transfer and debits your account.

<Warning>
  **Important:** Always call [Check Transfer](/api-reference/check-transfer) before executing a transfer to validate parameters and check receiver status.
</Warning>

## Endpoint

```http theme={null}
POST /api/transfer
```

## Authentication

<ParamField header="API-KEY" type="string" required>
  Your CashQ API Key for authentication
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`
</ParamField>

## Request Body

The request body parameters are identical to [Check Transfer](/api-reference/check-transfer).

<ParamField body="id" type="string" required>
  Unique numeric identifier for this transfer. Should match the ID used in Check Transfer. Must be numeric only.
</ParamField>

<ParamField body="sender_phone" type="string" required>
  Sender's phone number in E.164 format (e.g., `"+15615019469"`)
</ParamField>

<ParamField body="receiver_phone" type="string" required>
  Receiver's phone number in E.164 format (e.g., `"+201234567890"`)
</ParamField>

<ParamField body="amount" type="string" required>
  Transfer amount in dollars (e.g., `"5.0"` for \$5.00)
</ParamField>

<ParamField body="service" type="string" required>
  ID of corridor (e.g., `"1271"` for EGP). Payment attributes depend on the corridor and will be provided for the requested corridor upon request.
</ParamField>

<ParamField body="receiver_country" type="string" required>
  Country code of receiver (e.g., `"MX"` for Mexico, `"EG"` for Egypt).
</ParamField>

<ParamField body="receiver_currency" type="string" required>
  Currency code for the receiver (e.g., `"MXN"` for Mexican Peso, `"EGP"` for Egyptian Pound)
</ParamField>

<ParamField body="attribute" type="array" required>
  Array of corridor-specific payment attributes. Required attributes vary by corridor and include receiver details, bank information, address, and identification. Contact support for specific corridor requirements.

  <Expandable title="Attribute structure">
    Each attribute object contains:

    * `name` (string): Attribute name
    * `value` (string): Attribute value

    **Common attributes:**

    * **`receivedAmount`** - Amount in receiver's currency (e.g., amount in EGP)
    * **`receiverName`** - Full name of receiver
    * **`receiverFirstName`** - Receiver's first name
    * **`receiverLastName`** - Receiver's last name
    * **`receiverAddressStreet`** - Street address
    * **`receiverAddressCity`** - City
    * **`receiverAddressState`** - State/Region
    * **`receiverAddressCountry`** - Country code (e.g., "EG")
    * **`receiverAccType`** - Account type (e.g., "1" for bank account)
    * **`receiverIssuerCode`** - Bank issuer code
    * **`receiverAccountNumber`** - Bank account number
    * **`receiverBankBranchCode`** - Bank branch code (optional, if applicable)
    * **`receiverBankName`** - Bank name
    * **`receiverIdType`** - ID type ("2" for International Passport, "3" for Identification ID)
    * **`receiverIdNumber`** - Identification number
  </Expandable>

  <Warning>
    **Important: `approvelyId` Attribute**

    If you're using the Payout API with our Payin API, you must include the `approvelyId` attribute to link the payout with the payin transaction:

    ```json theme={null}
    {
      "name": "approvelyId",
      "value": "46364493"
    }
    ```

    Without this attribute, the transaction will be created but will wait for automated/manual reconciliation checking, which may cause delays.
  </Warning>
</ParamField>

## Request Example

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST 'https://api.cashqbot.com/api/transfer' \
    -H 'API-KEY: your_api_key_here' \
    -H 'Content-Type: application/json' \
    -d '{
      "id": "123456789",
      "sender_phone": "+15551234567",
      "receiver_phone": "+525551234568",
      "amount": "5.0",
      "service": "1234",
      "receiver_country": "MX",
      "receiver_currency": "MXN",
      "attribute": []
    }'
  ```

  ```javascript Node.js theme={null}
  const transferData = {
    id: '123456789',
    sender_phone: '+15551234567',
    receiver_phone: '+525551234568',
    amount: '5.0',
    service: '1234',
    receiver_country: 'MX',
    receiver_currency: 'MXN',
    attribute: []
  };

  const response = await fetch('https://api.cashqbot.com/api/transfer', {
    method: 'POST',
    headers: {
      'API-KEY': 'your_api_key_here',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(transferData)
  });

  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests
  import json

  transfer_data = {
      'id': '123456789',
      'sender_phone': '+15551234567',
      'receiver_phone': '+525551234568',
      'amount': '5.0',
      'service': '1234',
      'receiver_country': 'MX',
      'receiver_currency': 'MXN',
      'attribute': []
  }

  response = requests.post(
      'https://api.cashqbot.com/api/transfer',
      headers={
          'API-KEY': 'your_api_key_here',
          'Content-Type': 'application/json'
      },
      json=transfer_data
  )

  data = response.json()
  print(data)
  ```

  ```php PHP theme={null}
  <?php
  $transferData = [
      'id' => '123456789',
      'sender_phone' => '+15551234567',
      'receiver_phone' => '+525551234568',
      'amount' => '5.0',
      'service' => '1234',
      'receiver_country' => 'MX',
      'receiver_currency' => 'MXN',
      'attribute' => []
  ];

  $ch = curl_init();

  curl_setopt($ch, CURLOPT_URL, 'https://api.cashqbot.com/api/transfer');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      'API-KEY: your_api_key_here',
      'Content-Type: application/json'
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($transferData));

  $response = curl_exec($ch);
  curl_close($ch);

  $data = json_decode($response, true);
  print_r($data);
  ?>
  ```
</CodeGroup>

## Response

<ResponseField name="success" type="boolean" required>
  Indicates if the transfer was initiated successfully
</ResponseField>

<ResponseField name="error" type="string">
  Error message if transfer failed, empty string if successful
</ResponseField>

<ResponseField name="payment_response" type="object">
  Transfer response details

  <Expandable title="Payment response properties">
    <ResponseField name="id" type="string">
      The transfer ID you provided
    </ResponseField>

    <ResponseField name="payment_id" type="string | null">
      Internal payment ID (may be null initially)
    </ResponseField>

    <ResponseField name="state" type="string">
      Transfer state code (see [Status Codes](/api-reference/status-codes))
    </ResponseField>

    <ResponseField name="substate" type="string">
      Transfer substate code
    </ResponseField>

    <ResponseField name="code" type="string">
      Response code
    </ResponseField>
  </Expandable>
</ResponseField>

## Response Examples

<ResponseExample>
  ```json Success theme={null}
  {
    "payment_response": {
      "payment_id": null,
      "state": "-2",
      "substate": "0",
      "code": "0",
      "id": "123456789"
    },
    "error": "",
    "success": true
  }
  ```

  ```json Insufficient Funds theme={null}
  {
    "error": {
      "message": "Insufficient funds in merchant account",
      "code": "insufficient_funds"
    },
    "success": "false"
  }
  ```

  ```json Invalid Phone Number theme={null}
  {
    "error": {
      "message": "Invalid phone number format",
      "code": "invalid_phone_number"
    },
    "success": "false"
  }
  ```
</ResponseExample>

## Complete Transfer Flow

Follow this recommended flow for executing transfers:

<Steps>
  <Step title="Check balance">
    Verify you have sufficient funds using [Get Balance](/api-reference/balance)

    ```javascript theme={null}
    const balance = await getBalance();
    if (balance.balance + balance.overdraft < amountInCents) {
      throw new Error('Insufficient funds');
    }
    ```
  </Step>

  <Step title="Check KYC">
    Verify receiver's KYC status using [Check KYC](/api-reference/kyc)

    ```javascript theme={null}
    const kyc = await checkKYC(receiverPhone);
    if (parseFloat(kyc.money_limit) < amount) {
      throw new Error('Amount exceeds receiver limit');
    }
    ```
  </Step>

  <Step title="Validate transfer">
    Call [Check Transfer](/api-reference/check-transfer) to validate parameters

    ```javascript theme={null}
    const validation = await checkTransfer(transferData);
    if (!validation.success) {
      throw new Error('Validation failed');
    }
    ```
  </Step>

  <Step title="Execute transfer">
    Call this endpoint to execute the transfer

    ```javascript theme={null}
    const result = await executeTransfer(transferData);
    ```
  </Step>

  <Step title="Monitor status">
    Use [Check Status](/api-reference/status) to monitor transfer completion

    ```javascript theme={null}
    const status = await pollTransferStatus(transferId);
    ```
  </Step>
</Steps>

## Transfer States

After initiating a transfer, monitor its status:

| State | Description | Action                                |
| ----- | ----------- | ------------------------------------- |
| 0     | New         | Transfer created, processing starting |
| 40    | Processing  | Transfer in progress                  |
| 60    | Success     | Transfer completed successfully       |
| 80    | Error       | Transfer failed                       |
| -2    | Not Found   | Transfer ID not found                 |

<Info>
  See the complete [Status Codes Reference](/api-reference/status-codes) for all possible states.
</Info>

## Error Responses

| Error Code              | Description                   | Solution                                         |
| ----------------------- | ----------------------------- | ------------------------------------------------ |
| `authentication_error`  | Invalid or missing API key    | Verify your API key                              |
| `insufficient_funds`    | Not enough balance            | Add funds or reduce amount                       |
| `invalid_phone_number`  | Phone number format incorrect | Use E.164 format without `+`                     |
| `invalid_amount`        | Amount is invalid             | Check amount is positive and formatted correctly |
| `kyc_not_verified`      | Receiver KYC limits exceeded  | Reduce amount or ask receiver to verify          |
| `duplicate_transfer`    | Transfer ID already used      | Use a unique transfer ID                         |
| `internal_server_error` | Server error occurred         | Retry the request                                |

## Best Practices

<AccordionGroup>
  <Accordion title="Always validate first">
    Call Check Transfer before executing to catch errors early and check receiver status.
  </Accordion>

  <Accordion title="Use unique transfer IDs">
    Generate unique IDs for each transfer. Reusing IDs may cause duplicate transfer errors.
  </Accordion>

  <Accordion title="Check balance before transfer">
    Verify sufficient funds to avoid insufficient balance errors.
  </Accordion>

  <Accordion title="Monitor transfer status">
    Poll the status endpoint to track transfer completion and handle any issues.
  </Accordion>

  <Accordion title="Handle payment invitations">
    Inform users when sending to new receivers about the 6-hour expiration window.
  </Accordion>

  <Accordion title="Implement idempotency">
    Store transfer IDs and results to prevent duplicate transfers if requests are retried.
  </Accordion>

  <Accordion title="Log all transfers">
    Keep detailed logs of all transfer attempts for debugging and reconciliation.
  </Accordion>
</AccordionGroup>

## Related Endpoints

<CardGroup cols={2}>
  <Card title="Check Transfer" icon="magnifying-glass" href="/api-reference/check-transfer">
    Validate transfer before execution
  </Card>

  <Card title="Check Status" icon="clock" href="/api-reference/status">
    Monitor transfer status after execution
  </Card>

  <Card title="Get Balance" icon="wallet" href="/api-reference/balance">
    Check available funds before transfer
  </Card>

  <Card title="Check KYC" icon="shield" href="/api-reference/kyc">
    Verify receiver's limits before transfer
  </Card>
</CardGroup>
