alat-rs 0.2.2

Unofficial, type-safe, async Rust client for the ALAT by Wema banking APIs
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# Wema ALAT Rust SDK — and a field guide to the ALAT APIs

An **unofficial**, asynchronous, type-safe Rust SDK for the [ALAT by Wema](https://www.alat.ng/)
developer APIs — and, just as importantly, **the map of the ALAT API that Wema's own docs don't give
you in one place**.

ALAT's APIs are spread across two separate developer portals, grouped into ~30 products, and rendered
through a JavaScript console that hides the request/response schemas. This repository flattens all of
that into:

- a **type-safe Rust client** with correct paths, payloads, and response models (this crate);
- a complete, schema-level **API map** ([`MY_API_MAP.md`]./MY_API_MAP.md) covering **all 55 API
  groups / 342 endpoints** across both portals;
- this README, a **plain-English guide** to how the API is structured, **which keys you need, where to
  get them, and which product to subscribe to for which endpoint**;
- [`WEMA_API_ONBOARDING.md`]./WEMA_API_ONBOARDING.md, a guide to **getting credentialed by Wema and
  going to production** (how to obtain the `x-api-key` and other bank-issued credentials).

> Everything here was derived directly from the live ALAT APIM developer portals. This project is
> **not affiliated with or endorsed by Wema Bank**.

---

## Contents

1. [How the ALAT API is structured]#1-how-the-alat-api-is-structured
2. [The two portals: Playground vs. APIM Dev]#2-the-two-portals-playground-vs-apim-dev
3. [Authentication: the four credentials]#3-authentication-the-four-credentials
4. [Getting your keys, step by step]#4-getting-your-keys-step-by-step
5. [Product & endpoint catalog]#5-product--endpoint-catalog
6. [How responses are shaped (envelopes & the callback model)]#6-how-responses-are-shaped-envelopes--the-callback-model
7. [Financial & ecosystem concepts]#7-financial--ecosystem-concepts
8. [Using this SDK]#8-using-this-sdk
9. [What this SDK covers]#9-what-this-sdk-covers
10. [Error handling]#10-error-handling
11. [Full schema reference]#11-full-schema-reference

---

## 1. How the ALAT API is structured

ALAT runs on **Microsoft Azure API Management (APIM)**. Three concepts explain almost everything:

- **Gateway** — a single host that receives every API call, e.g. `https://playground.azure-api.net`.
  ⚠️ This is **not** the sign-up portal host (`playground.alat.ng`) — calls to the portal host 404.
- **API group** — a related set of endpoints mounted under a **path prefix**, e.g. the funds-transfer
  group lives under `/funds-transfer-open`. Every request is therefore
  `https://<gateway>/<path-prefix>/<operation>`.
- **Product** — a *bundle of API groups* that you **subscribe** to. Subscribing yields a
  **subscription key**, and that one key authorizes **every API group inside that product** (and
  nothing outside it). Products are the unit of access — not individual endpoints.

```
https://playground.azure-api.net / bills-payment / api/BillsPayment/GetAllBills
└───────── gateway ────────────┘  └─ path prefix ┘ └──────── operation ────────┘
                              (an API group inside the "Wallet Services" product)
```

So the practical workflow is: **pick the endpoint → find which product contains its API group →
subscribe to that product → use the resulting subscription key.** Section 5 is the lookup table for
that.

---

## 2. The two portals: Playground vs. APIM Dev

ALAT publishes **two independent APIM instances**. They have different gateways, different keys, and
**different product catalogs** — a key issued on one is useless on the other.

| | **Playground** | **APIM Dev** |
| :-- | :-- | :-- |
| Sign-up / keys portal | `https://playground.alat.ng` | `https://wema-alatdev-apimgt.developer.azure-api.net` |
| API gateway (calls go here) | `https://playground.azure-api.net` | `https://wema-alatdev-apimgt.azure-api.net` |
| Focus | partner wallet ecosystem | open-banking / merchant ecosystem |
| Products | 10 | 22 |
| `Config` constructor | `Config::playground(...)` | `Config::apim_dev(...)` |

> ⚠️ On **Playground** the portal and the gateway are the **same host**. On **APIM Dev** they
> **differ** — you sign up at `…developer.azure-api.net` but your code calls
> `…azure-api.net` (no `developer.`). The SDK's `Config::apim_dev(...)` already targets the gateway.

Because a [`Client`] is bound to one gateway + key, spanning both portals means more than one client.
In **production**, Wema typically fronts all of *your* subscribed products behind a single gateway host
they issue you — pass it to `Config::new(base_url, sub_key, api_key)`.

---

## 3. Authentication: the four credentials

Depending on the endpoint, a call carries up to four secrets. Crucially, **only the first is
self-serve** — the rest are issued by Wema when they onboard your integration "channel":

| Credential | Sent as | Scope | How to obtain |
| :-- | :-- | :-- | :-- |
| **Subscription key** | `Ocp-Apim-Subscription-Key` header | per **product** | **Self-serve**: subscribe to a product on the portal (Section 4). |
| **Channel API key** | `x-api-key` header | per **channel** (constant) | Issued by **Wema** when your channel is registered. |
| **Access key** | `access` header | bills & airtime only | Issued by **Wema** for the bills/airtime product. |
| **Transfer salt** | used to compute the `hash` header (HMAC-SHA512) | per **channel** | Issued by **Wema**; used to sign transfers. |

What you can do with each:

- **Subscription key only** → call endpoints that need nothing else, e.g. **`GetAllBanks`** and
  **name enquiry** on the funds-transfer product. Great for a first end-to-end smoke test.
- **+ channel `x-api-key`** → wallet creation, account, statement, and most write operations.
- **+ `access`** → bills payment and airtime/data.
- **+ salt** → submitting transfers (the SDK computes the `hash` for you).

The SDK validates these at construction and injects them per request; see Section 8.

---

## 4. Getting your keys, step by step

### A. Self-serve: a subscription key (do this now)

1. Open the **developer portal** for the gateway you need (Section 2) and click **Sign up**; confirm
   your email and **Sign in**.
2. Go to **Products** and open the product that contains your target API group (use the catalog in
   Section 5). Most products show **"Subscribe"** and are granted instantly (a few are marked
   🔒 *approval required* and are reviewed by Wema).
3. After subscribing, open your **Profile** — your subscription lists a **Primary** and **Secondary**
   key. Either works as `Ocp-Apim-Subscription-Key`.

Repeat per product/portal you need (Section 9 lists what this SDK uses).

### B. Wema-issued: channel API key, access key, transfer salt

The `x-api-key`, channel ID, `access` header, and funds-transfer `salt` identify *your* integration and
are **not** generated in the portal — Wema issues them during merchant onboarding (*"This value would be
provided by the bank."*). To request them:

1. Use the **"Go Live"** button on a product page → it opens Wema's **ALAT Open API Portal**
   (`https://openapidelegation.azurewebsites.net`); register/log in to apply for credentials.
2. And/or **contact your bank liaison** (`help@alat.ng`, or the Contact link once signed in) — endpoint
   pages say *"Merchants are expected to be onboarded before they are able to make valid calls."*

**See [`WEMA_API_ONBOARDING.md`](./WEMA_API_ONBOARDING.md) for the full onboarding & production guide**
— the credential map, the two-stage go-live flow, what to request per product, and the (undocumented)
questions to put to Wema.

> **Sandbox conveniences** (per Wema's docs): the development OTP is **`123456`**, and onboarding/
> payment flows return a **"Pending"** status immediately, with the final result delivered to your
> **callback URL** (Section 6).

---

## 5. Product & endpoint catalog

The lookup table promised in Section 1: every product on each portal, the API groups (path prefixes) it
unlocks, and the endpoint count. Endpoints used by **this SDK** are tagged. For per-operation request/
response **schemas**, see [`MY_API_MAP.md`](./MY_API_MAP.md).

### Playground

- **Developer portal (sign up / get keys):** `https://playground.alat.ng`
- **API gateway (what the SDK calls):** `https://playground.azure-api.net`
- **10 products · 20 distinct API groups · 82 endpoints** (some groups appear in more than one product)

| Product (subscribe to this) | API groups it unlocks | Endpoints |
| :-- | :-- | :--: |
| **Account Creation - Address Verification** | `/bills-payment` · `/card-management` · `/credit-wallet` · `/debit-wallet` · `/partnership-address-verification` · `/ws-acct-mgt` | 33 |
| **Buy Now Pay Later Service** | `/alat-bnpl` | 5 |
| **Direct Debit Service - Scheduled Payments** | `/merchant-direct-debit` | 4 |
| **Get Statement Service** | `/get-statement-service` | 2 |
| **Pay with Bank Account** | `/pwba-authenticator` | 2 |
| **Remita Payment** | *(no APIs currently published)* | 0 |
| **Term-Deposit-Credit-Card** | `/credit-check` · `/credit-wallet` · `/debit-wallet` · `/partnership-address-verification` · `/fdcreditcard` · `/ws-acct-mgt` | 21 |
| **Verify Discount Code - Merchants** | `/merchant-verify-discount-code` | 1 |
| **Virtual Naira Card** | *(no APIs currently published)* | 0 |
| **Wallet Services** | `/account-upgrade` · `/airtime-data` · `/bills-payment` · `/card-management` · `/credit-wallet` · `/debit-wallet` · `/create-account-face` · `/create-account` · `/partnership-address-verification` · `/remita-payment` · `/account-creation` · `/wallet-creation` · `/ws-acct-mgt` | 64 |

<details><summary>Full API-group breakdown for Playground (paths · purpose · #endpoints)</summary>

**Account Creation - Address Verification**  
_This API requires the bank to perform physical address verification for account upgrade._  
- `Bills Payment API``/bills-payment` · 6 endpoints  — **✅ bills in this SDK**
- `Card Management API``/card-management` · 10 endpoints
- `Credit Wallet API``/credit-wallet` · 3 endpoints
- `Debit Wallet API``/debit-wallet` · 6 endpoints
- `Partnership Account - with Address Verification``/partnership-address-verification` · 6 endpoints
- `Wallet Services - Account Management API``/ws-acct-mgt` · 2 endpoints  — **✅ account in this SDK**

**Buy Now Pay Later Service**  
_Customers can now access short-term financing that allows them to make purchases and pay for them over time._  
- `Buy-Now-Pay-Later Service``/alat-bnpl` · 5 endpoints

**Direct Debit Service - Scheduled Payments**  
_Create one-time and recurring payment schedules on WEMA/ALAT accounts._  
- `Direct Debit Service - Merchants``/merchant-direct-debit` · 4 endpoints

**Get Statement Service**  
_Use transaction statement for informed analytics._  
- `Get Statement API``/get-statement-service` · 2 endpoints  — **✅ statement in this SDK**

**Pay with Bank Account**  
_API to make payments using a Wema/ALAT bank account number._  
- `Pay with Bank Account - ALAT Authenticator``/pwba-authenticator` · 2 endpoints

**Remita Payment**  
_Pay your Remita bills on the ALAT Playground._  
- *(no APIs currently published under this product)*

**Term-Deposit-Credit-Card**  
_APIs to issue credit cards backed by term deposits._  
- `Credit Check API``/credit-check` · 1 endpoints
- `Credit Wallet API``/credit-wallet` · 3 endpoints
- `Debit Wallet API``/debit-wallet` · 6 endpoints
- `Partnership Account - with Address Verification``/partnership-address-verification` · 6 endpoints
- `Term-Deposit-Backed Credit Card Issuance Service``/fdcreditcard` · 3 endpoints
- `Wallet Services - Account Management API``/ws-acct-mgt` · 2 endpoints  — **✅ account in this SDK**

**Verify Discount Code - Merchants**  
_Merchants who have offered discounts on ALAT Rewards can programmatically verify discount codes presented by customers for redemption._  
- `VerifyDiscountCode - Merchant``/merchant-verify-discount-code` · 1 endpoints

**Virtual Naira Card**  
_API to request and manage Virtual Naira cards_  
- *(no APIs currently published under this product)*

**Wallet Services**  
_APIs to help businesses build a robust ecosystem for creating and maintaining wallets._  
- `Account Upgrade API``/account-upgrade` · 3 endpoints
- `Airtime and Data API``/airtime-data` · 6 endpoints  — **✅ airtime in this SDK**
- `Bills Payment API``/bills-payment` · 6 endpoints  — **✅ bills in this SDK**
- `Card Management API``/card-management` · 10 endpoints
- `Credit Wallet API``/credit-wallet` · 3 endpoints
- `Debit Wallet API``/debit-wallet` · 6 endpoints
- `Partnership Account - Face Biometric Authentication``/create-account-face` · 5 endpoints
- `Partnership Account - KYC``/create-account` · 4 endpoints
- `Partnership Account - with Address Verification``/partnership-address-verification` · 6 endpoints
- `Remita-Payment API``/remita-payment` · 3 endpoints
- `Wallet Creation API - BVN``/account-creation` · 5 endpoints  — **✅ wallet (BVN) in this SDK**
- `Wallet Creation API - NIN``/wallet-creation` · 5 endpoints  — **✅ wallet (NIN) in this SDK**
- `Wallet Services - Account Management API``/ws-acct-mgt` · 2 endpoints  — **✅ account in this SDK**

</details>

### APIM Dev

- **Developer portal (sign up / get keys):** `https://wema-alatdev-apimgt.developer.azure-api.net`
- **API gateway (what the SDK calls):** `https://wema-alatdev-apimgt.azure-api.net`
- **22 products · 33 distinct API groups · 258 endpoints** (some groups appear in more than one product)

| Product (subscribe to this) | API groups it unlocks | Endpoints |
| :-- | :-- | :--: |
| **ALAT Faith** | `/alat-faith-tems` · `/alatfaith` | 6 |
| **ALAT Pay** | `/alat-pay` | 3 |
| **Account Generation by Microsite** | `/microsite-acct` | 33 |
| **Cardless Transactions (Coralpay)** | `/cardlesstrans` | 3 |
| **Cardless Transactions (PayAttitude)** | `/cardlesspayattitude` | 7 |
| **Clickatell** | `/airtime-int-clickatell` | 4 |
| **Consortium - PTA Product** | `/consortium-acct-creation` · `/consortium-acct-mgt` · `/consortium-payment` · `/consortium-card` | 11 |
| **Customer Identification Service** | `/customer-identification` | 2 |
| **Digital SME Loan** | `/smeloan` | 14 |
| **Fresh Desk** | `/freddy` | 3 |
| **Gaming Product** | `/alat-wallet` · `/merchant-payout` | 28 |
| **Get Transaction Statement** | `/get-statement` | 2 |
| **HQ Demo Cards** 🔒*(approval required)* | `/alat-card-v2` | 80 |
| **Merchant - Payout API** | `/merchant-payout` | 10 |
| **Money Guard Connect** | `/moneyguardconnect` | 3 |
| **Onboarding - Open API** | `/account-maintenance` · `/onboarding-wallets` · `/onboarding-open` · `/callback-url` | 16 |
| **Open Banking APIs** | `/account-maintenance` · `/airtime` · `/open-bills` · `/funds-transfer-open` | 12 |
| **Outlet Link Pay** | `/outlet-link` | 15 |
| **Partnership Accounts** | `/account-maintenance` · `/funds-transfer` · `/partnership-account` | 7 |
| **Payout API** | `/payout` · `/wallet-transfer` | 7 |
| **VerifyDiscountCode** | `/verify-discount-code` | 1 |
| **Virtual Account** 🔒*(approval required)* | `/VirtualAccount` | 7 |

<details><summary>Full API-group breakdown for APIM Dev (paths · purpose · #endpoints)</summary>

**ALAT Faith**  
_API to aid collections for religious organizations_  
- `ALAT Faith - Tems APIs``/alat-faith-tems` · 1 endpoints
- `ALAT Faith APIs``/alatfaith` · 5 endpoints

**ALAT Pay**  
_API for e-commerce payments using a Wema Bank account number._  
- `ALAT Pay E-Commerce Transfers``/alat-pay` · 3 endpoints

**Account Generation by Microsite**  
_APIs to support acquisition drive by special initiatives and programs._  
- `Microsite_Service.API``/microsite-acct` · 33 endpoints

**Cardless Transactions (Coralpay)**  
_API for cardless transactions._  
- `Cardless Transaction Platform API (Coralpay)``/cardlesstrans` · 3 endpoints

**Cardless Transactions (PayAttitude)**  
_APIs for cardless transactions_  
- `Cardless Transaction Platform API (PayAttitude)``/cardlesspayattitude` · 7 endpoints

**Clickatell**  
_For Clickatell integration_  
- `Airtime API Clickatell``/airtime-int-clickatell` · 4 endpoints

**Consortium - PTA Product**  
_This product offers PTAs to customers for transactions on physical or virtual cards._  
- `Consortium Account Creation API``/consortium-acct-creation` · 1 endpoints
- `Consortium Account Management API``/consortium-acct-mgt` · 2 endpoints
- `Consortium Accounts Payment API``/consortium-payment` · 3 endpoints
- `Consortium Card Management``/consortium-card` · 5 endpoints

**Customer Identification Service**  
_This API allows channels to validate WEMA/ALAT customer's identity._  
- `Customer Identification Service``/customer-identification` · 2 endpoints

**Digital SME Loan**  
_API to help SME customers access digitlal loans._  
- `SMELoan.Api``/smeloan` · 14 endpoints

**Fresh Desk**  
_APIs for Fresh Desk Integration._  
- `Freddy Chat APIs``/freddy` · 3 endpoints

**Gaming Product**  
_A bouquet of API services for gaming companies. Refer to the Product Summary page for more information._  
- `ALAT Wallet API Gateway``/alat-wallet` · 18 endpoints
- `Merchant-Payout API``/merchant-payout` · 10 endpoints

**Get Transaction Statement**  
_This REST API is used to retrieve an ALAT customer's transaction statement over a specified period of time._  
- `Get statement service``/get-statement` · 2 endpoints  — **✅ statement in this SDK**

**HQ Demo Cards** — 🔒 approval required  
_API for card operations_  
- `Alat Cards API V2``/alat-card-v2` · 80 endpoints

**Merchant - Payout API**  
_This API is to afford the merchant the ability to carry out fund transfer services._  
- `Merchant-Payout API``/merchant-payout` · 10 endpoints

**Money Guard Connect**  
_API for Money Guard Connect_  
- `MoneyGuardConnect.Api``/moneyguardconnect` · 3 endpoints

**Onboarding - Open API**  
_Open API for onboarding and generating wallet accounts for customers._  
- `Account Maintenance Open API``/account-maintenance` · 3 endpoints
- `Onboarding API - Wallets``/onboarding-wallets` · 1 endpoints
- `Onboarding Open API ``/onboarding-open` · 11 endpoints
- `The Callback URL``/callback-url` · 1 endpoints

**Open Banking APIs**  
_APIs for open banking._  
- `Account Maintenance Open API``/account-maintenance` · 3 endpoints
- `Airtime Open API``/airtime` · 3 endpoints
- `Bills Payment Open API``/open-bills` · 3 endpoints
- `Funds Transfer OpenAPI``/funds-transfer-open` · 3 endpoints  — **✅ transfer in this SDK**

**Outlet Link Pay**  
_Outlet Link Pay_  
- `Outlet-Link API``/outlet-link` · 15 endpoints

**Partnership Accounts**  
_APIs to create and manage accounts for partners._  
- `Account Maintenance Open API``/account-maintenance` · 3 endpoints
- `Funds Transfer API``/funds-transfer` · 3 endpoints
- `Partnership Account Creation``/partnership-account` · 1 endpoints

**Payout API**  
_Payout service used by merchants to channel specific accounts._  
- `Payout API``/payout` · 2 endpoints
- `Wallet Transfer API``/wallet-transfer` · 5 endpoints

**VerifyDiscountCode**  
_API to verify discount code for ALAT Rewards payment._  
- `VerifyDiscountCode``/verify-discount-code` · 1 endpoints

**Virtual Account** — 🔒 approval required  
_The WEMA Virtual account service is to provide the ability for the bank to receive NIP inflows into Vendor collection accounts on behalf of their customers._  
- `Virtual Account API``/VirtualAccount` · 7 endpoints

</details>

---

## 6. How responses are shaped (envelopes & the callback model)

### Response envelopes

Every ALAT response wraps its payload in one of **three** envelopes. The SDK models all three
generically (see [`envelope`]) and unwraps them for you, turning a bank-side failure into an
[`Error::Api`] that carries the bank's own message/code.

| Envelope | Shape | Success flag | Seen on |
| :-- | :-- | :-- | :-- |
| `ServiceResponse<T>` | `{ result, successful, message }` | `successful` | account, history, transfer |
| `Envelope<T>` | `{ result, errorMessage, errorMessages, hasError, timeGenerated }` | `!hasError` | name enquiry, bills, airtime |
| `ResponseModel<T>` | `{ data, status, message, code, statusCode, errors }` | `status` | wallet creation, statement |

### The asynchronous callback model

Money-movement and onboarding endpoints are **asynchronous**: a successful call returns **"Pending"**,
and ALAT later POSTs the final result to a **callback URL** you register with them. The callback body is
a generic model with a `RequestType` enum, e.g. `1 = WalletCreation`, `2 = AccountCreation`,
`3 = PinValidation`, `4 = PaymentResponse`, `5–8 = KYC re-upload prompts`. Build one callback endpoint
and switch on `RequestType`. (Full callback schema: the `The Callback URL` group in
[`MY_API_MAP.md`](./MY_API_MAP.md).)

---

## 7. Financial & ecosystem concepts

- **NUBAN** — the standard **10-digit** Nigerian bank account number. Every wallet/account uses it.
- **BVN** — 11-digit **Bank Verification Number**; the cross-bank biometric identity anchor for KYC.
- **NIN** — 11-digit **National Identification Number**; an alternative KYC anchor for Tier-1 wallets.
- **Tier-1 wallet** — a low-KYC account openable purely digitally, with CBN balance/transaction limits.
- **Name enquiry** — looking up the registered holder name for a NUBAN **before** sending money;
  Nigerian transfers are instant and irreversible, so this is mandatory.
- **Intrabank vs. interbank** — within Wema/ALAT vs. to another bank (the latter routes over NIBSS).
- **NIBSS / NIP** — the national switch and its instant-payments rail used for interbank transfers.
- **PND ("Post No Debit")** — a restriction that blocks debits from an account.
- **Common bank codes** — Wema `035`, GTBank `058`, Zenith `057`, Access `044`, UBA `033`,
  First Bank `011` (fetch the authoritative list with [`get_bank_list`]Client::get_bank_list).

---

## 8. Using this SDK

### Install

```toml
[dependencies]
alat-rs = { path = "." } # or a published version
tokio = { version = "1", features = ["full"] }
```

### One client per gateway; sibling clients per product key

APIM issues **one subscription key per product**. Only the subscription key varies between products on
the same gateway (your `x-api-key` is constant), so derive sibling clients that **share one connection
pool**:

```rust,no_run
use alat::{Client, Config};
# fn main() -> Result<(), alat::Error> {
// Playground · "Wallet Services" product (wallet, account, bills, airtime):
let wallet = Client::new(Config::playground("WALLET_SERVICES_KEY", "channel_api_key"))?;
// Playground · "Get Statement Service" product — shares the HTTP pool:
let statements = wallet.with_subscription_key("GET_STATEMENT_KEY")?;
// APIM Dev · "Open Banking APIs" product (funds transfer) — different gateway:
let transfers = Client::new(Config::apim_dev("OPEN_BANKING_KEY", "channel_api_key"))?;
# let _ = (wallet, statements, transfers);
# Ok(())
# }
```

Add the bills/airtime credential with `Config::with_access_key("...")`, and tune the timeout with
`Config::with_timeout(...)`.

### Quickstart: verify a recipient, then transfer

```rust,no_run
use alat::{Client, Config};
use alat::modules::transfer::TransferRequest;

#[tokio::main]
async fn main() -> Result<(), alat::Error> {
    let client = Client::new(Config::apim_dev("OPEN_BANKING_KEY", "API_KEY"))?;

    // Always confirm the beneficiary first — transfers are irreversible.
    let who = client.verify_account("058", "0011223344", None).await?; // 058 = GTBank
    println!("Sending to: {}", who.account_name);

    let req = TransferRequest {
        amount: 5000.0,
        narration: "Invoice".into(),
        transaction_reference: "unique-ref-0001".into(), // idempotency key
        destination_bank_code: "058".into(),
        destination_bank_name: "GTBank".into(),
        destination_account_number: "0011223344".into(),
        destination_account_name: who.account_name,
        source_account_number: "0223344556".into(),
    };
    let res = client.transfer_funds("YOUR_SALT_KEY", &req).await?; // hash computed for you
    println!("Pending: {:?}", res.platform_transaction_reference);
    Ok(())
}
```

### Quickstart: open a Tier-1 wallet with a BVN

```rust,no_run
use alat::{Client, Config};
use alat::modules::wallet::{CreateWalletWithBvnRequest, ValidateOtpRequest};

#[tokio::main]
async fn main() -> Result<(), alat::Error> {
    let client = Client::new(Config::playground("WALLET_SERVICES_KEY", "API_KEY"))?;

    client.create_wallet_with_bvn(&CreateWalletWithBvnRequest {
        phone_number: "08012345678".into(),
        email: "jane@example.com".into(),
        bvn: "12345678901".into(),
    }).await?;                                  // step 1 → sends OTP

    client.validate_bvn_otp(&ValidateOtpRequest {
        phone_number: "08012345678".into(),
        otp: "123456".into(),                    // sandbox OTP
        tracking_id: "tracking-id".into(),
    }).await?;                                  // step 2 → enqueues creation

    let acct = client.get_bvn_partnership_account_details("08012345678").await?;
    println!("New NUBAN: {}", acct.account_number);     // step 3
    Ok(())
}
```

---

## 9. What this SDK covers

The SDK wraps a focused, correct subset of the 342 endpoints. Each method maps to a product (and thus a
subscription key) and a gateway:

| SDK module / methods | API group | Product to subscribe to | Gateway |
| :-- | :-- | :-- | :-- |
| `wallet``create_wallet_with_bvn`, `validate_bvn_otp`, `resend_bvn_otp`, `get_bvn_partnership_account_details`, `set_bvn_debit_restriction` (+ NIN equivalents) | `/account-creation`, `/wallet-creation` | **Wallet Services** | Playground |
| `account``get_wallet_details`, `get_transaction_history` | `/ws-acct-mgt` | **Wallet Services** | Playground |
| `statement``initiate_statement`, `get_statement_transactions` | `/get-statement-service` | **Get Statement Service** | Playground |
| `bills``get_all_bills`, `validate_customer`, `pay_bill`, `check_bill_transaction_status` | `/bills-payment` | **Wallet Services** | Playground |
| `bills` (airtime) — `get_data_plans`, `purchase_airtime`, `purchase_data` | `/airtime-data` | **Wallet Services** | Playground |
| `transfer``get_bank_list`, `verify_account`, `transfer_funds`, `get_nip_charges` | `/funds-transfer-open`, `/debit-wallet` (charges) | **Open Banking APIs** / **Wallet Services** | APIM Dev / Playground |
| `virtual_account``create_prefix`, `modify_prefix`, `list_prefixes`, `get_prefix`, `query_transactions` (+ webhook models) | `/VirtualAccount` | **Virtual Account** 🔒 | APIM Dev |
| `webhook` — generic callback types (`Callback`, `RequestType`, `NubanData`, …) | — (you host the endpoint) |||

So a full local test uses **three subscription keys**: *Wallet Services* + *Get Statement Service*
(Playground) and *Open Banking APIs* (APIM Dev); collections additionally need the 🔒 approval-gated
*Virtual Account* product (APIM Dev). Everything else in Section 5 is documented in
[`MY_API_MAP.md`](./MY_API_MAP.md) and is straightforward to add following the same patterns.

### Building a collections → payout → refund system

`virtual_account` + `transfer` + `webhook` compose into the common aggregator flow: register a prefix
pointing at your central settlement account, mint a virtual account per payment, receive credits via
your `TransNotify` webhook, then disburse/refund from the central account with `transfer_funds`
(size refunds with `AccountNameEnquiry::charge_for` / `get_nip_charges`). Virtual accounts are
**collection-only** — payouts always debit the real central account. See the crate docs for the full
walkthrough.

### Running the tests

```bash
cargo test                       # offline: schema round-trips, HMAC, multi-key
# Live smoke test (needs only a subscription key for Open Banking APIs):
export WEMA_APIM_SUB_KEY="<your Open Banking key>"
cargo test --test sdk_tests live_get_bank_list_smoke -- --nocapture
```

---

## 10. Error handling

Every call returns `Result<T, alat::Error>`:

| Variant | Meaning | Typical cause |
| :-- | :-- | :-- |
| [`Error::Network`] | no usable HTTP response | DNS/timeout/TLS; safe to retry idempotent reads |
| [`Error::Http`] | non-2xx from the gateway | wrong/expired key, not subscribed (`401`/`403`), rate limit (`429`) |
| [`Error::Decode`] | 2xx but body didn't match the schema | API drift (body is included for diagnosis) |
| [`Error::Api`] | the bank rejected an otherwise-valid request | "Invalid BVN", "Insufficient funds", … (carries message + code) |
| [`Error::Configuration`] | bad/missing credential, caught before any I/O | invalid header bytes, missing `access` key |
| [`Error::Validation`] | client-side guard | e.g. empty transfer salt |

---

## 11. Full schema reference

- **[`MY_API_MAP.md`]./MY_API_MAP.md** — every one of the 342 endpoints across both portals, with
  path, method, params, required headers, and **request/response example schemas**, extracted directly
  from the live ALAT developer portals.
- **[`WEMA_API_ONBOARDING.md`]./WEMA_API_ONBOARDING.md** — how to get credentialed by Wema and go to
  production: the self-serve vs. bank-issued credential map, the "Go Live" flow, and what to ask Wema.

## License

MIT. Unofficial; not affiliated with or endorsed by Wema Bank. API details are derived from Wema's
public developer portals and may change without notice — treat [`MY_API_MAP.md`](./MY_API_MAP.md) as a
snapshot and verify against the portals for production use.