@inkress/admin-sdk 1.0.0 → 1.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.
- package/CHANGELOG.md +213 -0
- package/README.md +1174 -87
- package/dist/client.d.ts +3 -3
- package/dist/client.d.ts.map +1 -1
- package/dist/data-mappings.d.ts +177 -0
- package/dist/data-mappings.d.ts.map +1 -0
- package/dist/index.d.ts +34 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +4166 -154
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +4203 -153
- package/dist/index.js.map +1 -1
- package/dist/resources/addresses.d.ts +58 -0
- package/dist/resources/addresses.d.ts.map +1 -0
- package/dist/resources/billing-plans.d.ts +32 -15
- package/dist/resources/billing-plans.d.ts.map +1 -1
- package/dist/resources/categories.d.ts +30 -20
- package/dist/resources/categories.d.ts.map +1 -1
- package/dist/resources/currencies.d.ts +41 -0
- package/dist/resources/currencies.d.ts.map +1 -0
- package/dist/resources/exchange-rates.d.ts +50 -0
- package/dist/resources/exchange-rates.d.ts.map +1 -0
- package/dist/resources/fees.d.ts +58 -0
- package/dist/resources/fees.d.ts.map +1 -0
- package/dist/resources/financial-accounts.d.ts +47 -0
- package/dist/resources/financial-accounts.d.ts.map +1 -0
- package/dist/resources/financial-requests.d.ts +51 -0
- package/dist/resources/financial-requests.d.ts.map +1 -0
- package/dist/resources/generics.d.ts +57 -0
- package/dist/resources/generics.d.ts.map +1 -0
- package/dist/resources/kyc.d.ts +118 -0
- package/dist/resources/kyc.d.ts.map +1 -0
- package/dist/resources/merchants.d.ts +52 -15
- package/dist/resources/merchants.d.ts.map +1 -1
- package/dist/resources/orders.d.ts +74 -2
- package/dist/resources/orders.d.ts.map +1 -1
- package/dist/resources/payment-links.d.ts +65 -0
- package/dist/resources/payment-links.d.ts.map +1 -0
- package/dist/resources/payment-methods.d.ts +48 -0
- package/dist/resources/payment-methods.d.ts.map +1 -0
- package/dist/resources/products.d.ts +62 -16
- package/dist/resources/products.d.ts.map +1 -1
- package/dist/resources/public.d.ts +27 -7
- package/dist/resources/public.d.ts.map +1 -1
- package/dist/resources/subscriptions.d.ts +86 -20
- package/dist/resources/subscriptions.d.ts.map +1 -1
- package/dist/resources/tokens.d.ts +62 -0
- package/dist/resources/tokens.d.ts.map +1 -0
- package/dist/resources/transaction-entries.d.ts +48 -0
- package/dist/resources/transaction-entries.d.ts.map +1 -0
- package/dist/resources/users.d.ts +43 -21
- package/dist/resources/users.d.ts.map +1 -1
- package/dist/resources/webhook-urls.d.ts +49 -0
- package/dist/resources/webhook-urls.d.ts.map +1 -0
- package/dist/types/resources.d.ts +1294 -0
- package/dist/types/resources.d.ts.map +1 -0
- package/dist/types.d.ts +1069 -197
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/query-builders.d.ts +518 -0
- package/dist/utils/query-builders.d.ts.map +1 -0
- package/dist/utils/query-transformer.d.ts +123 -0
- package/dist/utils/query-transformer.d.ts.map +1 -0
- package/dist/utils/translators.d.ts +126 -0
- package/dist/utils/translators.d.ts.map +1 -0
- package/dist/utils/webhooks.d.ts +19 -4
- package/dist/utils/webhooks.d.ts.map +1 -1
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -11,7 +11,10 @@ Official Inkress Commerce API SDK for JavaScript/TypeScript applications.
|
|
|
11
11
|
- 🚀 **Modern TypeScript SDK** - Built with TypeScript for excellent developer experience
|
|
12
12
|
- 🔒 **Secure Authentication** - JWT-based authentication with automatic token management
|
|
13
13
|
- 🌐 **Public Endpoints** - Access public merchant information without authentication
|
|
14
|
-
- 📦 **Comprehensive API Coverage** -
|
|
14
|
+
- 📦 **Comprehensive API Coverage** - 23+ resources with full CRUD operations
|
|
15
|
+
- 🎯 **100% Type-Safe** - Every method fully typed with specific interfaces
|
|
16
|
+
- 🔄 **Advanced Query System** - Fluent query builder with intelligent transformations
|
|
17
|
+
- 🌍 **Contextual Translations** - Human-readable strings automatically converted to API integers
|
|
15
18
|
- 🛠️ **Easy Integration** - Simple setup and intuitive API design
|
|
16
19
|
- 🔄 **Automatic Retries** - Built-in retry logic for resilient applications
|
|
17
20
|
- 📱 **Cross-Platform** - Works in Node.js, browsers, and React Native
|
|
@@ -38,12 +41,77 @@ pnpm add @inkress/admin-sdk
|
|
|
38
41
|
import { InkressSDK } from '@inkress/admin-sdk';
|
|
39
42
|
|
|
40
43
|
const inkress = new InkressSDK({
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
accessToken: 'your-jwt-token',
|
|
45
|
+
username: 'merchant-username', // Optional - automatically prepended with 'm-'
|
|
46
|
+
mode: 'live', // Optional - 'live' (default) or 'sandbox'
|
|
44
47
|
});
|
|
45
48
|
```
|
|
46
49
|
|
|
50
|
+
### Configuration Options
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const inkress = new InkressSDK({
|
|
54
|
+
// Required
|
|
55
|
+
accessToken: 'your-jwt-token',
|
|
56
|
+
|
|
57
|
+
// Optional
|
|
58
|
+
username: 'merchant-username', // Prepended with 'm-' for Client-Id header
|
|
59
|
+
mode: 'live', // 'live' = api.inkress.com, 'sandbox' = api-dev.inkress.com
|
|
60
|
+
apiVersion: 'v1', // API version (default: 'v1')
|
|
61
|
+
timeout: 30000, // Request timeout in ms (default: 30000)
|
|
62
|
+
retries: 3, // Number of retry attempts (default: 0)
|
|
63
|
+
headers: { // Custom headers for all requests
|
|
64
|
+
'X-Custom-Header': 'value'
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Why This SDK?
|
|
70
|
+
|
|
71
|
+
**🎯 100% Type-Safe** - Every single method across all 23 resources is fully typed:
|
|
72
|
+
```typescript
|
|
73
|
+
// Every parameter and return value has explicit types
|
|
74
|
+
const balances: ApiResponse<MerchantBalance> = await inkress.merchants.balances();
|
|
75
|
+
// balances.data: { available: number, pending: number, currency: string }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**🌍 Human-Readable API** - Use contextual strings instead of cryptic integers:
|
|
79
|
+
```typescript
|
|
80
|
+
// Clear, self-documenting code with contextual strings
|
|
81
|
+
await inkress.orders.update(123, {
|
|
82
|
+
status: 'confirmed',
|
|
83
|
+
kind: 'online'
|
|
84
|
+
});
|
|
85
|
+
// SDK automatically converts to integers for the API
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**🔍 Powerful Queries** - Intuitive query syntax or fluent builders:
|
|
89
|
+
```typescript
|
|
90
|
+
// Direct query syntax
|
|
91
|
+
await inkress.orders.query({
|
|
92
|
+
status: ['confirmed', 'shipped'],
|
|
93
|
+
total: { min: 100, max: 1000 },
|
|
94
|
+
reference_id: { contains: 'VIP' }
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Fluent query builder
|
|
98
|
+
await inkress.orders.createQueryBuilder()
|
|
99
|
+
.whereStatus(['confirmed', 'shipped'])
|
|
100
|
+
.whereTotalRange(100, 1000)
|
|
101
|
+
.whereReferenceContains('VIP')
|
|
102
|
+
.execute();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**📦 Complete Coverage** - 22 resources with 125+ fully-typed methods:
|
|
106
|
+
- Core: Merchants, Products, Categories, Orders, Users
|
|
107
|
+
- Billing: Plans, Subscriptions, Payment Links, Payment Methods
|
|
108
|
+
- Financial: Accounts, Requests, Fees, Currencies, Exchange Rates
|
|
109
|
+
- Identity: Addresses, Tokens, Webhooks
|
|
110
|
+
- Content: Public Data
|
|
111
|
+
- And more...
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
47
115
|
### Public Endpoints (No Authentication Required)
|
|
48
116
|
|
|
49
117
|
```typescript
|
|
@@ -60,41 +128,73 @@ const products = await inkress.public.getMerchantProducts('merchant-username', {
|
|
|
60
128
|
|
|
61
129
|
// Get merchant fees
|
|
62
130
|
const fees = await inkress.public.getMerchantFees('merchant-username', {
|
|
63
|
-
|
|
64
|
-
|
|
131
|
+
currency: 'JMD',
|
|
132
|
+
total: 1000
|
|
65
133
|
});
|
|
66
134
|
```
|
|
67
135
|
|
|
68
|
-
### Authenticated Operations
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
// List categories
|
|
72
|
-
const categories = await inkress.categories.list({ kind: 1 });
|
|
136
|
+
### Authenticated Operations with Contextual Values
|
|
73
137
|
|
|
74
|
-
|
|
75
|
-
const category = await inkress.categories.create({
|
|
76
|
-
name: 'Electronics',
|
|
77
|
-
description: 'Electronic devices and accessories',
|
|
78
|
-
kind: 1
|
|
79
|
-
});
|
|
138
|
+
The SDK automatically translates human-readable strings to API integers:
|
|
80
139
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
limit: 50,
|
|
84
|
-
category_id: 1
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Create an order
|
|
140
|
+
```typescript
|
|
141
|
+
// Create order with contextual strings
|
|
88
142
|
const order = await inkress.orders.create({
|
|
143
|
+
total: 99.99,
|
|
89
144
|
currency_code: 'USD',
|
|
145
|
+
status: 'pending', // SDK converts 'pending' → integer
|
|
146
|
+
kind: 'online', // SDK converts 'online' → integer
|
|
90
147
|
customer: {
|
|
91
148
|
email: 'customer@example.com',
|
|
92
149
|
first_name: 'John',
|
|
93
150
|
last_name: 'Doe'
|
|
94
151
|
},
|
|
95
|
-
total: 29.99,
|
|
96
152
|
reference_id: 'order-123'
|
|
97
153
|
});
|
|
154
|
+
|
|
155
|
+
// Update merchant with contextual values
|
|
156
|
+
const merchant = await inkress.merchants.update(123, {
|
|
157
|
+
status: 'approved', // SDK converts to integer
|
|
158
|
+
platform_fee_structure: 'customer_pay', // SDK converts to integer
|
|
159
|
+
provider_fee_structure: 'merchant_absorb'
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Create user with contextual status and kind
|
|
163
|
+
const user = await inkress.users.create({
|
|
164
|
+
email: 'user@example.com',
|
|
165
|
+
first_name: 'John',
|
|
166
|
+
last_name: 'Doe',
|
|
167
|
+
password: 'secure-password',
|
|
168
|
+
status: 'pending', // SDK converts to account_pending integer
|
|
169
|
+
kind: 'organisation' // SDK converts to user_organisation integer
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Advanced Query System
|
|
174
|
+
|
|
175
|
+
Use the intuitive query system for powerful filtering:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
// Query with multiple conditions
|
|
179
|
+
const orders = await inkress.orders.query({
|
|
180
|
+
status: ['confirmed', 'shipped'], // Array → IN query
|
|
181
|
+
total: { min: 100, max: 1000 }, // Range query
|
|
182
|
+
reference_id: { contains: 'VIP' }, // String search
|
|
183
|
+
inserted_at: { after: '2024-01-01' },
|
|
184
|
+
page: 1,
|
|
185
|
+
page_size: 20
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Or use fluent query builder
|
|
189
|
+
const products = await inkress.products
|
|
190
|
+
.createQueryBuilder()
|
|
191
|
+
.whereStatus('published')
|
|
192
|
+
.wherePriceRange(50, 500)
|
|
193
|
+
.whereTitleContains('laptop')
|
|
194
|
+
.whereCategory(5)
|
|
195
|
+
.paginate(1, 20)
|
|
196
|
+
.orderBy('price', 'desc')
|
|
197
|
+
.execute();
|
|
98
198
|
```
|
|
99
199
|
|
|
100
200
|
## Configuration Options
|
|
@@ -111,179 +211,925 @@ const order = await inkress.orders.create({
|
|
|
111
211
|
|
|
112
212
|
## API Resources
|
|
113
213
|
|
|
114
|
-
|
|
214
|
+
The SDK provides access to 23+ fully-typed resources:
|
|
215
|
+
|
|
216
|
+
### Core Resources
|
|
217
|
+
- **Merchants** - Merchant management and account operations
|
|
218
|
+
- **Products** - Product catalog with full CRUD
|
|
219
|
+
- **Categories** - Product categorization
|
|
220
|
+
- **Orders** - Order processing and tracking
|
|
221
|
+
- **Users** - User and account management
|
|
222
|
+
|
|
223
|
+
### Billing & Subscriptions
|
|
224
|
+
- **Billing Plans** - Subscription plan management
|
|
225
|
+
- **Subscriptions** - Recurring billing and subscriptions
|
|
226
|
+
- **Payment Links** - Payment link generation
|
|
227
|
+
- **Payment Methods** - Payment method configuration
|
|
228
|
+
|
|
229
|
+
### Financial
|
|
230
|
+
- **Financial Accounts** - Account management
|
|
231
|
+
- **Financial Requests** - Payout and withdrawal requests
|
|
232
|
+
- **Transaction Entries** - Transaction tracking
|
|
233
|
+
- **Fees** - Fee management and configuration
|
|
234
|
+
- **Exchange Rates** - Currency exchange rates
|
|
235
|
+
- **Currencies** - Multi-currency support
|
|
236
|
+
|
|
237
|
+
### Identity & Access
|
|
238
|
+
- **Addresses** - Address management
|
|
239
|
+
- **Tokens** - API token management
|
|
240
|
+
- **Webhook URLs** - Webhook configuration
|
|
241
|
+
|
|
242
|
+
### Content & Other
|
|
243
|
+
- **Generics** - Dynamic endpoint access
|
|
244
|
+
- **KYC** - Know Your Customer operations
|
|
245
|
+
- **Payout** - Payout processing
|
|
246
|
+
- **Public** - Public-facing merchant data
|
|
115
247
|
|
|
116
|
-
|
|
248
|
+
---
|
|
117
249
|
|
|
118
|
-
|
|
119
|
-
// Get merchant by username or domain
|
|
120
|
-
await inkress.public.getMerchant({ username: 'merchant-name' });
|
|
121
|
-
await inkress.public.getMerchant({ 'domain.cname': 'store.example.com' });
|
|
250
|
+
## Core Resource Examples
|
|
122
251
|
|
|
123
|
-
|
|
124
|
-
await inkress.public.getMerchantProducts('merchant-name', {
|
|
125
|
-
search: 'laptop',
|
|
126
|
-
category: 'electronics',
|
|
127
|
-
limit: 20
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Get merchant fees
|
|
131
|
-
await inkress.public.getMerchantFees('merchant-name');
|
|
132
|
-
```
|
|
252
|
+
### Merchants Resource
|
|
133
253
|
|
|
134
254
|
### Merchants Resource
|
|
135
255
|
|
|
256
|
+
Full merchant management with contextual translations and account methods:
|
|
257
|
+
|
|
136
258
|
```typescript
|
|
137
|
-
// List merchants
|
|
138
|
-
await inkress.merchants.list(
|
|
259
|
+
// List merchants with contextual filtering
|
|
260
|
+
const merchants = await inkress.merchants.list({
|
|
261
|
+
status: 'approved', // Contextual: converts to integer
|
|
262
|
+
platform_fee_structure: 'customer_pay',
|
|
263
|
+
organisation_id: 123,
|
|
264
|
+
q: 'coffee shop'
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Query merchants with advanced filtering
|
|
268
|
+
const merchants = await inkress.merchants.query({
|
|
269
|
+
status: ['approved', 'active'],
|
|
270
|
+
platform_fee_structure: 'customer_pay',
|
|
271
|
+
inserted_at: { after: '2024-01-01' }
|
|
272
|
+
});
|
|
139
273
|
|
|
140
274
|
// Get merchant details
|
|
141
|
-
await inkress.merchants.get(merchantId);
|
|
275
|
+
const merchant = await inkress.merchants.get(merchantId);
|
|
276
|
+
|
|
277
|
+
// Create merchant with contextual values
|
|
278
|
+
const newMerchant = await inkress.merchants.create({
|
|
279
|
+
name: 'My Store',
|
|
280
|
+
email: 'store@example.com',
|
|
281
|
+
username: 'mystore',
|
|
282
|
+
status: 'pending', // Contextual
|
|
283
|
+
platform_fee_structure: 'customer_pay',
|
|
284
|
+
provider_fee_structure: 'merchant_absorb'
|
|
285
|
+
});
|
|
142
286
|
|
|
143
287
|
// Update merchant
|
|
144
|
-
await inkress.merchants.update(merchantId, {
|
|
288
|
+
await inkress.merchants.update(merchantId, {
|
|
289
|
+
name: 'Updated Store Name',
|
|
290
|
+
status: 'approved'
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Merchant account methods (properly typed)
|
|
294
|
+
const balances = await inkress.merchants.balances();
|
|
295
|
+
// Returns: { available: number, pending: number, currency: string }
|
|
296
|
+
|
|
297
|
+
const limits = await inkress.merchants.limits();
|
|
298
|
+
// Returns: { transaction_limit: number, daily_limit: number, monthly_limit: number, currency: string }
|
|
299
|
+
|
|
300
|
+
const subscription = await inkress.merchants.subscription();
|
|
301
|
+
// Returns: { plan_name: string, status: string, billing_cycle: string, price: number, ... }
|
|
302
|
+
|
|
303
|
+
const invoices = await inkress.merchants.invoices();
|
|
304
|
+
// Returns: MerchantInvoice[]
|
|
305
|
+
|
|
306
|
+
const invoice = await inkress.merchants.invoice('invoice-123');
|
|
307
|
+
// Returns: MerchantInvoice
|
|
308
|
+
|
|
309
|
+
// Query builder
|
|
310
|
+
const merchants = await inkress.merchants
|
|
311
|
+
.createQueryBuilder()
|
|
312
|
+
.whereStatus('approved')
|
|
313
|
+
.wherePlatformFeeStructure('customer_pay')
|
|
314
|
+
.whereOrganisation(123)
|
|
315
|
+
.search('electronics')
|
|
316
|
+
.execute();
|
|
145
317
|
```
|
|
146
318
|
|
|
147
319
|
### Products Resource
|
|
148
320
|
|
|
321
|
+
Complete product management with status translations and advanced querying:
|
|
322
|
+
|
|
149
323
|
```typescript
|
|
150
|
-
// List products with
|
|
324
|
+
// List products with contextual filtering
|
|
151
325
|
await inkress.products.list({
|
|
152
|
-
|
|
153
|
-
per_page: 50,
|
|
326
|
+
status: 'published', // Contextual: 'published' instead of integer
|
|
154
327
|
category_id: 1,
|
|
155
|
-
|
|
328
|
+
price: { min: 50, max: 500 },
|
|
329
|
+
q: 'laptop'
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
// Query products with advanced filters
|
|
333
|
+
const products = await inkress.products.query({
|
|
334
|
+
status: ['published', 'featured'], // Array query
|
|
335
|
+
category_id: [1, 2, 3],
|
|
336
|
+
price: { min: 100 },
|
|
337
|
+
title: { contains: 'gaming' },
|
|
338
|
+
inserted_at: { after: '2024-01-01' }
|
|
156
339
|
});
|
|
157
340
|
|
|
158
341
|
// Get product details
|
|
159
342
|
await inkress.products.get(productId);
|
|
160
343
|
|
|
161
|
-
// Create
|
|
344
|
+
// Create product with contextual status
|
|
162
345
|
await inkress.products.create({
|
|
163
346
|
name: 'Gaming Laptop',
|
|
164
347
|
description: 'High-performance gaming laptop',
|
|
165
348
|
price: 1299.99,
|
|
166
|
-
category_id: 1
|
|
349
|
+
category_id: 1,
|
|
350
|
+
status: 'draft', // Contextual
|
|
351
|
+
kind: 'published' // Contextual
|
|
167
352
|
});
|
|
168
353
|
|
|
169
354
|
// Update product
|
|
170
|
-
await inkress.products.update(productId, {
|
|
355
|
+
await inkress.products.update(productId, {
|
|
356
|
+
price: 1199.99,
|
|
357
|
+
status: 'published' // Contextual translation
|
|
358
|
+
});
|
|
171
359
|
|
|
172
360
|
// Delete product
|
|
173
361
|
await inkress.products.delete(productId);
|
|
362
|
+
|
|
363
|
+
// Query builder
|
|
364
|
+
const products = await inkress.products
|
|
365
|
+
.createQueryBuilder()
|
|
366
|
+
.whereStatus('published')
|
|
367
|
+
.wherePriceRange(50, 500)
|
|
368
|
+
.whereCategory(5)
|
|
369
|
+
.whereTitleContains('laptop')
|
|
370
|
+
.paginate(1, 20)
|
|
371
|
+
.orderBy('price', 'desc')
|
|
372
|
+
.search('gaming')
|
|
373
|
+
.execute();
|
|
174
374
|
```
|
|
175
375
|
|
|
176
376
|
### Categories Resource
|
|
177
377
|
|
|
378
|
+
Category management with kind translations:
|
|
379
|
+
|
|
178
380
|
```typescript
|
|
179
|
-
// List categories
|
|
180
|
-
await inkress.categories.list({
|
|
381
|
+
// List categories with contextual filtering
|
|
382
|
+
await inkress.categories.list({
|
|
383
|
+
kind: 'published', // Contextual translation
|
|
384
|
+
q: 'electronics'
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Query categories
|
|
388
|
+
const categories = await inkress.categories.query({
|
|
389
|
+
kind: ['published', 'featured'],
|
|
390
|
+
parent_id: 1
|
|
391
|
+
});
|
|
181
392
|
|
|
182
393
|
// Get category details
|
|
183
394
|
await inkress.categories.get(categoryId);
|
|
184
395
|
|
|
185
|
-
// Create category
|
|
396
|
+
// Create category with contextual kind
|
|
186
397
|
await inkress.categories.create({
|
|
187
398
|
name: 'Electronics',
|
|
188
399
|
description: 'Electronic devices',
|
|
189
|
-
kind:
|
|
400
|
+
kind: 'published', // Contextual
|
|
401
|
+
parent_id: null
|
|
190
402
|
});
|
|
191
403
|
|
|
192
404
|
// Update category
|
|
193
|
-
await inkress.categories.update(categoryId, {
|
|
405
|
+
await inkress.categories.update(categoryId, {
|
|
406
|
+
name: 'Updated Name',
|
|
407
|
+
kind: 'featured' // Contextual
|
|
408
|
+
});
|
|
194
409
|
|
|
195
|
-
//
|
|
196
|
-
await inkress.categories
|
|
410
|
+
// Query builder
|
|
411
|
+
const categories = await inkress.categories
|
|
412
|
+
.createQueryBuilder()
|
|
413
|
+
.whereKind('published')
|
|
414
|
+
.whereParent(1)
|
|
415
|
+
.search('electronics')
|
|
416
|
+
.execute();
|
|
197
417
|
```
|
|
198
418
|
|
|
199
419
|
### Orders Resource
|
|
200
420
|
|
|
421
|
+
Order processing with full status and kind translations:
|
|
422
|
+
|
|
201
423
|
```typescript
|
|
202
|
-
// Create
|
|
424
|
+
// Create order with contextual strings
|
|
203
425
|
await inkress.orders.create({
|
|
426
|
+
total: 99.99,
|
|
204
427
|
currency_code: 'USD',
|
|
205
428
|
customer: {
|
|
206
429
|
email: 'customer@example.com',
|
|
207
430
|
first_name: 'John',
|
|
208
431
|
last_name: 'Doe'
|
|
209
432
|
},
|
|
210
|
-
total: 99.99,
|
|
211
433
|
reference_id: 'order-123',
|
|
212
|
-
kind: 'online'
|
|
434
|
+
kind: 'online', // Contextual: converts to integer
|
|
435
|
+
status: 'pending' // Contextual: converts to integer
|
|
213
436
|
});
|
|
214
437
|
|
|
215
438
|
// Get order details
|
|
216
439
|
await inkress.orders.get(orderId);
|
|
217
440
|
|
|
218
|
-
// Update order status
|
|
219
|
-
await inkress.orders.update(orderId, {
|
|
441
|
+
// Update order status with contextual string
|
|
442
|
+
await inkress.orders.update(orderId, {
|
|
443
|
+
status: 'confirmed' // Contextual translation
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
// List orders with contextual filtering
|
|
447
|
+
await inkress.orders.list({
|
|
448
|
+
status: 'shipped', // Contextual
|
|
449
|
+
kind: 'online', // Contextual
|
|
450
|
+
customer_id: 123,
|
|
451
|
+
q: 'electronics'
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Query orders with advanced filters
|
|
455
|
+
const orders = await inkress.orders.query({
|
|
456
|
+
status: ['confirmed', 'shipped'],
|
|
457
|
+
kind: ['online', 'subscription'],
|
|
458
|
+
total: { min: 100, max: 1000 },
|
|
459
|
+
reference_id: { contains: 'VIP' },
|
|
460
|
+
inserted_at: { after: '2024-01-01' }
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// Delete order
|
|
464
|
+
await inkress.orders.delete(orderId);
|
|
220
465
|
|
|
221
466
|
// Get order status (public endpoint)
|
|
222
467
|
await inkress.orders.getStatus(orderId);
|
|
223
468
|
|
|
224
|
-
//
|
|
225
|
-
await inkress.orders
|
|
469
|
+
// Query builder
|
|
470
|
+
const orders = await inkress.orders
|
|
471
|
+
.createQueryBuilder()
|
|
472
|
+
.whereStatus(['confirmed', 'shipped'])
|
|
473
|
+
.whereKind('online')
|
|
474
|
+
.whereTotalRange(100, 1000)
|
|
475
|
+
.whereReferenceContains('PREMIUM')
|
|
476
|
+
.whereCustomer(123)
|
|
477
|
+
.paginate(1, 20)
|
|
478
|
+
.execute();
|
|
226
479
|
```
|
|
227
480
|
|
|
228
481
|
### Users Resource
|
|
229
482
|
|
|
483
|
+
User management with status and kind translations:
|
|
484
|
+
|
|
230
485
|
```typescript
|
|
231
|
-
// List users
|
|
232
|
-
await inkress.users.list(
|
|
486
|
+
// List users with contextual filtering
|
|
487
|
+
await inkress.users.list({
|
|
488
|
+
status: 'approved', // Contextual: account_approved
|
|
489
|
+
kind: 'organisation', // Contextual: user_organisation
|
|
490
|
+
organisation_id: 123,
|
|
491
|
+
q: 'admin'
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// Query users
|
|
495
|
+
const users = await inkress.users.query({
|
|
496
|
+
status: ['approved', 'active'],
|
|
497
|
+
kind: ['organisation', 'merchant'],
|
|
498
|
+
inserted_at: { after: '2024-01-01' }
|
|
499
|
+
});
|
|
233
500
|
|
|
234
501
|
// Get user details
|
|
235
502
|
await inkress.users.get(userId);
|
|
236
503
|
|
|
237
|
-
// Create user
|
|
504
|
+
// Create user with contextual values
|
|
238
505
|
await inkress.users.create({
|
|
239
506
|
email: 'user@example.com',
|
|
240
507
|
first_name: 'John',
|
|
241
508
|
last_name: 'Doe',
|
|
242
|
-
|
|
509
|
+
password: 'secure-password',
|
|
510
|
+
status: 'pending', // Contextual
|
|
511
|
+
kind: 'organisation' // Contextual
|
|
243
512
|
});
|
|
244
513
|
|
|
245
|
-
// Update user
|
|
246
|
-
await inkress.users.update(userId, {
|
|
514
|
+
// Update user with contextual status
|
|
515
|
+
await inkress.users.update(userId, {
|
|
516
|
+
first_name: 'Jane',
|
|
517
|
+
status: 'approved' // Contextual
|
|
518
|
+
});
|
|
247
519
|
|
|
248
520
|
// Delete user
|
|
249
521
|
await inkress.users.delete(userId);
|
|
522
|
+
|
|
523
|
+
// Query builder
|
|
524
|
+
const users = await inkress.users
|
|
525
|
+
.createQueryBuilder()
|
|
526
|
+
.whereStatus('approved')
|
|
527
|
+
.whereKind('organisation')
|
|
528
|
+
.whereOrganisation(123)
|
|
529
|
+
.search('john')
|
|
530
|
+
.execute();
|
|
250
531
|
```
|
|
251
532
|
|
|
252
533
|
### Billing Plans Resource
|
|
253
534
|
|
|
535
|
+
Billing plan management with kind translations:
|
|
536
|
+
|
|
254
537
|
```typescript
|
|
255
538
|
// List billing plans
|
|
256
|
-
await inkress.billingPlans.list(
|
|
539
|
+
await inkress.billingPlans.list({
|
|
540
|
+
kind: 'subscription', // Contextual
|
|
541
|
+
status: 'active'
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
// Query plans
|
|
545
|
+
const plans = await inkress.billingPlans.query({
|
|
546
|
+
kind: 'subscription',
|
|
547
|
+
public: true,
|
|
548
|
+
amount: { min: 10, max: 100 }
|
|
549
|
+
});
|
|
257
550
|
|
|
258
551
|
// Get plan details
|
|
259
552
|
await inkress.billingPlans.get(planId);
|
|
260
553
|
|
|
261
|
-
// Create billing plan
|
|
554
|
+
// Create billing plan with contextual kind
|
|
262
555
|
await inkress.billingPlans.create({
|
|
263
556
|
name: 'Premium Plan',
|
|
264
557
|
amount: 29.99,
|
|
265
|
-
currency: 'USD'
|
|
558
|
+
currency: 'USD',
|
|
559
|
+
kind: 'subscription', // Contextual
|
|
560
|
+
status: 'active'
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Update plan
|
|
564
|
+
await inkress.billingPlans.update(planId, {
|
|
565
|
+
amount: 24.99,
|
|
566
|
+
status: 'active'
|
|
266
567
|
});
|
|
568
|
+
|
|
569
|
+
// Delete plan
|
|
570
|
+
await inkress.billingPlans.delete(planId);
|
|
571
|
+
|
|
572
|
+
// Query builder
|
|
573
|
+
const plans = await inkress.billingPlans
|
|
574
|
+
.createQueryBuilder()
|
|
575
|
+
.whereKind('subscription')
|
|
576
|
+
.wherePublic(true)
|
|
577
|
+
.whereAmountRange(10, 50)
|
|
578
|
+
.execute();
|
|
267
579
|
```
|
|
268
580
|
|
|
269
581
|
### Subscriptions Resource
|
|
270
582
|
|
|
583
|
+
Subscription management with proper typing for all methods:
|
|
584
|
+
|
|
271
585
|
```typescript
|
|
272
586
|
// List subscriptions
|
|
273
|
-
await inkress.subscriptions.list(
|
|
587
|
+
await inkress.subscriptions.list({
|
|
588
|
+
status: 'active', // Contextual
|
|
589
|
+
billing_plan_id: 1,
|
|
590
|
+
customer_id: 123
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Query subscriptions
|
|
594
|
+
const subscriptions = await inkress.subscriptions.query({
|
|
595
|
+
status: ['active', 'trialing'],
|
|
596
|
+
billing_plan_id: [1, 2, 3],
|
|
597
|
+
inserted_at: { after: '2024-01-01' }
|
|
598
|
+
});
|
|
274
599
|
|
|
275
600
|
// Get subscription details
|
|
276
601
|
await inkress.subscriptions.get(subscriptionId);
|
|
277
602
|
|
|
278
|
-
// Create subscription
|
|
603
|
+
// Create subscription with contextual values
|
|
279
604
|
await inkress.subscriptions.create({
|
|
280
|
-
|
|
605
|
+
billing_plan_id: 1,
|
|
606
|
+
record: 'customer',
|
|
607
|
+
record_id: 123,
|
|
608
|
+
start_date: '2024-01-01',
|
|
609
|
+
status: 'active', // Contextual
|
|
610
|
+
kind: 'recurring' // Contextual
|
|
611
|
+
});
|
|
612
|
+
|
|
613
|
+
// Delete subscription
|
|
614
|
+
await inkress.subscriptions.delete(subscriptionId);
|
|
615
|
+
|
|
616
|
+
// Create subscription link (fully typed)
|
|
617
|
+
const link = await inkress.subscriptions.createLink({
|
|
618
|
+
reference_id: 'sub-123',
|
|
619
|
+
title: 'Premium Subscription',
|
|
620
|
+
plan_uid: 'plan-abc',
|
|
281
621
|
customer: {
|
|
282
|
-
email: 'customer@example.com',
|
|
283
622
|
first_name: 'John',
|
|
284
|
-
last_name: 'Doe'
|
|
623
|
+
last_name: 'Doe',
|
|
624
|
+
email: 'john@example.com'
|
|
285
625
|
}
|
|
286
626
|
});
|
|
627
|
+
// Returns: CreateSubscriptionLinkResponse
|
|
628
|
+
|
|
629
|
+
// Charge subscription (fully typed)
|
|
630
|
+
const charge = await inkress.subscriptions.charge('sub-uid', {
|
|
631
|
+
reference_id: 'charge-123',
|
|
632
|
+
total: 29.99,
|
|
633
|
+
title: 'Monthly charge'
|
|
634
|
+
});
|
|
635
|
+
// Returns: ChargeSubscriptionResponse with typed transaction
|
|
636
|
+
|
|
637
|
+
// Record usage (fully typed)
|
|
638
|
+
const usage = await inkress.subscriptions.usage('sub-uid', {
|
|
639
|
+
reference_id: 'usage-123',
|
|
640
|
+
total: 5.00,
|
|
641
|
+
title: 'API calls'
|
|
642
|
+
});
|
|
643
|
+
// Returns: SubscriptionUsageResponse
|
|
644
|
+
|
|
645
|
+
// Cancel subscription (fully typed)
|
|
646
|
+
const cancelled = await inkress.subscriptions.cancel(123, 'reason-code');
|
|
647
|
+
// Returns: SubscriptionCancelResponse
|
|
648
|
+
|
|
649
|
+
// Get subscription periods
|
|
650
|
+
const periods = await inkress.subscriptions.getPeriods('sub-uid', {
|
|
651
|
+
status: 'paid',
|
|
652
|
+
limit: 10
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
// Query builder
|
|
656
|
+
const subscriptions = await inkress.subscriptions
|
|
657
|
+
.createQueryBuilder()
|
|
658
|
+
.whereStatus('active')
|
|
659
|
+
.whereBillingPlan(1)
|
|
660
|
+
.whereCustomer(123)
|
|
661
|
+
.execute();
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## Additional Resources
|
|
667
|
+
|
|
668
|
+
### Payment Links
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
// List payment links
|
|
672
|
+
await inkress.paymentLinks.list({ status: 'active' });
|
|
673
|
+
|
|
674
|
+
// Create payment link
|
|
675
|
+
await inkress.paymentLinks.create({
|
|
676
|
+
title: 'Product Payment',
|
|
677
|
+
amount: 99.99,
|
|
678
|
+
currency: 'USD',
|
|
679
|
+
status: 'active'
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
// Update payment link
|
|
683
|
+
await inkress.paymentLinks.update(linkId, { amount: 89.99 });
|
|
684
|
+
|
|
685
|
+
// Delete payment link
|
|
686
|
+
await inkress.paymentLinks.delete(linkId);
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### Financial Accounts
|
|
690
|
+
|
|
691
|
+
```typescript
|
|
692
|
+
// List financial accounts
|
|
693
|
+
await inkress.financialAccounts.list();
|
|
694
|
+
|
|
695
|
+
// Create account
|
|
696
|
+
await inkress.financialAccounts.create({
|
|
697
|
+
name: 'Main Account',
|
|
698
|
+
type: 'checking',
|
|
699
|
+
currency: 'USD'
|
|
700
|
+
});
|
|
701
|
+
|
|
702
|
+
// Update account
|
|
703
|
+
await inkress.financialAccounts.update(accountId, { name: 'Updated Name' });
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### Tokens
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
// List tokens
|
|
710
|
+
await inkress.tokens.list({ kind: 'api', enabled: true });
|
|
711
|
+
|
|
712
|
+
// Create token
|
|
713
|
+
await inkress.tokens.create({
|
|
714
|
+
title: 'Production API Key',
|
|
715
|
+
provider: 'stripe',
|
|
716
|
+
kind: 'api'
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// Delete token
|
|
720
|
+
await inkress.tokens.delete(tokenId);
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
### Addresses
|
|
724
|
+
|
|
725
|
+
```typescript
|
|
726
|
+
// List addresses
|
|
727
|
+
await inkress.addresses.list({ country: 'US' });
|
|
728
|
+
|
|
729
|
+
// Create address
|
|
730
|
+
await inkress.addresses.create({
|
|
731
|
+
line1: '123 Main St',
|
|
732
|
+
city: 'New York',
|
|
733
|
+
state: 'NY',
|
|
734
|
+
country: 'US',
|
|
735
|
+
postal_code: '10001'
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
// Update address
|
|
739
|
+
await inkress.addresses.update(addressId, { line1: '456 Broadway' });
|
|
740
|
+
|
|
741
|
+
// Delete address
|
|
742
|
+
await inkress.addresses.delete(addressId);
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
### Fees
|
|
746
|
+
|
|
747
|
+
```typescript
|
|
748
|
+
// List fees
|
|
749
|
+
await inkress.fees.list({ active: true });
|
|
750
|
+
|
|
751
|
+
// Create fee
|
|
752
|
+
await inkress.fees.create({
|
|
753
|
+
name: 'Processing Fee',
|
|
754
|
+
amount: 2.50,
|
|
755
|
+
percentage: 2.9,
|
|
756
|
+
kind: 'transaction'
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
// Update fee
|
|
760
|
+
await inkress.fees.update(feeId, { amount: 2.75 });
|
|
761
|
+
|
|
762
|
+
// Delete fee
|
|
763
|
+
await inkress.fees.delete(feeId);
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
### Exchange Rates & Currencies
|
|
767
|
+
|
|
768
|
+
```typescript
|
|
769
|
+
// List currencies
|
|
770
|
+
await inkress.currencies.list();
|
|
771
|
+
|
|
772
|
+
// Create currency
|
|
773
|
+
await inkress.currencies.create({
|
|
774
|
+
code: 'USD',
|
|
775
|
+
name: 'US Dollar',
|
|
776
|
+
symbol: '$'
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
// List exchange rates
|
|
780
|
+
await inkress.exchangeRates.list({ from_currency: 'USD' });
|
|
781
|
+
|
|
782
|
+
// Create exchange rate
|
|
783
|
+
await inkress.exchangeRates.create({
|
|
784
|
+
from_currency: 'USD',
|
|
785
|
+
to_currency: 'EUR',
|
|
786
|
+
rate: 0.85
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
// Update exchange rate
|
|
790
|
+
await inkress.exchangeRates.update(rateId, { rate: 0.86 });
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### Public Resource
|
|
794
|
+
|
|
795
|
+
Access public merchant information without authentication:
|
|
796
|
+
|
|
797
|
+
```typescript
|
|
798
|
+
// Get merchant by username or domain
|
|
799
|
+
await inkress.public.getMerchant({ username: 'merchant-name' });
|
|
800
|
+
await inkress.public.getMerchant({ 'domain.cname': 'store.example.com' });
|
|
801
|
+
|
|
802
|
+
// Get merchant products with filtering
|
|
803
|
+
await inkress.public.getMerchantProducts('merchant-name', {
|
|
804
|
+
search: 'laptop',
|
|
805
|
+
category: 'electronics',
|
|
806
|
+
limit: 20
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
// Get merchant fees (fully typed)
|
|
810
|
+
const fees = await inkress.public.getMerchantFees('merchant-name', {
|
|
811
|
+
currency: 'USD',
|
|
812
|
+
total: 100
|
|
813
|
+
});
|
|
814
|
+
// Returns: PublicMerchantFees
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
## Advanced Query System
|
|
818
|
+
|
|
819
|
+
The SDK provides a powerful type-safe query system with two interfaces:
|
|
820
|
+
|
|
821
|
+
### 1. Direct Query Method
|
|
822
|
+
|
|
823
|
+
Use the `query()` method with an intuitive object-based syntax:
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
// Simple equality
|
|
827
|
+
await inkress.orders.query({
|
|
828
|
+
status: 'confirmed',
|
|
829
|
+
customer_id: 123
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
// Array queries (IN operations)
|
|
833
|
+
await inkress.orders.query({
|
|
834
|
+
status: ['confirmed', 'shipped', 'delivered'],
|
|
835
|
+
id: [1, 2, 3, 4, 5]
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
// Range queries
|
|
839
|
+
await inkress.products.query({
|
|
840
|
+
price: { min: 100, max: 1000 },
|
|
841
|
+
rating: { min: 4 }
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
// String contains
|
|
845
|
+
await inkress.products.query({
|
|
846
|
+
title: { contains: 'laptop' },
|
|
847
|
+
description: { contains: 'gaming' }
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
// Date ranges
|
|
851
|
+
await inkress.orders.query({
|
|
852
|
+
inserted_at: { after: '2024-01-01', before: '2024-12-31' },
|
|
853
|
+
updated_at: { on: '2024-06-15' }
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
// Complex combined queries
|
|
857
|
+
await inkress.orders.query({
|
|
858
|
+
status: ['confirmed', 'shipped'],
|
|
859
|
+
kind: 'online',
|
|
860
|
+
total: { min: 50, max: 500 },
|
|
861
|
+
reference_id: { contains: 'VIP' },
|
|
862
|
+
customer_id: [100, 101, 102],
|
|
863
|
+
inserted_at: { after: '2024-01-01' },
|
|
864
|
+
page: 1,
|
|
865
|
+
page_size: 20,
|
|
866
|
+
q: 'electronics'
|
|
867
|
+
});
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
### 2. Fluent Query Builder
|
|
871
|
+
|
|
872
|
+
Use the query builder for a fluent, chainable interface:
|
|
873
|
+
|
|
874
|
+
```typescript
|
|
875
|
+
// Products query builder
|
|
876
|
+
const products = await inkress.products
|
|
877
|
+
.createQueryBuilder()
|
|
878
|
+
.whereStatus('published')
|
|
879
|
+
.whereStatusIn(['published', 'featured'])
|
|
880
|
+
.whereCategory(5)
|
|
881
|
+
.whereCategoryIn([1, 2, 3])
|
|
882
|
+
.wherePriceRange(50, 500)
|
|
883
|
+
.wherePriceMin(50)
|
|
884
|
+
.wherePriceMax(500)
|
|
885
|
+
.whereTitleContains('gaming')
|
|
886
|
+
.whereDescriptionContains('RGB')
|
|
887
|
+
.whereCreatedAfter('2024-01-01')
|
|
888
|
+
.whereCreatedBefore('2024-12-31')
|
|
889
|
+
.whereCreatedBetween('2024-01-01', '2024-12-31')
|
|
890
|
+
.paginate(1, 20)
|
|
891
|
+
.orderBy('price', 'desc')
|
|
892
|
+
.search('laptop')
|
|
893
|
+
.execute();
|
|
894
|
+
|
|
895
|
+
// Orders query builder
|
|
896
|
+
const orders = await inkress.orders
|
|
897
|
+
.createQueryBuilder()
|
|
898
|
+
.whereStatus('confirmed')
|
|
899
|
+
.whereStatusIn(['confirmed', 'shipped'])
|
|
900
|
+
.whereKind('online')
|
|
901
|
+
.whereKindIn(['online', 'subscription'])
|
|
902
|
+
.whereTotalRange(100, 1000)
|
|
903
|
+
.whereReferenceContains('VIP')
|
|
904
|
+
.whereCustomer(123)
|
|
905
|
+
.whereCustomerIn([100, 101, 102])
|
|
906
|
+
.whereCreatedBetween('2024-01-01', '2024-12-31')
|
|
907
|
+
.paginate(1, 20)
|
|
908
|
+
.search('electronics')
|
|
909
|
+
.execute();
|
|
910
|
+
|
|
911
|
+
// Merchants query builder
|
|
912
|
+
const merchants = await inkress.merchants
|
|
913
|
+
.createQueryBuilder()
|
|
914
|
+
.whereStatus('approved')
|
|
915
|
+
.wherePlatformFeeStructure('customer_pay')
|
|
916
|
+
.whereProviderFeeStructure('merchant_absorb')
|
|
917
|
+
.whereOrganisation(123)
|
|
918
|
+
.whereNameContains('coffee')
|
|
919
|
+
.paginate(1, 50)
|
|
920
|
+
.execute();
|
|
921
|
+
|
|
922
|
+
// Users query builder
|
|
923
|
+
const users = await inkress.users
|
|
924
|
+
.createQueryBuilder()
|
|
925
|
+
.whereStatus('approved')
|
|
926
|
+
.whereKind('organisation')
|
|
927
|
+
.whereOrganisation(123)
|
|
928
|
+
.whereEmailContains('@company.com')
|
|
929
|
+
.paginate(1, 50)
|
|
930
|
+
.search('admin')
|
|
931
|
+
.execute();
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### Query Transformation
|
|
935
|
+
|
|
936
|
+
The SDK automatically transforms your clean queries into API-compatible format:
|
|
937
|
+
|
|
938
|
+
```typescript
|
|
939
|
+
// You write:
|
|
940
|
+
{
|
|
941
|
+
status: ['confirmed', 'shipped'],
|
|
942
|
+
total: { min: 100, max: 1000 },
|
|
943
|
+
reference_id: { contains: 'VIP' }
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
// SDK transforms to:
|
|
947
|
+
{
|
|
948
|
+
status_in: [4, 7], // Contextual strings → integers with _in suffix
|
|
949
|
+
total_min: 100, // min/max → _min/_max suffixes
|
|
950
|
+
total_max: 1000,
|
|
951
|
+
"contains.reference_id": "VIP" // contains → prefix format
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
### Available Query Operations
|
|
956
|
+
|
|
957
|
+
| Operation | Input Syntax | API Output | Description |
|
|
958
|
+
|-----------|-------------|------------|-------------|
|
|
959
|
+
| **Equality** | `field: value` | `field: value` | Direct match |
|
|
960
|
+
| **Array (IN)** | `field: [1,2,3]` | `field_in: [1,2,3]` | Value in array |
|
|
961
|
+
| **Range Min** | `field: {min: 10}` | `field_min: 10` | Minimum value |
|
|
962
|
+
| **Range Max** | `field: {max: 100}` | `field_max: 100` | Maximum value |
|
|
963
|
+
| **Contains** | `field: {contains: 'text'}` | `"contains.field": "text"` | String contains |
|
|
964
|
+
| **Date After** | `field: {after: 'date'}` | `"after.field": "date"` | After date |
|
|
965
|
+
| **Date Before** | `field: {before: 'date'}` | `"before.field": "date"` | Before date |
|
|
966
|
+
| **Date On** | `field: {on: 'date'}` | `"on.field": "date"` | Exact date |
|
|
967
|
+
|
|
968
|
+
### Query Builder Methods
|
|
969
|
+
|
|
970
|
+
All resources with query support provide these methods:
|
|
971
|
+
|
|
972
|
+
**Equality Methods:**
|
|
973
|
+
- `.whereField(value)` - Direct equality
|
|
974
|
+
- `.whereFieldIn([values])` - Array IN query
|
|
975
|
+
|
|
976
|
+
**Range Methods:**
|
|
977
|
+
- `.whereFieldRange(min, max)` - Min and max
|
|
978
|
+
- `.whereFieldMin(value)` - Minimum value
|
|
979
|
+
- `.whereFieldMax(value)` - Maximum value
|
|
980
|
+
|
|
981
|
+
**String Methods:**
|
|
982
|
+
- `.whereFieldContains(text)` - String contains
|
|
983
|
+
|
|
984
|
+
**Date Methods:**
|
|
985
|
+
- `.whereCreatedAfter(date)` - After date
|
|
986
|
+
- `.whereCreatedBefore(date)` - Before date
|
|
987
|
+
- `.whereCreatedBetween(start, end)` - Date range
|
|
988
|
+
- `.whereUpdatedAfter(date)` - After date
|
|
989
|
+
- `.whereUpdatedBefore(date)` - Before date
|
|
990
|
+
|
|
991
|
+
**Utility Methods:**
|
|
992
|
+
- `.paginate(page, pageSize)` - Pagination
|
|
993
|
+
- `.orderBy(field, direction)` - Sorting
|
|
994
|
+
- `.search(query)` - General search (q parameter)
|
|
995
|
+
- `.execute()` - Execute the query
|
|
996
|
+
|
|
997
|
+
### Field Type Validation
|
|
998
|
+
|
|
999
|
+
The SDK validates field types at runtime to prevent API errors:
|
|
1000
|
+
|
|
1001
|
+
```typescript
|
|
1002
|
+
// Runtime validation ensures correct types
|
|
1003
|
+
await inkress.products.query({
|
|
1004
|
+
price: 99.99, // ✅ Number field
|
|
1005
|
+
unlimited: true, // ✅ Boolean field
|
|
1006
|
+
category_id: 5, // ✅ Integer field
|
|
1007
|
+
inserted_at: '2024-01-01' // ✅ String field
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
// Type mismatches are caught early
|
|
1011
|
+
await inkress.products.query({
|
|
1012
|
+
price: { contains: 'text' } // ❌ Error: price is numeric, not string
|
|
1013
|
+
});
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
## Search and Filtering
|
|
1017
|
+
|
|
1018
|
+
All list operations support comprehensive search and filtering capabilities:
|
|
1019
|
+
|
|
1020
|
+
### General Search with `q`
|
|
1021
|
+
|
|
1022
|
+
Use the `q` parameter for intelligent searching across multiple relevant fields:
|
|
1023
|
+
|
|
1024
|
+
```typescript
|
|
1025
|
+
// Search merchants - searches name, email, username, etc.
|
|
1026
|
+
await inkress.merchants.list({ q: 'john smith' });
|
|
1027
|
+
|
|
1028
|
+
// Search products - searches title, description, etc.
|
|
1029
|
+
await inkress.products.list({ q: 'gaming laptop' });
|
|
1030
|
+
|
|
1031
|
+
// Search orders - searches reference ID, customer details, etc.
|
|
1032
|
+
await inkress.orders.list({ q: 'ORDER-12345' });
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
### String-Based Status and Kind Values
|
|
1036
|
+
|
|
1037
|
+
The SDK supports human-readable string values for better code clarity:
|
|
1038
|
+
|
|
1039
|
+
```typescript
|
|
1040
|
+
// Use descriptive strings for merchants
|
|
1041
|
+
await inkress.merchants.list({
|
|
1042
|
+
status: 'account_approved',
|
|
1043
|
+
platform_fee_structure: 'customer_pay',
|
|
1044
|
+
q: 'electronics'
|
|
1045
|
+
});
|
|
1046
|
+
|
|
1047
|
+
// Filter orders with readable values
|
|
1048
|
+
await inkress.orders.list({
|
|
1049
|
+
status: 'order_confirmed',
|
|
1050
|
+
kind: 'order_online',
|
|
1051
|
+
q: 'laptop'
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
// Filter products by status
|
|
1055
|
+
await inkress.products.list({
|
|
1056
|
+
status: 'product_published',
|
|
1057
|
+
q: 'smartphone'
|
|
1058
|
+
});
|
|
1059
|
+
|
|
1060
|
+
// Integers also work for backward compatibility
|
|
1061
|
+
await inkress.merchants.list({
|
|
1062
|
+
status: 2,
|
|
1063
|
+
platform_fee_structure: 1
|
|
1064
|
+
});
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
### Available String Values
|
|
1068
|
+
|
|
1069
|
+
**Status Values:**
|
|
1070
|
+
- Orders: `order_pending`, `order_confirmed`, `order_shipped`, `order_delivered`, `order_cancelled`, etc.
|
|
1071
|
+
- Accounts: `account_pending`, `account_approved`, `account_suspended`, etc.
|
|
1072
|
+
- Products: `product_draft`, `product_published`, `product_archived`
|
|
1073
|
+
- Transactions: `transaction_pending`, `transaction_authorized`, `transaction_captured`, etc.
|
|
1074
|
+
|
|
1075
|
+
**Kind Values:**
|
|
1076
|
+
- Orders: `order_online`, `order_offline`, `order_subscription`, `order_invoice`
|
|
1077
|
+
- Products: `product_draft`, `product_published`, `product_archived`
|
|
1078
|
+
- Users: `user_address`, `role_organisation`, `role_store`
|
|
1079
|
+
- Billing: `billing_plan_subscription`, `billing_plan_payout`
|
|
1080
|
+
|
|
1081
|
+
**Fee Structure Values:**
|
|
1082
|
+
- `customer_pay` - Customer pays the fees
|
|
1083
|
+
- `merchant_absorb` - Merchant absorbs the fees
|
|
1084
|
+
|
|
1085
|
+
### Database Field Filtering
|
|
1086
|
+
|
|
1087
|
+
Filter by any database field for precise results:
|
|
1088
|
+
|
|
1089
|
+
```typescript
|
|
1090
|
+
// Filter products by specific criteria
|
|
1091
|
+
await inkress.products.list({
|
|
1092
|
+
status: 'product_published', // Published only (string format)
|
|
1093
|
+
category_id: 5, // Specific category
|
|
1094
|
+
price: 1000, // Exact price
|
|
1095
|
+
unlimited: true, // Unlimited quantity
|
|
1096
|
+
inserted_at: '2024-01-01' // Created after date
|
|
1097
|
+
});
|
|
1098
|
+
|
|
1099
|
+
// Filter merchants by organization
|
|
1100
|
+
await inkress.merchants.list({
|
|
1101
|
+
organisation_id: 123,
|
|
1102
|
+
status: 'account_approved',
|
|
1103
|
+
platform_fee_structure: 'customer_pay'
|
|
1104
|
+
});
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
### Combining Search and Filters
|
|
1108
|
+
|
|
1109
|
+
Mix general search with specific filters for powerful queries:
|
|
1110
|
+
|
|
1111
|
+
```typescript
|
|
1112
|
+
await inkress.products.list({
|
|
1113
|
+
q: 'phone', // General search
|
|
1114
|
+
status: 'product_published', // Published only
|
|
1115
|
+
category_id: 5, // Electronics category
|
|
1116
|
+
page: 1, // Pagination
|
|
1117
|
+
per_page: 20, // Results per page
|
|
1118
|
+
sort: 'price', // Sort by price
|
|
1119
|
+
order: 'desc' // Descending order
|
|
1120
|
+
});
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
### Legacy Search Field
|
|
1124
|
+
|
|
1125
|
+
Many resources still support the legacy `search` field for backward compatibility:
|
|
1126
|
+
|
|
1127
|
+
```typescript
|
|
1128
|
+
// Legacy approach (still works)
|
|
1129
|
+
await inkress.products.list({ search: 'laptop' });
|
|
1130
|
+
|
|
1131
|
+
// Recommended approach
|
|
1132
|
+
await inkress.products.list({ q: 'laptop' });
|
|
287
1133
|
```
|
|
288
1134
|
|
|
289
1135
|
## Error Handling
|
|
@@ -297,7 +1143,7 @@ try {
|
|
|
297
1143
|
if (error.response?.status === 404) {
|
|
298
1144
|
console.log('Product not found');
|
|
299
1145
|
} else if (error.response?.status === 422) {
|
|
300
|
-
console.log('Validation errors:', error.response.
|
|
1146
|
+
console.log('Validation errors:', error.response.result);
|
|
301
1147
|
} else {
|
|
302
1148
|
console.log('Unexpected error:', error.message);
|
|
303
1149
|
}
|
|
@@ -306,22 +1152,192 @@ try {
|
|
|
306
1152
|
|
|
307
1153
|
## TypeScript Support
|
|
308
1154
|
|
|
309
|
-
The SDK is built with TypeScript and provides
|
|
1155
|
+
The SDK is built with TypeScript and provides **100% type safety** across all 128+ methods:
|
|
1156
|
+
|
|
1157
|
+
### Complete Type Coverage
|
|
1158
|
+
|
|
1159
|
+
Every method has:
|
|
1160
|
+
- ✅ Fully typed input parameters (no `any` types)
|
|
1161
|
+
- ✅ Fully typed return values with specific interfaces
|
|
1162
|
+
- ✅ IDE autocomplete for all fields and methods
|
|
1163
|
+
- ✅ Compile-time type checking
|
|
310
1164
|
|
|
311
1165
|
```typescript
|
|
312
1166
|
import {
|
|
313
1167
|
InkressSDK,
|
|
1168
|
+
// Core types
|
|
314
1169
|
Product,
|
|
315
1170
|
Category,
|
|
316
1171
|
Order,
|
|
317
1172
|
Merchant,
|
|
1173
|
+
User,
|
|
1174
|
+
BillingPlan,
|
|
1175
|
+
Subscription,
|
|
1176
|
+
|
|
1177
|
+
// Create/Update types
|
|
318
1178
|
CreateProductData,
|
|
319
|
-
|
|
1179
|
+
UpdateProductData,
|
|
1180
|
+
CreateOrderData,
|
|
1181
|
+
UpdateMerchantData,
|
|
1182
|
+
CreateUserData,
|
|
1183
|
+
|
|
1184
|
+
// Response types
|
|
1185
|
+
ApiResponse,
|
|
1186
|
+
ProductListResponse,
|
|
1187
|
+
OrderListResponse,
|
|
1188
|
+
MerchantBalance,
|
|
1189
|
+
MerchantLimits,
|
|
1190
|
+
MerchantSubscription,
|
|
1191
|
+
MerchantInvoice,
|
|
1192
|
+
|
|
1193
|
+
// Query types
|
|
1194
|
+
ProductQueryParams,
|
|
1195
|
+
OrderQueryParams,
|
|
1196
|
+
RangeQuery,
|
|
1197
|
+
StringQuery,
|
|
1198
|
+
|
|
1199
|
+
// Enum types
|
|
1200
|
+
OrderStatus,
|
|
1201
|
+
OrderKind,
|
|
1202
|
+
AccountStatus,
|
|
1203
|
+
UserKind,
|
|
1204
|
+
FeeStructureKey,
|
|
1205
|
+
StatusKey,
|
|
1206
|
+
KindKey
|
|
320
1207
|
} from '@inkress/admin-sdk';
|
|
321
1208
|
|
|
322
|
-
// All
|
|
323
|
-
const response: ApiResponse<
|
|
324
|
-
const products: Product[] = response.result ||
|
|
1209
|
+
// All responses are properly typed
|
|
1210
|
+
const response: ApiResponse<ProductListResponse> = await inkress.products.list();
|
|
1211
|
+
const products: Product[] = response.result?.entries || [];
|
|
1212
|
+
|
|
1213
|
+
// Create operations with full typing
|
|
1214
|
+
const createData: CreateProductData = {
|
|
1215
|
+
name: 'Gaming Laptop',
|
|
1216
|
+
price: 1299.99,
|
|
1217
|
+
category_id: 1,
|
|
1218
|
+
status: 'published',
|
|
1219
|
+
kind: 'published'
|
|
1220
|
+
};
|
|
1221
|
+
const product: ApiResponse<Product> = await inkress.products.create(createData);
|
|
1222
|
+
|
|
1223
|
+
// Update operations with full typing
|
|
1224
|
+
const updateData: UpdateMerchantData = {
|
|
1225
|
+
name: 'Updated Store',
|
|
1226
|
+
status: 'approved',
|
|
1227
|
+
platform_fee_structure: 'customer_pay'
|
|
1228
|
+
};
|
|
1229
|
+
await inkress.merchants.update(123, updateData);
|
|
1230
|
+
|
|
1231
|
+
// Merchant account methods with specific types
|
|
1232
|
+
const balances: ApiResponse<MerchantBalance> = await inkress.merchants.balances();
|
|
1233
|
+
// balances.data: { available: number, pending: number, currency: string }
|
|
1234
|
+
|
|
1235
|
+
const limits: ApiResponse<MerchantLimits> = await inkress.merchants.limits();
|
|
1236
|
+
// limits.data: { transaction_limit: number, daily_limit: number, monthly_limit: number, currency: string }
|
|
1237
|
+
|
|
1238
|
+
const subscription: ApiResponse<MerchantSubscription> = await inkress.merchants.subscription();
|
|
1239
|
+
// subscription.data: { plan_name: string, status: string, billing_cycle: string, price: number, ... }
|
|
1240
|
+
|
|
1241
|
+
const invoices: ApiResponse<MerchantInvoice[]> = await inkress.merchants.invoices();
|
|
1242
|
+
// invoices.data: Array of typed MerchantInvoice objects
|
|
1243
|
+
|
|
1244
|
+
// Query with full type safety
|
|
1245
|
+
const orderQuery: OrderQueryParams = {
|
|
1246
|
+
status: ['confirmed', 'shipped'],
|
|
1247
|
+
total: { min: 100, max: 1000 },
|
|
1248
|
+
reference_id: { contains: 'VIP' },
|
|
1249
|
+
page: 1,
|
|
1250
|
+
page_size: 20
|
|
1251
|
+
};
|
|
1252
|
+
const orders: ApiResponse<OrderListResponse> = await inkress.orders.query(orderQuery);
|
|
1253
|
+
|
|
1254
|
+
// Contextual enums for type safety
|
|
1255
|
+
const status: OrderStatus = 'confirmed'; // Only valid order statuses allowed
|
|
1256
|
+
const kind: OrderKind = 'online'; // Only valid order kinds allowed
|
|
1257
|
+
const feeStructure: FeeStructureKey = 'customer_pay'; // Only valid fee structures allowed
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
### Type-Safe Query Building
|
|
1261
|
+
|
|
1262
|
+
Query builders provide complete type safety:
|
|
1263
|
+
|
|
1264
|
+
```typescript
|
|
1265
|
+
// Typed query builder - only valid methods for each field type
|
|
1266
|
+
const products = await inkress.products
|
|
1267
|
+
.createQueryBuilder()
|
|
1268
|
+
.whereStatus('published') // String field - contextual value
|
|
1269
|
+
.whereCategory(5) // Number field - direct value
|
|
1270
|
+
.wherePriceRange(50, 500) // Number field - range
|
|
1271
|
+
.whereTitleContains('gaming') // String field - contains
|
|
1272
|
+
.whereUnlimited(true) // Boolean field - direct value
|
|
1273
|
+
.whereCreatedAfter('2024-01-01') // Date field - after
|
|
1274
|
+
.paginate(1, 20)
|
|
1275
|
+
.execute();
|
|
1276
|
+
|
|
1277
|
+
// TypeScript ensures you can't use wrong query types
|
|
1278
|
+
products
|
|
1279
|
+
.wherePrice({ contains: 'text' }) // ❌ Compile error: price is numeric
|
|
1280
|
+
.whereTitle(123); // ❌ Compile error: title is string
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
### Response Type Handling
|
|
1284
|
+
|
|
1285
|
+
Handle responses with full type awareness:
|
|
1286
|
+
|
|
1287
|
+
```typescript
|
|
1288
|
+
async function getProduct(id: number): Promise<Product | null> {
|
|
1289
|
+
try {
|
|
1290
|
+
const response: ApiResponse<Product> = await inkress.products.get(id);
|
|
1291
|
+
|
|
1292
|
+
// TypeScript knows the exact structure
|
|
1293
|
+
if (response.result) {
|
|
1294
|
+
return response.result; // Product type
|
|
1295
|
+
}
|
|
1296
|
+
return null;
|
|
1297
|
+
} catch (error) {
|
|
1298
|
+
console.error('Failed to fetch product:', error);
|
|
1299
|
+
return null;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
async function listProducts(): Promise<Product[]> {
|
|
1304
|
+
const response: ApiResponse<ProductListResponse> = await inkress.products.list();
|
|
1305
|
+
|
|
1306
|
+
// TypeScript knows ProductListResponse structure
|
|
1307
|
+
const entries = response.result?.entries || [];
|
|
1308
|
+
|
|
1309
|
+
// entries is Product[]
|
|
1310
|
+
return entries.map(product => ({
|
|
1311
|
+
...product,
|
|
1312
|
+
discounted_price: product.price * 0.9 // TypeScript knows price is a number
|
|
1313
|
+
}));
|
|
1314
|
+
}
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
### Discriminated Unions
|
|
1318
|
+
|
|
1319
|
+
Use TypeScript's discriminated unions for status/kind handling:
|
|
1320
|
+
|
|
1321
|
+
```typescript
|
|
1322
|
+
type OrderStatusAction =
|
|
1323
|
+
| { status: 'pending', action: 'await_payment' }
|
|
1324
|
+
| { status: 'confirmed', action: 'process_order' }
|
|
1325
|
+
| { status: 'shipped', action: 'track_shipment' }
|
|
1326
|
+
| { status: 'delivered', action: 'request_feedback' };
|
|
1327
|
+
|
|
1328
|
+
async function handleOrder(orderId: number, statusAction: OrderStatusAction) {
|
|
1329
|
+
await inkress.orders.update(orderId, { status: statusAction.status });
|
|
1330
|
+
|
|
1331
|
+
// TypeScript narrows the type based on status
|
|
1332
|
+
switch (statusAction.status) {
|
|
1333
|
+
case 'pending':
|
|
1334
|
+
// statusAction.action is 'await_payment'
|
|
1335
|
+
break;
|
|
1336
|
+
case 'confirmed':
|
|
1337
|
+
// statusAction.action is 'process_order'
|
|
1338
|
+
break;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
325
1341
|
```
|
|
326
1342
|
|
|
327
1343
|
## Environment Configuration
|
|
@@ -401,7 +1417,7 @@ Always implement proper error handling:
|
|
|
401
1417
|
async function fetchProducts() {
|
|
402
1418
|
try {
|
|
403
1419
|
const response = await inkress.products.list();
|
|
404
|
-
return response.result ||
|
|
1420
|
+
return response.result || [];
|
|
405
1421
|
} catch (error) {
|
|
406
1422
|
console.error('Failed to fetch products:', error);
|
|
407
1423
|
return [];
|
|
@@ -431,10 +1447,81 @@ async function getCachedMerchant(username: string) {
|
|
|
431
1447
|
}
|
|
432
1448
|
```
|
|
433
1449
|
|
|
1450
|
+
### 4. Webhook Verification
|
|
1451
|
+
|
|
1452
|
+
Verify incoming webhook requests from Inkress using HMAC SHA256:
|
|
1453
|
+
|
|
1454
|
+
```typescript
|
|
1455
|
+
import { WebhookUtils } from '@inkress/admin-sdk';
|
|
1456
|
+
|
|
1457
|
+
// Method 1: Verify with signature, body, and secret
|
|
1458
|
+
app.post('/webhooks/inkress', (req, res) => {
|
|
1459
|
+
const signature = req.headers['x-inkress-webhook-signature'];
|
|
1460
|
+
const body = JSON.stringify(req.body);
|
|
1461
|
+
const secret = process.env.INKRESS_WEBHOOK_SECRET;
|
|
1462
|
+
|
|
1463
|
+
const isValid = WebhookUtils.verifySignature(body, signature, secret);
|
|
1464
|
+
|
|
1465
|
+
if (!isValid) {
|
|
1466
|
+
return res.status(401).json({ error: 'Invalid signature' });
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
// Process webhook...
|
|
1470
|
+
res.status(200).json({ received: true });
|
|
1471
|
+
});
|
|
1472
|
+
|
|
1473
|
+
// Method 2: Let the SDK extract everything from the request
|
|
1474
|
+
app.post('/webhooks/inkress', (req, res) => {
|
|
1475
|
+
const secret = process.env.INKRESS_WEBHOOK_SECRET;
|
|
1476
|
+
|
|
1477
|
+
try {
|
|
1478
|
+
const { isValid, body } = WebhookUtils.verifyRequest(req, secret);
|
|
1479
|
+
|
|
1480
|
+
if (!isValid) {
|
|
1481
|
+
return res.status(401).json({ error: 'Invalid signature' });
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
// Parse the verified body
|
|
1485
|
+
const webhookPayload = WebhookUtils.parsePayload(body);
|
|
1486
|
+
|
|
1487
|
+
// Process webhook...
|
|
1488
|
+
res.status(200).json({ received: true });
|
|
1489
|
+
} catch (error) {
|
|
1490
|
+
res.status(400).json({ error: error.message });
|
|
1491
|
+
}
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1494
|
+
// Method 3: Use Express middleware for automatic verification
|
|
1495
|
+
import { createWebhookMiddleware } from '@inkress/admin-sdk';
|
|
1496
|
+
|
|
1497
|
+
app.use('/webhooks/inkress', createWebhookMiddleware(process.env.INKRESS_WEBHOOK_SECRET));
|
|
1498
|
+
|
|
1499
|
+
app.post('/webhooks/inkress', (req, res) => {
|
|
1500
|
+
// Request is already verified, payload attached to req.webhookPayload
|
|
1501
|
+
const { webhookPayload } = req;
|
|
1502
|
+
|
|
1503
|
+
console.log(`Received event: ${webhookPayload.event.action}`);
|
|
1504
|
+
|
|
1505
|
+
res.status(200).json({ received: true });
|
|
1506
|
+
});
|
|
1507
|
+
```
|
|
1508
|
+
|
|
1509
|
+
**Webhook Signature Format:**
|
|
1510
|
+
- Header: `X-Inkress-Webhook-Signature`
|
|
1511
|
+
- Algorithm: HMAC SHA256
|
|
1512
|
+
- Encoding: Base64
|
|
1513
|
+
- Equivalent to: `crypto.mac(:hmac, :sha256, secret, body) |> Base.encode64()`
|
|
1514
|
+
|
|
1515
|
+
See [examples/webhook-server.ts](examples/webhook-server.ts) for a complete implementation.
|
|
1516
|
+
|
|
434
1517
|
## Contributing
|
|
435
1518
|
|
|
436
1519
|
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
437
1520
|
|
|
1521
|
+
## Migrating from Older Versions
|
|
1522
|
+
|
|
1523
|
+
See [MIGRATION.md](MIGRATION.md) for upgrade instructions and breaking changes between versions.
|
|
1524
|
+
|
|
438
1525
|
## Support
|
|
439
1526
|
|
|
440
1527
|
- 📚 [API Documentation](https://docs.inkress.com)
|