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

# C# SDK

> Complete reference for the Bila C# SDK with all available methods and examples

## Overview

The Bila C# SDK provides convenient access to the Bila REST API from applications written in C#. It is generated with [Stainless](https://www.stainless.com/).

<CardGroup cols={2}>
  <Card title="Strongly Typed" icon="shield-check">
    Typed request and response models for every endpoint.
  </Card>

  <Card title="Async Methods" icon="code">
    Every method returns a `Task`, following standard .NET async conventions.
  </Card>

  <Card title="Comprehensive" icon="boxes-stacked">
    Access to all Bila API features: Accounts, Transfers, Collections, and more.
  </Card>

  <Card title="Stainless Generated" icon="bolt">
    Consistently structured and always up-to-date with the latest API changes.
  </Card>
</CardGroup>

## Installation

Install the package from [NuGet](https://www.nuget.org/packages/Usebila):

```bash theme={null}
dotnet add package Usebila
```

This library requires .NET Standard 2.0 or later.

## Quick Start

```csharp theme={null}
using System;
using Usebila;
using Usebila.Models.Accounts;
 
BilaClient client = new()
{
    ApiKey = "Your API key",
    BaseUrl = EnvironmentUrl.Sandbox, // either EnvironmentUrl.Production or EnvironmentUrl.Sandbox
};
 
AccountListParams parameters = new();
 
AccountListResponse accounts = await client.Accounts.List(parameters);
 
Console.WriteLine(accounts);
```

Configure the client using environment variables, so you don't need to pass `ApiKey` explicitly:

```csharp theme={null}
using Usebila;
 
// Configured using the BILA_API_KEY and BILA_BASE_URL environment variables
BilaClient client = new();
```

| Property  | Environment variable | Required | Default value               |
| --------- | -------------------- | -------- | --------------------------- |
| `ApiKey`  | `BILA_API_KEY`       | true     | -                           |
| `BaseUrl` | `BILA_BASE_URL`      | true     | `"https://api.usebila.com"` |

## API Classes

The SDK is organized into resources, each handling a specific domain:

| Resource                                  | Description                                                  |
| ----------------------------------------- | ------------------------------------------------------------ |
| [Accounts](#accounts)                     | Retrieve accounts, list accounts, and check balances         |
| [TransferRecipients](#transferrecipients) | Manage payout recipients for bank and mobile money transfers |
| [Transfers](#transfers)                   | Send payouts via bank transfer and mobile money              |
| [Collections](#collections)               | Collect payments via mobile money                            |
| [Transactions](#transactions)             | Retrieve and list transaction history                        |
| [Webhooks](#webhooks)                     | Configure webhooks and manage delivery history               |
| [Banks](#banks)                           | List supported banks and financial institutions              |
| [Resolve](#resolve)                       | Verify bank account and mobile money details                 |

## Accounts

Manage your Bila wallets and check balances.

### Methods

**`client.Accounts.Retrieve(id)`**

Retrieve details for a specific account.

```csharp theme={null}
const string accountId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
AccountRetrieveResponse account = await client.Accounts.Retrieve(accountId);
Console.WriteLine("retrieve: {0}", account);
```

Returns: `Task<AccountRetrieveResponse>`

**`client.Accounts.List(params)`**

List all accounts associated with your profile.

```csharp theme={null}
AccountListParams listParams = new() { Page = 1, PerPage = 50 };
 
AccountListResponse accounts = await client.Accounts.List(listParams);
Console.WriteLine("list: {0}", accounts);
```

Returns: `Task<AccountListResponse>`

**`client.Accounts.GetBalance(id)`**

Check the real-time balance of an account.

```csharp theme={null}
AccountGetBalanceResponse balance = await client.Accounts.GetBalance(accountId);
Console.WriteLine("getBalance: {0}", balance);
```

Returns: `Task<AccountGetBalanceResponse>`

## TransferRecipients

Manage payout recipients for bank and mobile money transfers.

### Methods

**`client.TransferRecipients.Retrieve(id)`**

Retrieve details for a specific transfer recipient.

```csharp theme={null}
const string transferRecipientId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
TransferRecipientRetrieveResponse recipient = await client.TransferRecipients.Retrieve(
    transferRecipientId
);
Console.WriteLine("retrieve: {0}", recipient);
```

Returns: `Task<TransferRecipientRetrieveResponse>`

**`client.TransferRecipients.List(params)`**

List all transfer recipients.

```csharp theme={null}
TransferRecipientListParams listParams = new()
{
    Page = 1,
    PerPage = 50,
    Type = Usebila.Models.TransferRecipients.Type.BankAccount,
};
 
TransferRecipientListResponse recipients = await client.TransferRecipients.List(listParams);
Console.WriteLine("list: {0}", recipients);
```

Returns: `Task<TransferRecipientListResponse>`

**`client.TransferRecipients.CreateBankAccount(params)`**

Create a new bank account transfer recipient.

```csharp theme={null}
TransferRecipientCreateBankAccountParams bankParams = new()
{
    AccountNumber = "1234567890",
    BankID = "bank-001",
    AccountName = "John Doe",
    Country = Country.Zm,
};
 
TransferRecipientCreateBankAccountResponse bankRecipient =
    await client.TransferRecipients.CreateBankAccount(bankParams);
Console.WriteLine("createBankAccount: {0}", bankRecipient);
```

Returns: `Task<TransferRecipientCreateBankAccountResponse>`

**`client.TransferRecipients.CreateMobileMoney(params)`**

Create a new mobile money transfer recipient. This uses the resource-specific `TransferRecipientCreateMobileMoneyParamsCountry` enum rather than the shared `Country` enum.

```csharp theme={null}
TransferRecipientCreateMobileMoneyParams mobileParams = new()
{
    Country = TransferRecipientCreateMobileMoneyParamsCountry.Zm,
    Operator = Operator.Airtel,
    Phone = "0977433571",
    AccountName = "Jane Doe",
};
 
TransferRecipientCreateMobileMoneyResponse mobileRecipient =
    await client.TransferRecipients.CreateMobileMoney(mobileParams);
Console.WriteLine("createMobileMoney: {0}", mobileRecipient);
```

Returns: `Task<TransferRecipientCreateMobileMoneyResponse>`

## Transfers

Send funds to bank accounts or mobile money wallets.

### Methods

**`client.Transfers.Retrieve(id)`**

Retrieve details for a specific transfer.

```csharp theme={null}
const string transferId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
TransferRetrieveResponse transfer = await client.Transfers.Retrieve(transferId);
Console.WriteLine("retrieve: {0}", transfer);
```

Returns: `Task<TransferRetrieveResponse>`

**`client.Transfers.List(params)`**

List all transfers.

```csharp theme={null}
TransferListParams listParams = new()
{
    AccountID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
    StartDate = "2024-01-01T00:00:00Z",
    EndDate = "2024-12-31T23:59:59Z",
    Page = 1,
    PerPage = 50,
    Status = Status.Pending,
    Type = Usebila.Models.Transfers.Type.BankAccount,
};
 
TransferListResponse transfers = await client.Transfers.List(listParams);
Console.WriteLine("list: {0}", transfers);
```

Returns: `Task<TransferListResponse>`

**`client.Transfers.GetStatusByReference(reference)`**

Get the status of a transfer by its reference.

```csharp theme={null}
const string bankReference = "transfer-001";
 
TransferGetStatusByReferenceResponse status = await client.Transfers.GetStatusByReference(
    bankReference
);
Console.WriteLine("getStatusByReference: {0}", status);
```

Returns: `Task<TransferGetStatusByReferenceResponse>`

**`client.Transfers.InitiateBankTransfer(params)`**

Initiate a bank transfer.

```csharp theme={null}
TransferInitiateBankTransferParams bankParams = new()
{
    AccountID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
    Amount = 1000,
    Reference = "transfer-001",
    AccountNumber = "1234567890",
    BankID = "bank-001",
    Country = Country.Zm,
    Narration = "Payment for services",
    RecipientName = "Jane Doe",
    TransferRecipientID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
    WalletID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
};
 
TransferInitiateBankTransferResponse bankTransfer = await client.Transfers.InitiateBankTransfer(
    bankParams
);
Console.WriteLine("initiateBankTransfer: {0}", bankTransfer);
```

Returns: `Task<TransferInitiateBankTransferResponse>`

**`client.Transfers.InitiateMobileMoneyTransfer(params)`**

Initiate a mobile money transfer.

```csharp theme={null}
TransferInitiateMobileMoneyTransferParams mobileParams = new()
{
    Amount = 250,
    Country = TransferInitiateMobileMoneyTransferParamsCountry.Zm,
    Operator = Operator.Airtel,
    Phone = "0977433571",
    Reference = "mobile-transfer-001",
    Narration = "Mobile money payout",
    RecipientName = "Jane Doe",
    WalletID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
};
 
TransferInitiateMobileMoneyTransferResponse mobileTransfer =
    await client.Transfers.InitiateMobileMoneyTransfer(mobileParams);
Console.WriteLine("initiateMobileMoneyTransfer: {0}", mobileTransfer);
```

Returns: `Task<TransferInitiateMobileMoneyTransferResponse>`

## Collections

Accept mobile money payments from customers.

### Methods

**`client.Collections.Retrieve(id)`**

Retrieve details for a specific collection.

```csharp theme={null}
const string collectionId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
CollectionRetrieveResponse collection = await client.Collections.Retrieve(collectionId);
Console.WriteLine("retrieve: {0}", collection);
```

Returns: `Task<CollectionRetrieveResponse>`

**`client.Collections.List(params)`**

List all collections.

```csharp theme={null}
CollectionListParams listParams = new()
{
    AccountID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
    StartDate = "2024-01-01T00:00:00Z",
    EndDate = "2024-12-31T23:59:59Z",
    Page = 1,
    PerPage = 50,
    Status = Status.Pending,
};
 
CollectionListResponse collections = await client.Collections.List(listParams);
Console.WriteLine("list: {0}", collections);
```

Returns: `Task<CollectionListResponse>`

**`client.Collections.GetStatusByReference(reference)`**

Get the status of a collection by its reference.

```csharp theme={null}
const string reference = "collection-001";
 
CollectionGetStatusByReferenceResponse status = await client.Collections.GetStatusByReference(
    reference
);
Console.WriteLine("getStatusByReference: {0}", status);
```

Returns: `Task<CollectionGetStatusByReferenceResponse>`

**`client.Collections.InitiateMobileMoneyCollection(params)`**

Initiate a mobile money collection. Use the `Country`, `Operator`, and `Bearer` constants rather than raw strings.

```csharp theme={null}
CollectionInitiateMobileMoneyCollectionParams initiateParams = new()
{
    Amount = 100.5,
    Country = Country.Zm,
    Operator = Operator.Airtel,
    Phone = "0977433571",
    Reference = "collection-001",
    WalletID = "68f11209-451f-4a15-bfcd-d916eb8b09f4",
    Bearer = Bearer.Customer,
    CustomerName = "John Doe",
    Narration = "Payment for subscription",
};
 
CollectionInitiateMobileMoneyCollectionResponse initiated =
    await client.Collections.InitiateMobileMoneyCollection(initiateParams);
Console.WriteLine("initiateMobileMoneyCollection: {0}", initiated);
```

Returns: `Task<CollectionInitiateMobileMoneyCollectionResponse>`

## Transactions

View and manage transaction history.

### Methods

**`client.Transactions.Retrieve(id)`**

Retrieve details for a specific transaction.

```csharp theme={null}
const string transactionId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
TransactionRetrieveResponse transaction = await client.Transactions.Retrieve(transactionId);
Console.WriteLine("retrieve: {0}", transaction);
```

Returns: `Task<TransactionRetrieveResponse>`

**`client.Transactions.List(params)`**

List all transactions.

```csharp theme={null}
TransactionListParams listParams = new() { Page = 1, PerPage = 50 };
 
TransactionListResponse transactions = await client.Transactions.List(listParams);
Console.WriteLine("list: {0}", transactions);
```

Returns: `Task<TransactionListResponse>`

## Webhooks

Configure endpoints to receive real-time event notifications.

### Methods

**`client.Webhooks.Create(params)`**

Register a new webhook endpoint. Note the field is `UrlValue`, and events use the `Event` enum.

```csharp theme={null}
WebhookCreateParams createParams = new()
{
    Events = [Event.PaymentCompleted, Event.WithdrawalCompleted, Event.TransferCompleted],
    UrlValue = "https://example.com/webhooks",
};
 
WebhookCreateResponse created = await client.Webhooks.Create(createParams);
Console.WriteLine("create: {0}", created);
```

Returns: `Task<WebhookCreateResponse>`

**`client.Webhooks.Update(id, params)`**

Update an existing webhook.

```csharp theme={null}
const string webhookId = "68f11209-451f-4a15-bfcd-d916eb8b09f4";
 
WebhookUpdateParams updateParams = new()
{
    Events =
    [
        WebhookUpdateParamsEvent.PaymentCompleted,
        WebhookUpdateParamsEvent.CollectionCompleted,
        WebhookUpdateParamsEvent.TransferFailed,
    ],
    UrlValue = "https://example.com/webhooks/v2",
    IsActive = true,
};
 
WebhookUpdateResponse updated = await client.Webhooks.Update(webhookId, updateParams);
Console.WriteLine("update: {0}", updated);
```

Returns: `Task<WebhookUpdateResponse>`

**`client.Webhooks.List()`**

List all registered webhooks.

```csharp theme={null}
WebhookListResponse webhooks = await client.Webhooks.List();
Console.WriteLine("list: {0}", webhooks);
```

Returns: `Task<WebhookListResponse>`

**`client.Webhooks.Deactivate(id)`**

Deactivate a webhook.

```csharp theme={null}
WebhookDeactivateResponse deactivated = await client.Webhooks.Deactivate(webhookId);
Console.WriteLine("deactivate: {0}", deactivated);
```

Returns: `Task<WebhookDeactivateResponse>`

**`client.Webhooks.GetDeliveries(id, params)`**

Get delivery history for a specific webhook.

```csharp theme={null}
WebhookGetDeliveriesParams deliveriesParams = new()
{
    StartDate = "2026-04-01T00:00:00.000Z",
    EndDate = "2026-04-30T23:59:59.999Z",
    EventType = "payment.completed",
    Page = 1,
    PerPage = 20,
    Status = "DELIVERED",
};
 
WebhookGetDeliveriesResponse deliveries = await client.Webhooks.GetDeliveries(
    webhookId,
    deliveriesParams
);
Console.WriteLine("getDeliveries: {0}", deliveries);
```

Returns: `Task<WebhookGetDeliveriesResponse>`

**`client.Webhooks.ListEvents()`**

List all supported webhook events.

```csharp theme={null}
WebhookListEventsResponse events = await client.Webhooks.ListEvents();
Console.WriteLine("listEvents: {0}", events);
```

Returns: `Task<WebhookListEventsResponse>`

**`client.Webhooks.RotateSecret(id)`**

Rotate the signing secret for a webhook.

```csharp theme={null}
WebhookRotateSecretResponse rotated = await client.Webhooks.RotateSecret(webhookId);
Console.WriteLine("rotateSecret: {0}", rotated);
```

Returns: `Task<WebhookRotateSecretResponse>`

## Banks

Utilities for listing supported financial institutions.

### Methods

**`client.Banks.List(params)`**

List supported banks for a specific country. Note this resource takes a plain string for `Country`, unlike Transfers, Collections, and Resolve.

```csharp theme={null}
BankListParams listParams = new() { Country = "zm" };
 
BankListResponse banks = await client.Banks.List(listParams);
Console.WriteLine("list: {0}", banks);
```

Returns: `Task<BankListResponse>`

## Resolve

Utilities for verifying account details.

### Methods

**`client.Resolve.BankAccount(params)`**

Verify the owner of a bank account.

```csharp theme={null}
ResolveBankAccountParams bankParams = new()
{
    AccountNumber = "1234567890",
    BankID = "bank-001",
    Country = Country.Zm,
};
 
ResolveBankAccountResponse resolution = await client.Resolve.BankAccount(bankParams);
Console.WriteLine("bankAccount: {0}", resolution);
```

Returns: `Task<ResolveBankAccountResponse>`

**`client.Resolve.MobileMoney(params)`**

Verify mobile money details. This uses the resource-specific `ResolveMobileMoneyParamsCountry` enum rather than the shared `Country` enum.

```csharp theme={null}
ResolveMobileMoneyParams mobileParams = new()
{
    Country = ResolveMobileMoneyParamsCountry.Zm,
    Operator = Operator.Airtel,
    Phone = "0977433571",
};
 
ResolveMobileMoneyResponse resolution = await client.Resolve.MobileMoney(mobileParams);
Console.WriteLine("mobileMoney: {0}", resolution);
```

Returns: `Task<ResolveMobileMoneyResponse>`

## Raw Responses

The SDK defines methods that deserialize responses into instances of C# classes. To access response headers, status code, or the raw body, prefix any call with `WithRawResponse`:

```csharp theme={null}
var response = await client.WithRawResponse.Accounts.List();
var statusCode = response.StatusCode;
var headers = response.Headers;
```

## Error Handling

The SDK throws custom unchecked exception types. `BilaApiException` is the base class for API errors:

```csharp theme={null}
using Usebila.Exceptions;
 
try
{
    await client.Accounts.Retrieve("invalid-id");
}
catch (BilaApiException ex)
{
    Console.Error.WriteLine($"Status: {ex.StatusCode}");
    Console.Error.WriteLine($"Message: {ex.Message}");
}
catch (Exception ex)
{
    Console.Error.WriteLine($"Unexpected error: {ex.Message}");
}
```

| Status | Exception                           |
| ------ | ----------------------------------- |
| 400    | `BilaBadRequestException`           |
| 401    | `BilaUnauthorizedException`         |
| 403    | `BilaForbiddenException`            |
| 404    | `BilaNotFoundException`             |
| 422    | `BilaUnprocessableEntityException`  |
| 429    | `BilaRateLimitException`            |
| 5xx    | `Bila5xxException`                  |
| others | `BilaUnexpectedStatusCodeException` |

All 4xx errors inherit from `Bila4xxException`. `BilaIOException` is thrown for I/O networking errors, and `BilaInvalidDataException` for failures interpreting parsed data.

## Best Practices

<Steps>
  <Step title="Use Environment Variables">
    Configure the client with no arguments to use `BILA_API_KEY` and `BILA_BASE_URL` automatically, rather than hardcoding credentials.
  </Step>

  <Step title="Check Which Resources Use Constants">
    `Country`, `Operator`, `Bearer`, `Status`, and `Event` constants are used for Transfers, Collections, TransferRecipients, Resolve, and Webhooks. Banks is the exception — its `Country` field takes a plain string. Some resources also define their own scoped country enum (e.g. `ResolveMobileMoneyParamsCountry`, `TransferRecipientCreateMobileMoneyParamsCountry`) rather than reusing the shared `Country` enum, so check the specific params class.
  </Step>

  <Step title="Reuse the Client">
    Create a single `BilaClient` instance and reuse it across requests, or use `WithOptions` to temporarily override settings without creating a new client.
  </Step>

  <Step title="Handle Errors Gracefully">
    Catch `BilaApiException` separately from generic exceptions to distinguish API-level errors from network failures.
  </Step>
</Steps>

## Next Steps

<CardGroup cols={2}>
  <Card title="SDK Quickstart" icon="rocket" href="/docs/sdks/sdk-quickstart">
    Complete integration guide with examples
  </Card>

  <Card title="Transfers" icon="right-left" href="/docs/sdks/csharp-sdk-reference#transfers">
    Learn about initiating transfers
  </Card>

  <Card title="Webhooks" icon="bell" href="/docs/sdks/csharp-sdk-reference#webhooks">
    Set up webhook notifications
  </Card>

  <Card title="API Reference" icon="file-lines" href="/docs/api-reference">
    Complete REST API documentation
  </Card>
</CardGroup>
