PHPackages                             itamelions/mono-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. itamelions/mono-php-sdk

ActiveLibrary[API Development](/categories/api)

itamelions/mono-php-sdk
=======================

PHP SDK for the Mono open banking API (mandates, accounts, debits, webhooks)

v1.2.0(1mo ago)31MITPHPPHP ^8.1CI passing

Since May 5Pushed 1mo agoCompare

[ Source](https://github.com/itamelions/mono-php-sdk)[ Packagist](https://packagist.org/packages/itamelions/mono-php-sdk)[ RSS](/packages/itamelions-mono-php-sdk/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (3)Versions (4)Used By (0)

mono-php
========

[](#mono-php)

[![Latest Version on Packagist](https://camo.githubusercontent.com/86b748fe310d2974b37e2832e99ca77eb1df156d2a36f38cb8cece9ebd0b583c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6974616d656c696f6e732f6d6f6e6f2d7068702d73646b2e737667)](https://packagist.org/packages/itamelions/mono-php-sdk)[![PHP Version](https://camo.githubusercontent.com/acffb6ae1962992d26e4466782832787e79504a6250f80d732c4283458b9f497/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253545382e312d626c75652e737667)](https://www.php.net/)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE)[![CI](https://github.com/itamelions/mono-php-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/itamelions/mono-php-sdk/actions)

Unofficial community PHP SDK for the [Mono](https://mono.co) open banking API.
Supports **Mandates**, **Debits**, **Customers**, **Accounts**, **Banks**, and **Webhooks**.
No framework coupling — works in any PHP 8.1+ project (Laravel, Symfony, plain PHP, etc.).

---

Requirements
------------

[](#requirements)

- PHP 8.1 or higher
- [Composer](https://getcomposer.org/)

---

Installation
------------

[](#installation)

```
composer require itamelions/mono-php-sdk
```

---

Quick Start
-----------

[](#quick-start)

```
use Mono\Mono;

$mono = new Mono($_ENV['MONO_SECRET_KEY']);

// Create a customer
$customer = $mono->customer()->create([
    'email'      => 'john@example.com',
    'first_name' => 'John',
    'last_name'  => 'Doe',
    'phone'      => '+2348000000000',
    'identity'   => ['type' => 'bvn', 'number' => '12345678901'],
]);
$customerId = $customer['data']['id'];

// Initiate a hosted mandate (returns a mono_url — redirect your user there)
$initiation = $mono->mandate()->initiate([
    'amount'       => 5000000,        // amount in kobo (₦50,000)
    'type'         => 'recurring-debit',
    'method'       => 'mandate',
    'mandate_type' => 'sweep',
    'debit_type'   => 'variable',
    'reference'    => 'your-unique-ref',
    'redirect_url' => 'https://yourapp.com/mandate/callback',
    'customer'     => ['id' => $customerId],
    'start_date'   => '2026-01-01',           // Mono interprets bare dates as midnight UTC
    'end_date'     => '2031-01-01',
]);

$monoUrl = $initiation['data']['mono_url'];
// → redirect the user to $monoUrl to complete mandate authorisation
```

---

Configuration
-------------

[](#configuration)

Set your Mono secret key as an environment variable:

```
MONO_SECRET_KEY=test_sk_xxxxxxxxxxxxxxxx

```

Then inject it:

```
$mono = new Mono(getenv('MONO_SECRET_KEY'));
```

---

Resource Reference
------------------

[](#resource-reference)

### Customer

[](#customer)

```
$mono->customer()->create(array $params): array
$mono->customer()->update(string $customerId, array $params): array
$mono->customer()->fetch(string $customerId): array
$mono->customer()->list(array $query = []): array   // supports: page, limit
```

### Account

[](#account)

```
// Exchange a Mono Connect auth code for an account ID (call once after Connect flow)
$mono->account()->auth(string $code): array

$mono->account()->fetch(string $accountId): array
$mono->account()->transactions(string $accountId, int $limit = 100, array $query = []): array
$mono->account()->identity(string $accountId): array
$mono->account()->income(string $accountId): array
$mono->account()->unlink(string $accountId): array
```

### Mandate

[](#mandate)

```
// Hosted mandate setup — returns mono_url to redirect user
$mono->mandate()->initiate(array $params): array

// Direct / e-mandate creation
$mono->mandate()->create(array $params): array

$mono->mandate()->fetch(string $mandateId): array
$mono->mandate()->list(array $query = []): array       // supports: page, limit
$mono->mandate()->pause(string $mandateId): array
$mono->mandate()->reinstate(string $mandateId): array
$mono->mandate()->cancel(string $mandateId): array
$mono->mandate()->balanceCheck(string $mandateId, ?int $amountInKobo = null): array
```

> **E-mandate / Sweep activation delay:** Do not call `charge()` until you receive the `events.mandates.ready` webhook. After a customer approves a sweep or e-mandate, Mono requires up to 3 hours before the mandate is ready to debit. Calling `charge()` before `ready` fires will return a Mono API error.
>
> **Amounts:** All `amount` values must be in the **lowest denomination** of the account currency — kobo for NGN (100 kobo = ₦1). Pass `500000` for ₦5,000, not `5000`.
>
> **Dates:** `start_date` and `end_date` accept `Y-m-d` strings (e.g. `'2026-01-01'`). Mono interprets them as **midnight UTC**. If your application runs in a non-UTC timezone, use UTC-based date logic to avoid off-by-one errors on the mandate start or expiry day.

### Debit

[](#debit)

```
// Charge a mandate (required params: amount in kobo, reference, narration)
$mono->debit()->charge(string $mandateId, array $params): array

$mono->debit()->fetch(string $mandateId, string $reference): array
$mono->debit()->all(string $mandateId, array $query = []): array
```

### Bank

[](#bank)

```
$mono->bank()->list(): array
```

---

Webhook Verification
--------------------

[](#webhook-verification)

Mono signs each webhook request body with your **webhook secret** using HMAC-SHA512 and sends the hex digest in the `mono-webhook-secret` HTTP header.

### Basic usage

[](#basic-usage)

```
use Mono\Webhook;
use Mono\Exceptions\MonoApiException;

$webhook = new Webhook($_ENV['MONO_WEBHOOK_SECRET']);

$webhook->on('events.mandates.created', function (array $data) {
    // persist $data or enqueue a job
    echo "Mandate created: " . $data['id'];
});

$webhook->on('events.mandates.debit.successful', function (array $data) {
    echo "Debit succeeded: " . $data['reference_number'];
});

// Catch-all — receives every event
$webhook->on('*', function (string $event, array $data) {
    error_log("Mono event: {$event}");
});

try {
    $rawBody  = file_get_contents('php://input');
    $sigHeader = $_SERVER['HTTP_MONO_WEBHOOK_SECRET'] ?? '';

    $webhook->process($rawBody, $sigHeader);

    http_response_code(200);
} catch (MonoApiException $e) {
    http_response_code($e->getCode() ?: 400);
    echo $e->getMessage();
}
```

### Manual signature verification

[](#manual-signature-verification)

```
$isValid = $webhook->verifySignature($rawBody, $sigHeader); // bool
```

### Idempotency

[](#idempotency)

Mono may retry unacknowledged webhook deliveries up to 25 times over 48 hours. Always deduplicate on `event_id` **before** calling `process()` to avoid double-processing:

```
$rawBody   = file_get_contents('php://input');
$sigHeader = $_SERVER['HTTP_MONO_WEBHOOK_SECRET'] ?? '';

$preview = json_decode($rawBody, true);
$eventId = $preview['event_id'] ?? null;

if ($eventId && YourCache::has($eventId)) {
    http_response_code(200);
    exit; // already handled
}

$webhook->process($rawBody, $sigHeader);

if ($eventId) {
    YourCache::put($eventId, true, ttl: 86400);
}
```

### Supported webhook events (non-exhaustive)

[](#supported-webhook-events-non-exhaustive)

EventDescription`events.mandates.created`Mandate initiated; awaiting customer approval`events.mandates.approved`Customer approved the mandate`events.mandates.ready`Mandate ready to debit — **wait for this before calling `charge()`**`events.mandates.rejected`Mandate was rejected`events.mandate.action.pause`Mandate was paused`events.mandate.action.reinstate`Paused mandate was reinstated`events.mandate.action.cancel`Mandate was cancelled`events.mandates.expired`Mandate has passed its end date`events.mandates.debit.processing`Debit pending NIBSS confirmation`events.mandates.debit.successful`Debit succeeded`events.mandates.debit.failed`Debit failed---

Error Handling
--------------

[](#error-handling)

All API errors throw subclasses of `Mono\Exceptions\MonoApiException`:

ExceptionWhen thrown`MonoApiException`Any API error (4xx/5xx) or network failure`MonoNotFoundException`API returns `404 Not Found````
use Mono\Exceptions\MonoApiException;
use Mono\Exceptions\MonoNotFoundException;

try {
    $mandate = $mono->mandate()->fetch('mmc_invalid');
} catch (MonoNotFoundException $e) {
    echo "Not found: " . $e->getMessage();
} catch (MonoApiException $e) {
    echo "API error {$e->getCode()}: " . $e->getMessage();
}
```

---

Running Tests
-------------

[](#running-tests)

```
composer install
./vendor/bin/phpunit
```

Tests use **Mockery** to mock the Guzzle HTTP client — no live API calls are made.

---

What This SDK Covers
--------------------

[](#what-this-sdk-covers)

ResourceMethodsCustomercreate, update, fetch, listAccountauth, fetch, transactions, identity, income, unlinkMandateinitiate, create, fetch, list, pause, reinstate, cancel, balanceCheckDebitcharge, fetch, allBanklistWebhookprocess, verifySignature, on() listener---

Version Roadmap
---------------

[](#version-roadmap)

VersionScope`v1.0`Accounts, Customers, Mandates, Debits, Banks, Webhooks`v1.1`Laravel service provider + facade`v1.2`Retry middleware, configurable timeout`v2.0`Full Mono Connect (statement, income, identity)---

Contributing
------------

[](#contributing)

Contributions are welcome! Please open an issue or submit a pull request.

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Write tests for your changes
4. Ensure all tests pass: `./vendor/bin/phpunit`
5. Open a pull request

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

---

Disclaimer
----------

[](#disclaimer)

This is an **unofficial** community SDK. It is not maintained by or affiliated with [Mono](https://mono.co). Refer to the [official Mono API docs](https://docs.mono.co)for the authoritative API reference.

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance93

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

3

Last Release

35d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a80b08accb2e92af5dba416683ba414b67063ae19a019f606bc39052a96cab7f?d=identicon)[itamelions](/maintainers/itamelions)

---

Top Contributors

[![itamelions](https://avatars.githubusercontent.com/u/19807417?v=4)](https://github.com/itamelions "itamelions (6 commits)")

---

Tags

apisdkpaymentsNigeriaOpen Bankingmonomandates

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/itamelions-mono-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/itamelions-mono-php-sdk/health.svg)](https://phpackages.com/packages/itamelions-mono-php-sdk)
```

###  Alternatives

[resend/resend-php

Resend PHP library.

596.2M34](/packages/resend-resend-php)[transbank/transbank-sdk

Transbank SDK

62658.8k14](/packages/transbank-transbank-sdk)[mozex/anthropic-laravel

Laravel integration for the Anthropic API: facade, config publishing, install command, testing fakes, messages, streaming, tool use, thinking, and batches.

74287.1k1](/packages/mozex-anthropic-laravel)[files.com/files-php-sdk

Files.com PHP SDK

2478.1k](/packages/filescom-files-php-sdk)[fingerprint/fingerprint-pro-server-api-sdk

Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device.

33250.3k1](/packages/fingerprint-fingerprint-pro-server-api-sdk)[eslazarev/wildberries-sdk

Wildberries OpenAPI clients (generated).

232.5k](/packages/eslazarev-wildberries-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
