@afriex/sdk 5.1.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +155 -148
  3. package/dist/cjs/client.d.ts +110 -0
  4. package/dist/cjs/client.js +231 -0
  5. package/dist/cjs/core/api-promise.d.ts +25 -0
  6. package/dist/cjs/core/api-promise.js +49 -0
  7. package/dist/cjs/core/errors.d.ts +78 -0
  8. package/dist/cjs/core/errors.js +143 -0
  9. package/dist/cjs/core/pagination.d.ts +47 -0
  10. package/dist/cjs/core/pagination.js +70 -0
  11. package/dist/cjs/core/resource.d.ts +18 -0
  12. package/dist/cjs/core/resource.js +36 -0
  13. package/dist/cjs/core/types.d.ts +43 -0
  14. package/dist/cjs/core/types.js +2 -0
  15. package/dist/cjs/generated/openapi.d.ts +5751 -0
  16. package/dist/cjs/generated/openapi.js +6 -0
  17. package/dist/cjs/index.d.ts +21 -0
  18. package/dist/cjs/index.js +34 -0
  19. package/dist/cjs/package.json +1 -0
  20. package/dist/cjs/resources/balance.d.ts +16 -0
  21. package/dist/cjs/resources/balance.js +19 -0
  22. package/dist/cjs/resources/checkout.d.ts +12 -0
  23. package/dist/cjs/resources/checkout.js +16 -0
  24. package/dist/cjs/resources/customers.d.ts +27 -0
  25. package/dist/cjs/resources/customers.js +56 -0
  26. package/dist/cjs/resources/media.d.ts +24 -0
  27. package/dist/cjs/resources/media.js +39 -0
  28. package/dist/cjs/resources/payment-batches.d.ts +41 -0
  29. package/dist/cjs/resources/payment-batches.js +76 -0
  30. package/dist/cjs/resources/payment-methods.d.ts +49 -0
  31. package/dist/cjs/resources/payment-methods.js +95 -0
  32. package/dist/cjs/resources/rates.d.ts +9 -0
  33. package/dist/cjs/resources/rates.js +13 -0
  34. package/dist/cjs/resources/sme-registration.d.ts +24 -0
  35. package/dist/cjs/resources/sme-registration.js +31 -0
  36. package/dist/cjs/resources/transactions.d.ts +39 -0
  37. package/dist/cjs/resources/transactions.js +67 -0
  38. package/dist/cjs/resources/webhooks.d.ts +43 -0
  39. package/dist/cjs/resources/webhooks.js +53 -0
  40. package/dist/cjs/version.d.ts +1 -0
  41. package/dist/cjs/version.js +5 -0
  42. package/dist/esm/client.d.ts +110 -0
  43. package/dist/esm/client.js +227 -0
  44. package/dist/esm/core/api-promise.d.ts +25 -0
  45. package/dist/esm/core/api-promise.js +45 -0
  46. package/dist/esm/core/errors.d.ts +78 -0
  47. package/dist/esm/core/errors.js +126 -0
  48. package/dist/esm/core/pagination.d.ts +47 -0
  49. package/dist/esm/core/pagination.js +65 -0
  50. package/dist/esm/core/resource.d.ts +18 -0
  51. package/dist/esm/core/resource.js +30 -0
  52. package/dist/esm/core/types.d.ts +43 -0
  53. package/dist/esm/core/types.js +1 -0
  54. package/dist/esm/generated/openapi.d.ts +5751 -0
  55. package/dist/esm/generated/openapi.js +5 -0
  56. package/dist/esm/index.d.ts +21 -0
  57. package/dist/esm/index.js +7 -0
  58. package/dist/esm/resources/balance.d.ts +16 -0
  59. package/dist/esm/resources/balance.js +15 -0
  60. package/dist/esm/resources/checkout.d.ts +12 -0
  61. package/dist/esm/resources/checkout.js +12 -0
  62. package/dist/esm/resources/customers.d.ts +27 -0
  63. package/dist/esm/resources/customers.js +52 -0
  64. package/dist/esm/resources/media.d.ts +24 -0
  65. package/dist/esm/resources/media.js +35 -0
  66. package/dist/esm/resources/payment-batches.d.ts +41 -0
  67. package/dist/esm/resources/payment-batches.js +72 -0
  68. package/dist/esm/resources/payment-methods.d.ts +49 -0
  69. package/dist/esm/resources/payment-methods.js +91 -0
  70. package/dist/esm/resources/rates.d.ts +9 -0
  71. package/dist/esm/resources/rates.js +9 -0
  72. package/dist/esm/resources/sme-registration.d.ts +24 -0
  73. package/dist/esm/resources/sme-registration.js +27 -0
  74. package/dist/esm/resources/transactions.d.ts +39 -0
  75. package/dist/esm/resources/transactions.js +63 -0
  76. package/dist/esm/resources/webhooks.d.ts +43 -0
  77. package/dist/esm/resources/webhooks.js +49 -0
  78. package/dist/esm/version.d.ts +1 -0
  79. package/dist/esm/version.js +2 -0
  80. package/package.json +52 -68
  81. package/dist/index.d.ts +0 -54
  82. package/dist/index.js +0 -54
  83. package/dist/version.d.ts +0 -8
  84. package/dist/version.js +0 -8
  85. package/skills/afriex-go-live/SKILL.md +0 -386
  86. package/skills/afriex-sdk/SKILL.md +0 -275
package/CHANGELOG.md ADDED
@@ -0,0 +1,43 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@afriex/sdk`. Versions 5.x and earlier were built in the [afriex-sdk](https://github.com/Afri-exchange/afriex-sdk) repository; see its changelog for them.
4
+
5
+ <!-- Entries go below this line, newest first. -->
6
+
7
+ ## 6.1.0
8
+
9
+ - Types updated from the API reference (#152).
10
+
11
+ ## 6.0.0
12
+
13
+ The SDK now lives next to the API reference and is generated from its OpenAPI spec, so it changes when the API does.
14
+
15
+ ### New
16
+
17
+ - A method for every endpoint in the API reference, including `transactions.quote()`.
18
+ - Types for every request, response and webhook event, generated from the spec. Webhook events are a union you can narrow on `event`.
19
+ - `for await` over any list method walks every page. Pages also have `hasNextPage()`, `getNextPage()` and `iterPages()`.
20
+ - `withResponse()` on every call returns the HTTP response and its `requestId`.
21
+ - Per-request options as the last argument: `timeout`, `maxRetries`, `headers` and `signal`.
22
+ - One error class per status, each with `status`, `code`, `details`, `headers` and `requestId`.
23
+ - `afriex.request()` calls an endpoint the SDK doesn't cover yet.
24
+ - `apiKey` defaults to the `AFRIEX_API_KEY` environment variable.
25
+ - ESM and CommonJS builds, no runtime dependencies.
26
+
27
+ ### Breaking changes, and how to migrate from 5.x
28
+
29
+ - **One package.** Import everything from `@afriex/sdk`. The SDK no longer uses `@afriex/core`, `@afriex/customers`, `@afriex/transactions` or the other per-resource packages, so remove them from your dependencies.
30
+ - **Node 20 or later.**
31
+ - **Retries are on by default** (`maxRetries: 2`), but only where they are safe: any request on `429`, and `GET` requests and `transactions.create` on timeouts and server errors. `retryConfig` is replaced by `maxRetries`, and `retryableMethods` and `retryableStatusCodes` are gone. See "Retries" in the README.
32
+ - **Configuration.** `customConfig.baseUrl` is now `baseURL`, and `customConfig.timeout` is now `timeout`. `userAgent`, `logLevel` and `enableLogging` are removed. `environment` takes `'sandbox'`; `'staging'` still works.
33
+ - **Errors.** `ApiError` is now `APIError`, with a subclass per status (`NotFoundError`, `ConflictError` and so on). `RateLimitError` extends it. `NetworkError` is now `APIConnectionError`. `ValidationError` is removed: the SDK no longer validates requests itself, and the API's `400` or `422` arrives as `BadRequestError` or `UnprocessableEntityError`.
34
+ - **Return values.** Every method resolves to the response's `data`, except:
35
+ - list methods, which resolve to a page, `{data, total, page}`, as before;
36
+ - `paymentMethods.getInstitutions()` and `paymentMethods.listVirtualAccounts()`, which resolve to the whole response, as before;
37
+ - `paymentMethods.delete()`, which resolves to the whole response.
38
+
39
+ `paymentMethods.resolveAccount()`, `paymentMethods.resolveInstitutionCode()`, `paymentMethods.getCryptoWallet()` and `webhooks.triggerTestWebhook()` used to resolve to the whole response and now resolve to its `data`. `customers.delete()`, `paymentBatches.delete()` and `paymentBatches.removeRecipient()` used to resolve to nothing and now resolve to the response's `data`. `paymentMethods.createVirtualAccount()` resolves to the response's `data` rather than `null` when the account opens later.
40
+ - **Type names** follow the spec and the `<Resource><Action>Params` pattern: `CreateCustomerRequest` is now `CustomerCreateParams`, `ListTransactionsParams` is now `TransactionListParams`, `WebhookPayload` is now `WebhookEvent`, and so on. Field types are exactly what the spec says. Where the spec does not mark a response field as required, its type is optional.
41
+ - **Removed helpers:** `balance.getBalanceForCurrency()`, `rates.getRate()` and `rates.convert()`. Use `balance.getBalance()` and `rates.getRates()`.
42
+ - **Webhooks.** The `WebhookVerifier` class and the `webhookVerifier` property are removed: create the client with `webhookPublicKey` and call `afriex.webhooks.verify()` or `verifyAndParse()`. Both now accept the header value as Node gives it (`string | string[] | undefined`). `verifyAndParse()` throws `WebhookVerificationError`. `triggerTestWebhook()` no longer accepts the deprecated `resourceId`: use `entityId`.
43
+ - `paymentMethods.listPoolAccounts()` is deprecated: use `paymentMethods.getPoolAccount()`.
package/README.md CHANGED
@@ -1,199 +1,206 @@
1
- # @afriex/sdk
1
+ # Afriex TypeScript SDK
2
2
 
3
- Official TypeScript SDK for the Afriex Business API. A unified interface for all Afriex services.
3
+ The official TypeScript and JavaScript client for the [Afriex Business API](https://docs.afriex.com). It is generated from the same OpenAPI spec as the API reference, so its types always match the documented API.
4
4
 
5
- ## Installation
5
+ - One package, no runtime dependencies, built on the platform's `fetch`
6
+ - Full types for every request, response and webhook event
7
+ - Retries with backoff where they are safe, timeouts, and typed errors
8
+ - Pagination you can `for await` over
9
+ - ESM and CommonJS, Node 20 or later
10
+
11
+ ## Install
6
12
 
7
13
  ```bash
8
14
  npm install @afriex/sdk
9
- # or
10
- pnpm add @afriex/sdk
11
15
  ```
12
16
 
13
- ## Quick Start
17
+ ## Usage
14
18
 
15
- ```typescript
16
- import { AfriexSDK } from "@afriex/sdk";
17
- // or use the alias
18
- import { Afriex } from "@afriex/sdk";
19
+ ```ts
20
+ import {Afriex} from '@afriex/sdk';
19
21
 
20
- const afriex = new AfriexSDK({
21
- apiKey: "your-api-key",
22
- environment: "production", // or 'staging' (default: 'production')
23
- webhookPublicKey: "-----BEGIN PUBLIC KEY-----...", // optional
22
+ const afriex = new Afriex({
23
+ apiKey: process.env.AFRIEX_API_KEY, // the default, so you can leave it out
24
+ environment: 'sandbox', // or 'production', the default
24
25
  });
25
26
 
26
- // Customers
27
27
  const customer = await afriex.customers.create({
28
- fullName: "John Doe",
29
- email: "john@example.com",
30
- phone: "+1234567890",
31
- countryCode: "US",
32
- });
33
-
34
- // Payment Methods
35
- const paymentMethod = await afriex.paymentMethods.create({
36
- customerId: customer.customerId,
37
- channel: "BANK_ACCOUNT",
38
- accountName: "John Doe",
39
- accountNumber: "1234567890",
40
- countryCode: "NG",
41
- institution: {
42
- institutionCode: "058",
43
- institutionName: "GTBank",
44
- },
28
+ fullName: 'Ada Obi',
29
+ email: 'ada@example.com',
30
+ phone: '+2348012345678',
31
+ countryCode: 'NG',
45
32
  });
46
33
 
47
- // Transactions
48
34
  const transaction = await afriex.transactions.create({
49
- customerId: customer.customerId,
50
- sourceAmount: "100",
51
- destinationAmount: "50000",
52
- sourceCurrency: "USD",
53
- destinationCurrency: "NGN",
54
- destinationId: paymentMethod.paymentMethodId,
55
- meta: {
56
- idempotencyKey: "quick-start-transaction-1",
57
- reference: "order-123",
58
- },
35
+ customerId: customer.customerId!,
36
+ destinationId: 'payment-method-id',
37
+ sourceAmount: '10',
38
+ sourceCurrency: 'USD',
39
+ destinationCurrency: 'NGN',
40
+ meta: {idempotencyKey: crypto.randomUUID(), reference: 'order-456'},
59
41
  });
42
+ ```
60
43
 
61
- // Rates
62
- const rate = await afriex.rates.getRate("USD", "NGN");
44
+ Every endpoint in the [API reference](https://docs.afriex.com/api-reference/introduction) has a method, grouped by resource: `customers`, `transactions`, `paymentMethods`, `paymentBatches`, `balance`, `rates`, `checkout`, `media`, `smeRegistration` and `webhooks`. Each endpoint page shows its SDK call.
63
45
 
64
- // Balance
65
- const balances = await afriex.balance.getBalance({
66
- currencies: ["USD", "NGN"],
67
- });
46
+ Keep your API key on your server. The SDK refuses to run in a browser.
68
47
 
69
- // Checkout - hosted payment page
70
- const session = await afriex.checkout.createSession({
71
- amount: 10000, // minor units, minimum 100
72
- currency: "USD",
73
- merchantReference: "order-123",
74
- redirectUrl: "https://example.com/checkout/complete",
75
- channels: ["VIRTUAL_BANK_ACCOUNT", "MOBILE_MONEY", "CARD"],
76
- customer: {
77
- name: "John Doe",
78
- email: "john@example.com",
79
- phone: "+1234567890",
80
- countryCode: "US",
81
- },
48
+ ## Configuration
49
+
50
+ | Option | Default | Description |
51
+ | :-- | :-- | :-- |
52
+ | `apiKey` | `AFRIEX_API_KEY` | Your API key, from **Developer → API keys** in the dashboard |
53
+ | `environment` | `'production'` | `'sandbox'` or `'production'`. `'staging'` also means the sandbox |
54
+ | `baseURL` | from `environment` | Overrides the base URL |
55
+ | `timeout` | `30000` | Milliseconds to wait for each attempt |
56
+ | `maxRetries` | `2` | Retries for a failed request. See [Retries](#retries) |
57
+ | `apiVersion` | `'2026-05-18'` | Sent as `x-api-version`. Each SDK release targets one API version |
58
+ | `webhookPublicKey` | none | Verifies webhook signatures. See [Webhooks](#webhooks) |
59
+ | `signRequest` | none | Returns the `x-api-signature` for a request, if your business has [request signing](https://docs.afriex.com/api-reference/authentication#request-signing) enabled |
60
+ | `defaultHeaders` | none | Headers sent with every request |
61
+ | `fetch` | global `fetch` | A `fetch` implementation to use instead |
62
+
63
+ `environment` defaults to production, so set it while you integrate.
64
+
65
+ ## Per-request options
66
+
67
+ Every method takes an options object last:
68
+
69
+ ```ts
70
+ const customer = await afriex.customers.get('customer-id', {
71
+ timeout: 5_000,
72
+ maxRetries: 0,
73
+ signal: AbortSignal.timeout(10_000),
74
+ headers: {'x-correlation-id': 'abc'},
82
75
  });
83
- // session.checkoutUrl, session.channels
76
+ ```
77
+
78
+ ## Errors
84
79
 
85
- // Webhook verification (requires webhookPublicKey)
86
- const isValid = afriex.webhooks.verify(payload, signature);
80
+ A failed request throws. A response outside 2xx throws an `APIError` subclass that carries the status, the API's error `code` and `details`, the response headers, and the `requestId` to quote to support:
81
+
82
+ | Status | Error |
83
+ | :-- | :-- |
84
+ | 400 | `BadRequestError` |
85
+ | 401 | `AuthenticationError` (wrong key, or a key without this endpoint's permission) |
86
+ | 403 | `PermissionDeniedError` |
87
+ | 404 | `NotFoundError` |
88
+ | 409 | `ConflictError` |
89
+ | 422 | `UnprocessableEntityError` |
90
+ | 429 | `RateLimitError`, with `retryAfter` in seconds |
91
+ | 500 and above | `InternalServerError` |
92
+ | no response | `APIConnectionError`, or `APIConnectionTimeoutError` after the timeout |
93
+ | you aborted | `APIUserAbortError` |
94
+
95
+ ```ts
96
+ import {APIError, ConflictError} from '@afriex/sdk';
97
+
98
+ try {
99
+ await afriex.transactions.create(params);
100
+ } catch (error) {
101
+ if (error instanceof ConflictError && error.code === 'DUPLICATE_REQUEST') {
102
+ // The idempotency key or reference is taken: look the transaction up.
103
+ const page = await afriex.transactions.list({reference: params.meta?.reference});
104
+ } else if (error instanceof APIError) {
105
+ console.error(error.status, error.code, error.requestId);
106
+ }
107
+ throw error;
108
+ }
87
109
  ```
88
110
 
89
- ## Available Services
111
+ Every error extends `AfriexError`.
90
112
 
91
- | Service | Description |
92
- | ----------------------- | ---------------------------------------------------------- |
93
- | `afriex.customers` | Customer CRUD, KYC updates, and document verification |
94
- | `afriex.transactions` | Create, authorize, list, and track transactions |
95
- | `afriex.paymentMethods` | Bank, mobile money, crypto wallets, virtual & pool accounts |
96
- | `afriex.paymentBatches` | Pay many recipients in one call |
97
- | `afriex.balance` | Organization wallet balances and sandbox top-ups |
98
- | `afriex.rates` | Exchange rates and conversions |
99
- | `afriex.checkout` | Hosted checkout sessions (card, virtual account, momo) |
100
- | `afriex.media` | Upload invoices, payment proofs and documents |
101
- | `afriex.smeRegistration` | Register the business for dedicated KES virtual accounts |
102
- | `afriex.webhooks` | Webhook signature verification and sandbox test triggers |
113
+ ## Retries
103
114
 
104
- Every service is always available on the client. `afriex.webhooks.verify()` returns `false`
105
- unless a `webhookPublicKey` was provided; `afriex.webhookVerifier` is set only when one was.
115
+ The SDK retries a request only when sending it again can't repeat its effect:
106
116
 
107
- ## Configuration
117
+ - **Every request on `429`.** The API rejects it before doing anything. The SDK waits for `Retry-After`.
118
+ - **`GET` requests,** and **`transactions.create`,** on a timeout, a dropped connection, `408` or a `5xx`. A transaction create is safe to send again because the API refuses a second request with the same `meta.idempotencyKey`. If the first attempt went through, the retry gets `409 DUPLICATE_REQUEST`: look the transaction up by its reference. See [Idempotency](https://docs.afriex.com/api-reference/idempotency).
108
119
 
109
- ```typescript
110
- interface AfriexSDKConfig {
111
- apiKey: string; // Required - Your Afriex API key
112
- environment?: "staging" | "production"; // Default: 'production'
113
- webhookPublicKey?: string; // Optional - Afriex's PEM public key for webhook verification
114
- customConfig?: { timeout?: number }; // Optional - override timeout
115
- logLevel?: LogLevel; // Default: LogLevel.ERROR
116
- enableLogging?: boolean; // Default: true
117
- retryConfig?: {
118
- maxRetries: number;
119
- retryDelay: number;
120
- retryableStatusCodes: number[]; // Default: [408, 429, 500, 502, 503, 504]
121
- retryableMethods?: HttpMethod[]; // Default: every method except POST and PATCH
122
- };
123
- apiVersion?: string; // Default: '2026-05-18', sent as x-api-version
124
- signRequest?: RequestSigner; // Optional - returns the x-api-signature value
125
- userAgent?: string; // Default: 'Afriex-TypeScript-SDK/<version of @afriex/sdk>'
120
+ Other `POST`, `PATCH` and `DELETE` requests are not retried on errors. The API has no idempotency key for them, so a retry could create a second customer or payment method.
121
+
122
+ Retries wait 0.5 seconds, doubling each time up to 8 seconds, with jitter. Set `maxRetries: 0` to turn them off.
123
+
124
+ ## Pagination
125
+
126
+ List methods return the first page as the API sends it, `{data, total, page}`:
127
+
128
+ ```ts
129
+ const page = await afriex.transactions.list({limit: 100, status: ['SUCCESS']});
130
+ console.log(page.data, page.total);
131
+ ```
132
+
133
+ Iterate the call with `for await` to walk every item across every page:
134
+
135
+ ```ts
136
+ for await (const transaction of afriex.transactions.list({limit: 100})) {
137
+ console.log(transaction.transactionId);
126
138
  }
127
139
  ```
128
140
 
129
- `SDK_VERSION` holds the version of `@afriex/sdk` that is installed.
141
+ A page also has `hasNextPage()`, `getNextPage()` and `iterPages()`.
130
142
 
131
- Retries are off by default. When they are on, `POST` and `PATCH` requests are
132
- still sent once unless `retryableMethods` lists them. See
133
- [`@afriex/core`](https://www.npmjs.com/package/@afriex/core) for retries and
134
- request signing.
143
+ ## Webhooks
135
144
 
136
- `staging` points at `https://sandbox.api.afriex.com/api/v1`, `production` at
137
- `https://api.afriex.com/api/v1`.
145
+ Verify a webhook before you act on it. The signature covers the exact bytes Afriex sent, so pass the raw body, not parsed JSON:
138
146
 
139
- ## Error Handling
147
+ ```ts
148
+ import express from 'express';
149
+ import {Afriex, WEBHOOK_SIGNATURE_HEADER, WebhookVerificationError} from '@afriex/sdk';
140
150
 
141
- All errors extend `AfriexError` and are re-exported from this package:
151
+ const afriex = new Afriex({webhookPublicKey: process.env.AFRIEX_WEBHOOK_PUBLIC_KEY});
152
+ const app = express();
142
153
 
143
- ```typescript
144
- import { AfriexError, ApiError, ValidationError, RateLimitError, NetworkError } from "@afriex/sdk";
154
+ app.post('/webhooks/afriex', express.raw({type: 'application/json'}), (req, res) => {
155
+ let event;
156
+ try {
157
+ event = afriex.webhooks.verifyAndParse(req.body, req.headers[WEBHOOK_SIGNATURE_HEADER]);
158
+ } catch (error) {
159
+ if (error instanceof WebhookVerificationError) return res.status(400).send('Invalid signature');
160
+ throw error;
161
+ }
145
162
 
146
- try {
147
- await afriex.transactions.create(request);
148
- } catch (error) {
149
- if (error instanceof ValidationError) {
150
- // Request failed local validation before being sent
151
- } else if (error instanceof RateLimitError) {
152
- // 429 - back off and retry
153
- } else if (error instanceof ApiError) {
154
- // Non-2xx response from the API
155
- } else if (error instanceof NetworkError) {
156
- // Connection/timeout failure
163
+ switch (event.event) {
164
+ case 'TRANSACTION.UPDATED':
165
+ console.log(event.data.transactionId, event.data.status);
166
+ break;
167
+ case 'CUSTOMER.CREATED':
168
+ console.log(event.data.customerId);
169
+ break;
157
170
  }
158
- }
171
+ res.sendStatus(200);
172
+ });
159
173
  ```
160
174
 
161
- ## Individual Packages
175
+ `event` is typed by its `event` name. `afriex.webhooks.verify()` returns a boolean instead of throwing. Store each event before you acknowledge it, keyed on `event.id`: see [Duplicates, ordering, and replays](https://docs.afriex.com/api-reference/endpoint/webhooks/introduction#duplicates-ordering-and-replays).
162
176
 
163
- For smaller bundle sizes, install packages individually:
177
+ ## The raw response
164
178
 
165
- | Package | Description |
166
- | ------------------------- | ------------------------------------------------------ |
167
- | `@afriex/core` | Base client, config, HTTP layer, errors, shared types |
168
- | `@afriex/customers` | Customer management and KYC |
169
- | `@afriex/transactions` | Transaction handling |
170
- | `@afriex/payment-methods` | Payment methods, institutions, virtual & pool accounts |
171
- | `@afriex/payment-batches` | Bulk payouts to a saved list of recipients |
172
- | `@afriex/balance` | Balance queries and sandbox top-ups |
173
- | `@afriex/rates` | Exchange rates and conversions |
174
- | `@afriex/checkout` | Hosted checkout sessions |
175
- | `@afriex/media` | File uploads |
176
- | `@afriex/sme-registration` | SME registration for KES virtual accounts |
177
- | `@afriex/webhooks` | Webhook verification and test triggers |
179
+ Every method returns an `APIPromise`. Call `withResponse()` for the HTTP response and its request id:
178
180
 
179
- Each service package depends only on `@afriex/core`, so you can mix and match.
181
+ ```ts
182
+ const {data: customer, response, requestId} = await afriex.customers.get('customer-id').withResponse();
183
+ ```
180
184
 
181
- ## AI agents
185
+ ## Types
182
186
 
183
- Every `@afriex/*` package ships [TanStack Intent](https://tanstack.com/intent) skills under
184
- `skills/`, so coding agents get grounded guidance on this SDK instead of guessing at the API.
185
- If you use an AI agent, run:
187
+ Request and response types are exported by name, such as `Customer`, `Transaction`, `TransactionCreateParams` and `WebhookEvent`. Every type in the spec is also available under the `OpenAPI` namespace:
186
188
 
187
- ```bash
188
- npx @tanstack/intent@latest install
189
+ ```ts
190
+ import type {OpenAPI} from '@afriex/sdk';
191
+ type Status = OpenAPI.components['schemas']['TransactionStatus'];
189
192
  ```
190
193
 
191
- List what is available with `npx @tanstack/intent@latest list`.
194
+ An endpoint the SDK doesn't cover yet can be called with `afriex.request('get', '/api/v1/...', {query})`.
195
+
196
+ ## Requirements
197
+
198
+ Node 20 or later. The SDK uses `fetch` and `node:crypto` (for webhooks), so it also runs on Bun, Deno, and edge runtimes with Node compatibility.
192
199
 
193
- ## Documentation
200
+ ## Versioning
194
201
 
195
- Full documentation available at [docs.afriex.com](https://docs.afriex.com/sdk/introduction)
202
+ The SDK follows [semantic versioning](https://semver.org). Each release targets the API version in `API_VERSION`. A change to the API that adds to it ships as a minor release; one that would break existing code ships as a major release. Releases are listed in the [changelog](https://docs.afriex.com/changelog), and [Upgrading from version 5](https://docs.afriex.com/sdk/introduction#upgrading-from-version-5) covers the move to 6.0.
196
203
 
197
- ## License
204
+ ## Support
198
205
 
199
- MIT
206
+ Full documentation is at [docs.afriex.com/sdk](https://docs.afriex.com/sdk/introduction). If something doesn't work as documented, email [support@afriex.com](mailto:support@afriex.com) with the `requestId` from the error.
@@ -0,0 +1,110 @@
1
+ import { APIPromise } from './core/api-promise.js';
2
+ import { PagePromise } from './core/pagination.js';
3
+ import type { RequestOptions } from './core/types.js';
4
+ import { Balance } from './resources/balance.js';
5
+ import { Checkout } from './resources/checkout.js';
6
+ import { Customers } from './resources/customers.js';
7
+ import { Media } from './resources/media.js';
8
+ import { PaymentBatches } from './resources/payment-batches.js';
9
+ import { PaymentMethods } from './resources/payment-methods.js';
10
+ import { Rates } from './resources/rates.js';
11
+ import { SmeRegistration } from './resources/sme-registration.js';
12
+ import { Transactions } from './resources/transactions.js';
13
+ import { Webhooks } from './resources/webhooks.js';
14
+ /** The base URL of each environment. `staging` is the sandbox's older name. */
15
+ export declare const ENVIRONMENTS: {
16
+ readonly sandbox: "https://sandbox.api.afriex.com";
17
+ readonly staging: "https://sandbox.api.afriex.com";
18
+ readonly production: "https://api.afriex.com";
19
+ };
20
+ export type Environment = keyof typeof ENVIRONMENTS;
21
+ /**
22
+ * The API version this release of the SDK was built against, sent as
23
+ * `x-api-version`. Each SDK release targets one API version.
24
+ */
25
+ export declare const API_VERSION = "2026-05-18";
26
+ /** What `signRequest` receives: the request exactly as it will be sent. */
27
+ export interface SignableRequest {
28
+ method: string;
29
+ url: string;
30
+ body: string;
31
+ }
32
+ export interface ClientOptions {
33
+ /** Your Afriex API key. Defaults to the `AFRIEX_API_KEY` environment variable. */
34
+ apiKey?: string;
35
+ /**
36
+ * `'sandbox'` or `'production'`. Defaults to `'production'`, so set it
37
+ * explicitly while you integrate. `'staging'` is accepted as the sandbox.
38
+ */
39
+ environment?: Environment;
40
+ /** Overrides the base URL that `environment` selects. */
41
+ baseURL?: string;
42
+ /** Sent as `x-api-version`. Defaults to `API_VERSION`. */
43
+ apiVersion?: string;
44
+ /** Milliseconds to wait for each attempt. Defaults to 30 seconds. */
45
+ timeout?: number;
46
+ /**
47
+ * How many times to retry a failed request. Defaults to 2. See the README
48
+ * for which requests are retried.
49
+ */
50
+ maxRetries?: number;
51
+ /**
52
+ * Returns the `x-api-signature` for a request, if your business has request
53
+ * signing enabled.
54
+ */
55
+ signRequest?: (request: SignableRequest) => string | undefined | Promise<string | undefined>;
56
+ /** Afriex's public key for webhook signatures, from **Developer → Webhook** in the dashboard. */
57
+ webhookPublicKey?: string;
58
+ /** Headers sent with every request. */
59
+ defaultHeaders?: Record<string, string>;
60
+ /** A `fetch` implementation to use instead of the global one. */
61
+ fetch?: typeof fetch;
62
+ /**
63
+ * The SDK refuses to run in a browser, where your API key would be visible
64
+ * to anyone. Set this only if you understand that.
65
+ */
66
+ dangerouslyAllowBrowser?: boolean;
67
+ }
68
+ type Method = 'get' | 'post' | 'patch' | 'delete';
69
+ export interface APIRequestInit {
70
+ query?: object;
71
+ body?: unknown;
72
+ /**
73
+ * Safe to send twice: retried on timeouts and server errors as well as on
74
+ * 429. True for every GET; set it for a POST whose body carries an
75
+ * idempotency key.
76
+ */
77
+ idempotent?: boolean;
78
+ options?: RequestOptions;
79
+ }
80
+ export declare class Afriex {
81
+ #private;
82
+ readonly customers: Customers;
83
+ readonly transactions: Transactions;
84
+ readonly paymentMethods: PaymentMethods;
85
+ readonly paymentBatches: PaymentBatches;
86
+ readonly balance: Balance;
87
+ readonly rates: Rates;
88
+ readonly checkout: Checkout;
89
+ readonly media: Media;
90
+ readonly smeRegistration: SmeRegistration;
91
+ readonly webhooks: Webhooks;
92
+ readonly baseURL: string;
93
+ readonly apiVersion: string;
94
+ readonly timeout: number;
95
+ readonly maxRetries: number;
96
+ constructor(options?: ClientOptions);
97
+ /**
98
+ * Sends a request and returns the parsed JSON body. The resource methods
99
+ * call this; use it yourself only for an endpoint they don't cover yet.
100
+ */
101
+ request<T>(method: Method, path: string, init?: APIRequestInit): APIPromise<T>;
102
+ /** @internal Fetches one page of a list endpoint. */
103
+ getPage<Item>(path: string, query?: {
104
+ page?: number;
105
+ limit?: number;
106
+ } & object, options?: RequestOptions): PagePromise<Item>;
107
+ /** @internal Sends a request with the configured `fetch`, without the API key. For presigned upload URLs. */
108
+ fetchUnauthenticated(url: string, init: RequestInit): Promise<Response>;
109
+ }
110
+ export {};