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

# SDK Quickstart

> Get started with Bila SDKs to integrate payments, collections, and transfers into your application.

This guide walks you through integrating the Bila SDK into your application. You'll learn how to configure the SDK, manage accounts, initiate collections, and send payouts across local markets.

## Overview

The Bila SDK provides a unified, type-safe interface to:

<CardGroup cols={2}>
  <Card title="Collections" icon="money-bill-wave">
    Accept mobile money payments from customers in Zambia and beyond.
  </Card>

  <Card title="Payouts & Transfers" icon="paper-plane">
    Send funds to bank accounts and mobile money wallets with ease.
  </Card>

  <Card title="Account Management" icon="wallet">
    Check balances and manage sub-wallets programmatically.
  </Card>

  <Card title="Webhooks" icon="bell">
    Receive real-time notifications for transaction status updates.
  </Card>
</CardGroup>

***

## Installation

<Tabs>
  <Tab title="TypeScript">
    ```bash theme={null}
        npm install @usebila/sdk
        # or
        yarn add @usebila/sdk
    ```
  </Tab>

  <Tab title="Python">
    ```bash theme={null}
        pip install usebila
    ```
  </Tab>

  <Tab title="Go">
    ```bash theme={null}
        go get -u github.com/bilasdk/go
    ```
  </Tab>
</Tabs>

***

## Configuration

Before making API calls, configure the SDK with your API credentials from the [Bila Console](https://app.usebila.com). You can obtain your `BILA_API_KEY` from the dashboard under **Settings → API Keys**.

<CodeGroup>
  ```typescript TypeScript theme={null}
    import Bila from '@usebila/sdk';

    const client = new Bila({
      apiKey: process.env.BILA_API_KEY,
      environment: 'sandbox', // Use 'production' for live transactions
    });
  ```

  ```python Python theme={null}
    import os
    from usebila import Bila

    client = Bila(
        api_key=os.environ.get("BILA_API_KEY"),
        environment="sandbox"  # Use 'production' for live transactions
    )
  ```

  ```go Go theme={null}
    import (
        bila "github.com/bilasdk/go"
        "github.com/bilasdk/go/option"
    )

    client := bila.NewClient(
        option.WithAPIKey(os.Getenv("BILA_API_KEY")),
        option.WithEnvironment(bila.EnvironmentSandbox),
    )
  ```
</CodeGroup>

<Warning>
  Never hardcode your API key in production code. Always use environment variables or a secure secrets manager.
</Warning>

***

## Core Flows

### 1. Check Account Balance

Verify your wallet balance before initiating payouts.

<CodeGroup>
  ```typescript TypeScript theme={null}
    const ACCOUNT_ID = 'your-account-id';

    const balance = await client.accounts.getBalance(ACCOUNT_ID);
    console.log(`Balance: ${balance.availableBalance} ${balance.currency}`);
  ```

  ```python Python theme={null}
    ACCOUNT_ID = "your-account-id"

    balance = client.accounts.get_balance(ACCOUNT_ID)
    print(f"Balance: {balance.available_balance} {balance.currency}")
  ```

  ```go Go theme={null}
    accountID := "your-account-id"

    balance, err := client.Accounts.GetBalance(ctx, accountID)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Balance: %v %v\n", balance.AvailableBalance, balance.Currency)
  ```
</CodeGroup>

***

### 2. Collect Mobile Money

Initiate a mobile money collection request from a customer. The customer receives a USSD push prompt on their phone to authorise the payment.

<CodeGroup>
  ```typescript TypeScript theme={null}
    const collection = await client.collections.initiateMobileMoneyCollection({
      amount: 100.50,
      country: 'zm',
      operator: 'airtel',
      phone: '0977000000',
      reference: 'collection-001',
      walletId: 'your-wallet-id',
      bearer: 'customer',
      customerName: 'John Doe',
      narration: 'Payment for subscription',
    });

    console.log('Collection initiated:', collection);
  ```

  ```python Python theme={null}
    collection = client.collections.initiate_mobile_money_collection(
        amount=100.50,
        country="zm",
        operator="airtel",
        phone="0977000000",
        reference="collection-001",
        wallet_id="your-wallet-id",
        bearer="customer",
        customer_name="John Doe",
        narration="Payment for subscription",
    )

    print("Collection initiated:", collection)
  ```

  ```go Go theme={null}
    collection, err := client.Collections.InitiateMobileMoneyCollection(ctx,
        bila.CollectionInitiateMobileMoneyCollectionParams{
            Amount:       bila.Float(100.50),
            Country:      bila.String("zm"),
            Operator:     bila.String("airtel"),
            Phone:        bila.String("0977000000"),
            Reference:    bila.String("collection-001"),
            WalletID:     bila.String("your-wallet-id"),
            Bearer:       bila.String("customer"),
            CustomerName: bila.String("John Doe"),
            Narration:    bila.String("Payment for subscription"),
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Collection initiated:", collection)
  ```
</CodeGroup>

#### Check Collection Status

Poll or verify the status of a collection using its reference.

<CodeGroup>
  ```typescript TypeScript theme={null}
    const status = await client.collections.getStatusByReference('collection-001');
    console.log('Status:', status);
  ```

  ```python Python theme={null}
    status = client.collections.get_status_by_reference("collection-001")
    print("Status:", status)
  ```

  ```go Go theme={null}
    status, err := client.Collections.GetStatusByReference(ctx, "collection-001")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Status:", status)
  ```
</CodeGroup>

***

### 3. Send a Mobile Money Payout

Send funds directly to a recipient's mobile money wallet.

<CodeGroup>
  ```typescript TypeScript theme={null}
    const payout = await client.transfers.initiateMobileMoneyTransfer({
      amount: 250,
      country: 'zm',
      operator: 'airtel',
      phone: '0977433571',
      reference: 'payout-001',
      narration: 'Mobile money payout',
      recipientName: 'Jane Doe',
      walletId: 'your-wallet-id',
    });

    console.log('Payout initiated:', payout);
  ```

  ```python Python theme={null}
    payout = client.transfers.initiate_mobile_money_transfer(
        amount=250,
        country="zm",
        operator="airtel",
        phone="0977433571",
        reference="payout-001",
        narration="Mobile money payout",
        recipient_name="Jane Doe",
        wallet_id="your-wallet-id",
    )

    print("Payout initiated:", payout)
  ```

  ```go Go theme={null}
    payout, err := client.Transfers.InitiateMobileMoneyTransfer(ctx,
        bila.TransferInitiateMobileMoneyTransferParams{
            Amount:        bila.Float(250),
            Country:       bila.String("zm"),
            Operator:      bila.String("airtel"),
            Phone:         bila.String("0977433571"),
            Reference:     bila.String("payout-001"),
            Narration:     bila.String("Mobile money payout"),
            RecipientName: bila.String("Jane Doe"),
            WalletID:      bila.String("your-wallet-id"),
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Payout initiated:", payout)
  ```
</CodeGroup>

***

### 4. Send a Bank Transfer

Send funds to a recipient's bank account.

<CodeGroup>
  ```typescript TypeScript theme={null}
    const transfer = await client.transfers.initiateBankTransfer({
      accountId: 'your-account-id',
      amount: 1000,
      reference: 'transfer-001',
      accountNumber: '1234567890',
      bankId: 'bank-001',
      country: 'zm',
      narration: 'Payment for services',
      recipientName: 'Jane Doe',
      transferRecipientId: 'recipient-id',
      walletId: 'your-wallet-id',
    });

    console.log('Transfer initiated:', transfer);
  ```

  ```python Python theme={null}
    transfer = client.transfers.initiate_bank_transfer(
        account_id="your-account-id",
        amount=1000,
        reference="transfer-001",
        account_number="1234567890",
        bank_id="bank-001",
        country="zm",
        narration="Payment for services",
        recipient_name="Jane Doe",
        transfer_recipient_id="recipient-id",
        wallet_id="your-wallet-id",
    )

    print("Transfer initiated:", transfer)
  ```

  ```go Go theme={null}
    transfer, err := client.Transfers.InitiateBankTransfer(ctx,
        bila.TransferInitiateBankTransferParams{
            AccountID:           bila.String("your-account-id"),
            Amount:              bila.Float(1000),
            Reference:           bila.String("transfer-001"),
            AccountNumber:       bila.String("1234567890"),
            BankID:              bila.String("bank-001"),
            Country:             bila.String("zm"),
            Narration:           bila.String("Payment for services"),
            RecipientName:       bila.String("Jane Doe"),
            TransferRecipientID: bila.String("recipient-id"),
            WalletID:            bila.String("your-wallet-id"),
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Transfer initiated:", transfer)
  ```
</CodeGroup>

***

## Webhook Integration

Use webhooks to receive real-time notifications when transactions are completed, failed, or updated — without polling the API.

### Transfer Events

| Event                  | When it fires                                  |
| ---------------------- | ---------------------------------------------- |
| `transfer.completed`   | A bank or mobile money transfer was successful |
| `transfer.failed`      | A transfer attempt was unsuccessful            |
| `collection.completed` | A mobile money collection was approved         |
| `payment.completed`    | A payment was successfully processed           |

### Create a Webhook

<CodeGroup>
  ```typescript TypeScript theme={null}
    const webhook = await client.webhooks.create({
      url: 'https://yourapp.com/webhooks/bila',
      events: ['payment.completed', 'transfer.completed', 'transfer.failed'],
    });

    console.log('Webhook created:', webhook);
  ```

  ```python Python theme={null}
    webhook = client.webhooks.create(
        url="https://yourapp.com/webhooks/bila",
        events=["payment.completed", "transfer.completed", "transfer.failed"],
    )

    print("Webhook created:", webhook)
  ```

  ```go Go theme={null}
    webhook, err := client.Webhooks.Create(ctx,
        bila.WebhookCreateParams{
            URL: bila.String("https://yourapp.com/webhooks/bila"),
            Events: []string{
                "payment.completed",
                "transfer.completed",
                "transfer.failed",
            },
        },
    )
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Webhook created:", webhook)
  ```
</CodeGroup>

### List Webhooks

<CodeGroup>
  ```typescript TypeScript theme={null}
    const webhooks = await client.webhooks.list();
    console.log('Webhooks:', webhooks);
  ```

  ```python Python theme={null}
    webhooks = client.webhooks.list()
    print("Webhooks:", webhooks)
  ```

  ```go Go theme={null}
    webhooks, err := client.Webhooks.List(ctx)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Webhooks:", webhooks)
  ```
</CodeGroup>

### Handling Webhook Events

When Bila sends an event to your endpoint, verify the signature and process the payload.

```typescript TypeScript theme={null}
app.post('/webhooks/bila', (req, res) => {
  const signature = req.headers['x-bila-signature'];

  // Verify the signature matches your webhook secret
  // Process the event payload
  const event = req.body;

  switch (event.type) {
    case 'payment.completed':
      console.log('Payment received:', event.data);
      break;
    case 'transfer.completed':
      console.log('Transfer sent:', event.data);
      break;
    case 'transfer.failed':
      console.log('Transfer failed:', event.data);
      break;
  }

  res.status(200).send('OK');
});
```

***

## Complete Integration Example

Here's a real-world example demonstrating the complete flow:

1. Configure the SDK with your API credentials
2. Retrieve your account balance
3. Initiate a mobile money collection
4. Set up a webhook to receive real-time status updates

<CodeGroup>
  ```typescript TypeScript theme={null}
    import Bila from '@usebila/sdk';

    const client = new Bila({
      apiKey: process.env.BILA_API_KEY,
      environment: 'sandbox',
    });

    async function runExample() {
      // Step 1: Check balance before initiating
      const balance = await client.accounts.getBalance('your-account-id');
      console.log(`Available balance: ${balance.availableBalance} ZMW`);

      // Step 2: Initiate a collection
      const collection = await client.collections.initiateMobileMoneyCollection({
        amount: 100.50,
        country: 'zm',
        operator: 'airtel',
        phone: '0977000000',
        reference: 'collection-001',
        walletId: 'your-wallet-id',
        customerName: 'John Doe',
        narration: 'Payment for order #1234',
      });
      console.log('Collection initiated:', collection.id);

      // Step 3: Register webhook for real-time updates
      const webhook = await client.webhooks.create({
        url: 'https://yourapp.com/webhooks/bila',
        events: ['collection.completed', 'payment.completed'],
      });
      console.log('Webhook registered:', webhook.id);
    }

    runExample().catch(console.error);
  ```

  ```python Python theme={null}
    import os
    from usebila import Bila

    client = Bila(
        api_key=os.environ.get("BILA_API_KEY"),
        environment="sandbox",
    )

    # Step 1: Check balance before initiating
    balance = client.accounts.get_balance("your-account-id")
    print(f"Available balance: {balance.available_balance} ZMW")

    # Step 2: Initiate a collection
    collection = client.collections.initiate_mobile_money_collection(
        amount=100.50,
        country="zm",
        operator="airtel",
        phone="0977000000",
        reference="collection-001",
        wallet_id="your-wallet-id",
        customer_name="John Doe",
        narration="Payment for order #1234",
    )
    print("Collection initiated:", collection.id)

    # Step 3: Register webhook for real-time updates
    webhook = client.webhooks.create(
        url="https://yourapp.com/webhooks/bila",
        events=["collection.completed", "payment.completed"],
    )
    print("Webhook registered:", webhook.id)
  ```

  ```go Go theme={null}
    package main

    import (
        "context"
        "fmt"
        "log"
        "os"

        bila "github.com/bilasdk/go"
        "github.com/bilasdk/go/option"
    )

    func main() {
        client := bila.NewClient(
            option.WithAPIKey(os.Getenv("BILA_API_KEY")),
            option.WithEnvironment(bila.EnvironmentSandbox),
        )

        ctx := context.Background()

        // Step 1: Check balance before initiating
        balance, err := client.Accounts.GetBalance(ctx, "your-account-id")
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Available balance: %v ZMW\n", balance.AvailableBalance)

        // Step 2: Initiate a collection
        collection, err := client.Collections.InitiateMobileMoneyCollection(ctx,
            bila.CollectionInitiateMobileMoneyCollectionParams{
                Amount:       bila.Float(100.50),
                Country:      bila.String("zm"),
                Operator:     bila.String("airtel"),
                Phone:        bila.String("0977000000"),
                Reference:    bila.String("collection-001"),
                WalletID:     bila.String("your-wallet-id"),
                CustomerName: bila.String("John Doe"),
                Narration:    bila.String("Payment for order #1234"),
            },
        )
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Collection initiated:", collection.ID)

        // Step 3: Register webhook for real-time updates
        webhook, err := client.Webhooks.Create(ctx,
            bila.WebhookCreateParams{
                URL:    bila.String("https://yourapp.com/webhooks/bila"),
                Events: []string{"collection.completed", "payment.completed"},
            },
        )
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("Webhook registered:", webhook.ID)
    }
  ```
</CodeGroup>

***

## Error Handling

All SDK methods may throw exceptions. Here are common error scenarios and how to handle them.

| HTTP Code | Error Type    | Description                        |
| --------- | ------------- | ---------------------------------- |
| 400       | Bad Request   | Invalid request parameters         |
| 401       | Unauthorized  | Invalid or missing API credentials |
| 403       | Forbidden     | Insufficient permissions           |
| 404       | Not Found     | Resource not found                 |
| 422       | Unprocessable | Business logic validation failed   |
| 429       | Rate Limited  | Too many requests                  |

<AccordionGroup>
  <Accordion title="TypeScript Error Handling">
    ```typescript theme={null}
        try {
          const collection = await client.collections.initiateMobileMoneyCollection({
            amount: 100.50,
            country: 'zm',
            operator: 'airtel',
            phone: '0977000000',
            reference: 'collection-001',
            walletId: 'your-wallet-id',
          });
        } catch (error) {
          if (error instanceof Bila.BilaError) {
            console.error(`Status: ${error.status}`);
            console.error(`Message: ${error.message}`);
          } else {
            console.error('Unexpected error:', error);
          }
        }
    ```
  </Accordion>

  <Accordion title="Python Error Handling">
    ```python theme={null}
        from usebila import APIStatusError

        try:
            collection = client.collections.initiate_mobile_money_collection(
                amount=100.50,
                country="zm",
                operator="airtel",
                phone="0977000000",
                reference="collection-001",
                wallet_id="your-wallet-id",
            )
        except APIStatusError as e:
            print(f"Status: {e.status_code}")
            print(f"Response: {e.response}")
    ```
  </Accordion>

  <Accordion title="Go Error Handling">
    ```go theme={null}
        collection, err := client.Collections.InitiateMobileMoneyCollection(ctx,
            bila.CollectionInitiateMobileMoneyCollectionParams{
                Amount:    bila.Float(100.50),
                Country:   bila.String("zm"),
                Operator:  bila.String("airtel"),
                Phone:     bila.String("0977000000"),
                Reference: bila.String("collection-001"),
                WalletID:  bila.String("your-wallet-id"),
            },
        )
        if err != nil {
            var apiErr *bila.Error
            if errors.As(err, &apiErr) {
                fmt.Printf("Status: %d\n", apiErr.StatusCode)
                fmt.Printf("Body: %s\n", apiErr.Body)
            }
            log.Fatal(err)
        }
    ```
  </Accordion>
</AccordionGroup>

***

## Best Practices

<Steps>
  <Step title="Secure Your Credentials">
    Always use environment variables or a secrets manager for API credentials. Never commit credentials to version control.
  </Step>

  <Step title="Implement Webhook Signature Verification">
    Always verify webhook signatures to ensure events are legitimately from Bila and haven't been tampered with.
  </Step>

  <Step title="Handle Errors Gracefully">
    Implement proper error handling with retry logic for transient failures (5xx errors, rate limits).
  </Step>

  <Step title="Use Idempotent References">
    Always pass a unique `reference` on transfers and collections. This prevents duplicate transactions if a request is retried.
  </Step>

  <Step title="Use Webhooks Over Polling">
    Rely on webhook events for transaction status updates rather than polling the status endpoint repeatedly.
  </Step>
</Steps>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="TypeScript SDK Reference" icon="code" href="/docs/sdks/typescript-sdk-reference">
    Full method-by-method reference for the TypeScript SDK.
  </Card>

  <Card title="API Reference" icon="gears" href="/docs/api-reference">
    Explore the underlying REST API directly.
  </Card>

  <Card title="Webhooks Overview" icon="bell" href="/docs/webhooks">
    Deep dive into webhook events and security.
  </Card>

  <Card title="Collections Guide" icon="money-bill-wave" href="/docs/collections">
    Learn more about mobile money collections.
  </Card>
</CardGroup>
