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

# Python

> Learn how to complete a bank transfer using Python.

## Concepts

This guide will walk you through the steps needed to transfer funds using Flutterwave's API with Python. You'll learn how to:

1. **Set up your server app**: Create a Python project and install the dependencies needed to configure your workspace.
2. **Get bank code**:
   Retrieve a list of bank codes from Flutterwave's API for initiating transactions.
3. **Get Account Details**:
   Use a bank code to fetch and confirm bank account details.
4. **Initiate a transfer**:
   Send money to the resolved bank account via Flutterwave.
5. **Fetch the transfer**:
   Retrieve the status of a transfer to ensure it was processed.
6. **Verify a transaction is valid**:
   Confirm the authenticity of a transaction using Flutterwave's verification endpoint.

## Step 1: Setting up your Server App

To initiate a transfer successfully, you need to whitelist your current IP address. Here is a [quick guide](https://flutterwave.com/mu/support/integrations/how-to-whitelist-ip-addresses-on-your-flutterwave-dashboard) on how to do that.

<Info>
  You can also use the universal address `0.0.0.0` to allow transfers from all IP addresses. However, this method offers less control compared to specifying a list of acceptable IP addresses.
</Info>

Create a new Python project by running the following command:

```bash theme={null}
mkdir flutterwave_python
cd flutterwave_python
```

Next, create a virtual environment for the project.

```bash theme={null}
python3 -m venv env
source env/bin/activate  
```

### Installing Your Dependencies

Next, install the required dependencies for making HTTP requests and loading environment variables.

```bash theme={null}
pip install requests python-dotenv
```

### Configuring Your Environment

Log into your [Flutterwave dashboard](https://app.flutterwave.com/dashboard) to get your API keys and add the keys to your `.env` file.

```bash theme={null}
FLW_SECRET_KEY=<your_secret_key_here>
FLW_PUBLIC_KEY=<your_public_key_here>
```

### Initializing your Project

In your Python project, create a `app.py` and import the required dependencies.

```python theme={null}
import os
import requests
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Retrieve the Flutterwave secret key
secret_key = os.getenv("FLW_SECRET_KEY")
if not secret_key:
    raise ValueError("Error loading the FLW_SECRET_KEY from .env file")
```

## Step 2: Fetch Bank Code

Before you make a transfer to any bank, you need the bank code. It is a unique identifier that every bank has. You will use this to identify the bank you want to transfer to.

```python theme={null}
# Step 2: Fetch Bank Code from Flutterwave API
def get_bank_code(country, account_bank):
    url = f"https://api.flutterwave.com/v3/banks/{country}"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }

    response = requests.get(url, headers=headers)

    if response.status_code != 200:
        raise Exception(f"Failed to fetch bank list: {response.text}")

    banks = response.json().get("data", [])
    print("Bank list fetched...")

    # Filter for the bank with the provided code
    selected_bank = next((bank for bank in banks if bank['code'] == account_bank), None)
    if not selected_bank:
        raise Exception(f"Bank not found for code: {account_bank}")

    print(f"Selected Bank: {selected_bank['name']}")
    return selected_bank
```

## Step 3: Resolve Account

Next, validate the account before making the transfer.

```python theme={null}
# Step 2 code goes here

# Step 3: Resolve Bank Account Details
def resolve_account(account_number, account_bank):
    url = "https://api.flutterwave.com/v3/accounts/resolve"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "account_number": account_number,
        "account_bank": account_bank
    }

    response = requests.post(url, headers=headers, json=data)

    if response.status_code != 200:
        raise Exception(f"Failed to resolve account: {response.text}")

    account_details = response.json().get("data")
    print("Account Verified:", account_details)
    return account_details
```

## Step 4: Initiate Transfer

Initiate the transfer once the bank account details have been verified.

```python theme={null}
# Step 3 code goes here

# Step 4: Initiate Transfer
def initiate_transfer(dummy_data, selected_bank):
    url = "https://api.flutterwave.com/v3/transfers"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "account_bank": selected_bank["code"],
        "account_number": dummy_data["account_number"],
        "amount": dummy_data["amount"],
        "narration": dummy_data["narration"],
        "currency": dummy_data["currency"],
        "reference": dummy_data["reference"],
        "callback_url": "https://example.com/callback"
    }

    response = requests.post(url, headers=headers, json=data)

    if response.status_code != 200:
        raise Exception(f"Failed to initiate transfer: {response.text}")

    transfer_response = response.json().get("data")
    print("Transfer Initiated:", transfer_response)
    return transfer_response
```

## Step 5: Fetch Transfer Status

Check the status of the transfer using the transfer ID returned from the previous step.

```python theme={null}
# Step 4 code goes here

# Step 5: Fetch Transfer Status
def fetch_transfer_status(transfer_id):
    url = f"https://api.flutterwave.com/v3/transfers/{transfer_id}"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }

    response = requests.get(url, headers=headers)

    if response.status_code != 200:
        raise Exception(f"Failed to fetch transfer status: {response.text}")

    transfer_status = response.json().get("data")
    print("Transfer Status:", transfer_status)
    return transfer_status
```

### Calling the Requests

Make the requests to simulate the bank transfer using all the functions created above.

```python theme={null}
# Step 4 code goes here
    
# Dummy Data for the transfer
dummy_data = {
    "country": "NG",
    "account_number": "0690000031",  # Replace with actual account number
    "account_bank": "044",           # Replace with actual bank code (e.g., 044 for Access Bank Nigeria)
    "amount": 10000,                 # Amount to transfer
    "narration": "Payment for services rendered",
    "currency": "NGN",               # Currency code (e.g., NGN for Naira)
    "reference": "unique-transfer-ref-hgp8"  # Unique reference for the transaction
}

# Main Flow
try:
    # Step 1: Get Bank Code
    selected_bank = get_bank_code(dummy_data["country"], dummy_data["account_bank"])

    # Step 2: Resolve Account
    account_details = resolve_account(dummy_data["account_number"], selected_bank["code"])

    # Step 3: Initiate Transfer
    transfer_response = initiate_transfer(dummy_data, selected_bank)

    # Step 4: Fetch Transfer Status (using transfer_id from response)
    transfer_status = fetch_transfer_status(transfer_response["id"])

    # Step 5: Verify Transaction (using transaction_id from response)
    verified_transaction = verify_transaction(transfer_response["id"])

except Exception as e:
    print(f"Error: {e}")
```

The code example above includes fetching the bank code, resolving the account, initiating the transfer, and fetching the transfer status for verification.

### The Complete App

Here is how your entire `app.py` should look like on completing the steps above.

```python theme={null}
import os
import requests
from dotenv import load_dotenv

# Load environment variables
load_dotenv()
FLW_SECRET_KEY = os.getenv('FLW_SECRET_KEY')

# Step 1: Fetch Bank Code from Flutterwave API
def get_bank_code(country, account_bank):
    url = f"https://api.flutterwave.com/v3/banks/{country}"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers)
    
    if response.status_code != 200:
        raise Exception(f"Failed to fetch bank list: {response.text}")
    banks = response.json().get("data", [])
    print("Bank list fetched...")
    # Filter for the bank with the provided code
    selected_bank = next((bank for bank in banks if bank['code'] == account_bank), None)
    if not selected_bank:
        raise Exception(f"Bank not found for code: {account_bank}")
    
    print(f"Selected Bank: {selected_bank['name']}")
    return selected_bank

# Step 2: Resolve Bank Account Details
def resolve_account(account_number, account_bank):
    url = "https://api.flutterwave.com/v3/accounts/resolve"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "account_number": account_number,
        "account_bank": account_bank
    }
    response = requests.post(url, headers=headers, json=data)
    if response.status_code != 200:
        raise Exception(f"Failed to resolve account: {response.text}")
    account_details = response.json().get("data")
    print("Account Verified:", account_details)
    return account_details

# Step 3: Initiate Transfer
def initiate_transfer(dummy_data, selected_bank):
    url = "https://api.flutterwave.com/v3/transfers"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "account_bank": selected_bank["code"],
        "account_number": dummy_data["account_number"],
        "amount": dummy_data["amount"],
        "narration": dummy_data["narration"],
        "currency": dummy_data["currency"],
        "reference": dummy_data["reference"],
        "callback_url": "https://example.com/callback"
    }
    response = requests.post(url, headers=headers, json=data)
    if response.status_code != 200:
        raise Exception(f"Failed to initiate transfer: {response.text}")
    transfer_response = response.json().get("data")
    print("Transfer Initiated:", transfer_response)
    return transfer_response

# Step 4: Fetch Transfer Status
def fetch_transfer_status(transfer_id):
    url = f"https://api.flutterwave.com/v3/transfers/{transfer_id}"
    headers = {
        "Authorization": f"Bearer {FLW_SECRET_KEY}",
        "Content-Type": "application/json"
    }
    response = requests.get(url, headers=headers)
    if response.status_code != 200:
        raise Exception(f"Failed to fetch transfer status: {response.text}")
    transfer_status = response.json().get("data")
    print("Transfer Status:", transfer_status)
    return transfer_status

# Dummy Data for the transfer
dummy_data = {
    "country": "NG",
    "account_number": "0690000031",  # Replace with actual account number
    "account_bank": "044",           # Replace with actual bank code (e.g., 044 for Access Bank Nigeria)
    "amount": 10000,                 # Amount to transfer
    "narration": "Payment for services rendered",
    "currency": "NGN",               # Currency code (e.g., NGN for Naira)
    "reference": "unique-transfer-ref-9p8"  # Unique reference for the transaction
}

# Main Flow
try:
    # Step 1: Get Bank Code
    selected_bank = get_bank_code(dummy_data["country"], dummy_data["account_bank"])

    # Step 2: Resolve Account
    account_details = resolve_account(dummy_data["account_number"], selected_bank["code"])

    # Step 3: Initiate Transfer
    transfer_response = initiate_transfer(dummy_data, selected_bank)

    # Step 4: Fetch Transfer Status (using transfer_id from response)
    transfer_status = fetch_transfer_status(transfer_response["id"])

except Exception as e:
    print(f"Error: {e}")
```

Run the command below to start the app.

```bash theme={null}
python app.py
```

## Next Step

Check out the features you can integrate with our [APIs](https://developer.flutterwave.com/reference/introduction) and our [Python SDK](https://github.com/Flutterwave/Python-v2?tab=readme-ov-file#usage).
Also checkout our [best practices](/best-practices) and [error handling](/common-errors) guides to learn how to build more robust applications.
