Skip to main content

alat/
lib.rs

1//! # Wema ALAT Rust SDK
2//!
3//! An unofficial, asynchronous, type-safe Rust client for the **ALAT by Wema**
4//! developer APIs. ALAT is the fully-digital bank by Wema Bank (Nigeria); its
5//! APIM gateways let fintech partners open wallets, move money, and pay bills
6//! programmatically.
7//!
8//! This crate is designed to double as **documentation**: every type and method
9//! is annotated with both *what* it is (syntax) and *why/when* you use it
10//! (semantics), and each endpoint method cites its exact HTTP path. All models
11//! are derived from the live API schemas (see `MY_API_MAP.md` in the repo).
12//!
13//! ## Core ecosystem terminology
14//!
15//! - **NUBAN** — the standard 10-digit Nigerian bank account number. Every wallet
16//!   and account in this SDK is identified by one.
17//! - **BVN / NIN** — 11-digit identity anchors (Bank Verification Number /
18//!   National Identification Number) used for KYC during wallet creation.
19//! - **Name enquiry** — looking up the registered holder name for a NUBAN before
20//!   sending money. Nigerian transfers are instant and irreversible, so this is a
21//!   mandatory safety step.
22//! - **NIBSS / NIP** — the national switch (NIBSS) and its instant-payments rail
23//!   (NIP) that interbank transfers route through.
24//!
25//! ## Authentication
26//!
27//! APIM gates each product with a **subscription key**
28//! (`Ocp-Apim-Subscription-Key`); ALAT identifies your software **channel** with
29//! an **API key** (`x-api-key`). Bills/airtime additionally require an **access
30//! key** (`access` header). Configure these on [`Config`].
31//!
32//! Only the subscription key is self-serve; the `x-api-key` and other channel
33//! credentials are **issued by Wema during merchant onboarding**. See
34//! `WEMA_API_ONBOARDING.md` in the repository for how to obtain them and go live.
35//!
36//! ## Gateways: one client per gateway
37//!
38//! The reference endpoints span two sandboxes with different hosts and keys:
39//! funds transfer lives on the **APIM Dev** gateway, while wallet creation,
40//! account, statement, bills, and airtime live on **Playground**. A [`Client`]
41//! is bound to one gateway, so against the sandboxes you may need two clients.
42//! In production, Wema typically fronts all your products behind a single
43//! gateway host — pass it to [`Config::new`]. See [`config`] for details.
44//!
45//! ## Quickstart: verify a recipient before paying them
46//!
47//! ```no_run
48//! use alat::{Client, Config};
49//!
50//! #[tokio::main]
51//! async fn main() -> Result<(), alat::Error> {
52//!     // Funds transfer / name enquiry is on the APIM Dev gateway.
53//!     let client = Client::new(Config::apim_dev("subscription_key", "api_key"))?;
54//!
55//!     // Name enquiry: confirm who owns 0123456789 at Wema (035) before sending.
56//!     let beneficiary = client.verify_account("035", "0123456789", None).await?;
57//!     println!("Verified recipient: {}", beneficiary.account_name);
58//!     Ok(())
59//! }
60//! ```
61//!
62//! ## Building a collections → payout → refund system
63//!
64//! A common use case is a service with one **central account** that customers pay
65//! into, from which you disburse to arbitrary banks and issue (partial) refunds.
66//! The pieces map onto these modules:
67//!
68//! - **Collect with attribution** — [`modules::virtual_account`]: register a prefix
69//!   pointing at your central account, mint a virtual account per payment/user, and
70//!   handle the credit notifications. Money lands in your central account.
71//! - **Disburse / refund** — [`modules::transfer`]: `verify_account` then
72//!   `transfer_funds` (HMAC-signed) debiting your central account to any bank. A
73//!   refund is just a payout back to the payer (whose account/bank arrives in the
74//!   virtual-account credit notification); size it with the fee bands from
75//!   [`AccountNameEnquiry::charge_for`](modules::transfer::AccountNameEnquiry::charge_for)
76//!   or [`get_nip_charges`](Client::get_nip_charges).
77//! - **Reconcile** — [`modules::account`] / [`modules::statement`] for balances and
78//!   history; [`query_transactions`](Client::query_transactions) for settled inflows.
79//! - **Receive async results** — [`modules::webhook`]: the generic callback Wema
80//!   posts for payment/onboarding outcomes (virtual accounts have their own
81//!   notify/name-enquiry webhooks in [`modules::virtual_account`]).
82//!
83//! Virtual accounts are **collection-only** — they cannot be debited; payouts and
84//! refunds always come from the real central (settlement) account.
85//!
86//! ## Error model
87//!
88//! Calls return [`Result<T>`]. Failures are one of: [`Error::Network`]
89//! (transport), [`Error::Http`] (non-2xx), [`Error::Decode`] (schema mismatch),
90//! [`Error::Api`] (the bank rejected an otherwise-valid request, with its own
91//! message/code), or [`Error::Configuration`] / [`Error::Validation`]
92//! (client-side). See [`error`].
93
94pub mod client;
95pub mod config;
96pub mod envelope;
97pub mod error;
98pub mod modules;
99
100// Ergonomic crate-root re-exports.
101pub use client::Client;
102pub use config::Config;
103pub use envelope::{Acknowledgement, ApiResponse, Envelope, ServiceResponse, StatusResponse};
104pub use error::{Error, Result};