@scryme/sdk 0.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/README.md +410 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# Scryme V3 SDK
|
|
2
|
+
|
|
3
|
+
The official TypeScript SDK for the **Scryme V3 API**βengineered for scalability, security, and developer convenience. This SDK provides complete, type-safe coverage of all Scryme V3 services, allowing developers to seamlessly integrate their applications with the Scryme ecosystem.
|
|
4
|
+
|
|
5
|
+
## π Features
|
|
6
|
+
|
|
7
|
+
- **End-to-End Type Safety**: Direct compilation from the core OpenAPI 3.0 specification.
|
|
8
|
+
- **Axios-Based Client**: Built-in support for request/response interceptors, customizable base URLs, and timeout configurations.
|
|
9
|
+
- **Comprehensive API Coverage**:
|
|
10
|
+
- **Auth**: Token exchange (Client Credentials Flow) & OAuth2 proxy support.
|
|
11
|
+
- **Inventory**: Stock queries, multi-branch listings, batch tracking (trace, split, merge), B2B availability checks, and integrity verify/fix logic.
|
|
12
|
+
- **Orders & B2B**: Quote requests, quote-to-order conversions, and order management.
|
|
13
|
+
- **CRM & Customers**: Customer registration (Zitadel), custom CRM definitions, custom fields, relationships, associations, notes, and activity timelines.
|
|
14
|
+
- **Loyalty**: Loyalty status (tiers & points), voucher validation, and reward redemption.
|
|
15
|
+
- **Finance**: Corporate expenses, utility account tracking, and petty cash fund management (allocations, transactions, top-ups).
|
|
16
|
+
- **POS**: POS device provisioning, staff login, and petty cash expense logging.
|
|
17
|
+
- **Members & Roles**: Staff rosters, custom roles, permission sets, departments, and attendance logging (check-in/check-out).
|
|
18
|
+
- **Services & Bookings**: Resource utilization, booking funnel, public-facing OTP-verified booking, shifts, and materials consumption.
|
|
19
|
+
- **Integrations & Webhooks**: Subscription management and Strapi E-commerce integration (storefront customer registration, storefront token exchange, sync queues).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## π¦ Installation
|
|
24
|
+
|
|
25
|
+
To use the Scryme V3 SDK in your project, install it from the workspace repository:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add @scryme/sdk
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## π Authentication
|
|
34
|
+
|
|
35
|
+
The Scryme V3 API uses **OAuth2 Client Credentials Flow** to authorize external applications and integrations.
|
|
36
|
+
|
|
37
|
+
### Step 1: Exchange Credentials for an Access Token
|
|
38
|
+
To retrieve an access token, pass your `clientId` and `clientSecret` (generated during device/app provisioning) to the token exchange endpoint:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import axios from "axios";
|
|
42
|
+
import { authExchangeToken } from "@scryme/sdk";
|
|
43
|
+
|
|
44
|
+
// Initialize the global axios configuration if needed
|
|
45
|
+
axios.defaults.baseURL = "https://api.scryme.tech";
|
|
46
|
+
|
|
47
|
+
async function authenticate() {
|
|
48
|
+
try {
|
|
49
|
+
const response = await authExchangeToken({
|
|
50
|
+
clientId: "your_client_id_123",
|
|
51
|
+
clientSecret: "your_client_secret_456"
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const { accessToken, expiresIn } = response.data;
|
|
55
|
+
console.log(`Authenticated successfully! Token expires in ${expiresIn}s.`);
|
|
56
|
+
return accessToken;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("Authentication failed:", error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Step 2: Configure Authenticated Client Calls
|
|
65
|
+
Once you have the `accessToken`, register an Axios request interceptor to automatically attach the bearer token to all outgoing requests:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import axios from "axios";
|
|
69
|
+
|
|
70
|
+
function setupAuthenticatedClient(token: string) {
|
|
71
|
+
axios.interceptors.request.use((config) => {
|
|
72
|
+
config.headers.Authorization = `Bearer ${token}`;
|
|
73
|
+
return config;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## π οΈ Domain Modules & Usage Examples
|
|
81
|
+
|
|
82
|
+
Below are comprehensive examples showing how to interact with the key V3 modules.
|
|
83
|
+
|
|
84
|
+
### π¦ 1. V3 Inventory Management
|
|
85
|
+
Query stock levels, trace/merge/split batches, and check availability for B2B accounts.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import {
|
|
89
|
+
inventoryGetInventory,
|
|
90
|
+
inventoryVerifyIntegrity,
|
|
91
|
+
inventoryMergeBatches,
|
|
92
|
+
inventorySplitBatch
|
|
93
|
+
} from "@scryme/sdk";
|
|
94
|
+
|
|
95
|
+
const orgSlug = "scryme-hq";
|
|
96
|
+
const locationId = "loc_nairobi_001";
|
|
97
|
+
|
|
98
|
+
// 1. Get current stock levels at a specific location
|
|
99
|
+
async function checkStock() {
|
|
100
|
+
const response = await inventoryGetInventory(orgSlug, {
|
|
101
|
+
locationId,
|
|
102
|
+
limit: 50,
|
|
103
|
+
offset: 0
|
|
104
|
+
});
|
|
105
|
+
console.log("Stock Inventory:", response.data);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 2. Verify stock integrity and run discrepancy checks
|
|
109
|
+
async function runIntegrityCheck() {
|
|
110
|
+
const result = await inventoryVerifyIntegrity(orgSlug);
|
|
111
|
+
console.log("Integrity Report:", result.data);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 3. Merge multiple stock batches into a single parent batch
|
|
115
|
+
async function consolidateBatches() {
|
|
116
|
+
await inventoryMergeBatches(orgSlug, {
|
|
117
|
+
// Merge parameters
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### π 2. Orders & B2B Sales
|
|
123
|
+
Submit quotes, verify B2B item stock availability, and convert approved quotes to orders.
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import {
|
|
127
|
+
ordersCreateOrder,
|
|
128
|
+
ordersRequestB2BQuote,
|
|
129
|
+
ordersConvertQuoteToOrder,
|
|
130
|
+
ordersGetOrders
|
|
131
|
+
} from "@scryme/sdk";
|
|
132
|
+
|
|
133
|
+
// 1. Request a pricing and availability quote for B2B items
|
|
134
|
+
async function createQuote() {
|
|
135
|
+
const quote = await ordersRequestB2BQuote(orgSlug, {
|
|
136
|
+
customerId: "cust_999",
|
|
137
|
+
businessAccountId: "biz_acme_corp",
|
|
138
|
+
locationId: "loc_nairobi_001",
|
|
139
|
+
items: [
|
|
140
|
+
{ variantId: "var_espresso_beans_01", quantity: 15 }
|
|
141
|
+
],
|
|
142
|
+
notes: "Requires delivery before Friday"
|
|
143
|
+
});
|
|
144
|
+
console.log("Quote Requested:", quote.data);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 2. Convert an approved quote directly into a sales order
|
|
148
|
+
async function approveAndOrder(quoteId: string) {
|
|
149
|
+
const order = await ordersConvertQuoteToOrder(quoteId, orgSlug);
|
|
150
|
+
console.log("Sales Order Created:", order.data);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### π₯ 3. Customers & CRM
|
|
155
|
+
Create and query contacts, build custom CRM records with schemas, and manage timelines.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import {
|
|
159
|
+
customersGetCustomers,
|
|
160
|
+
crmControllerCreateRecord,
|
|
161
|
+
crmControllerCreateNote,
|
|
162
|
+
crmControllerGetTimeline
|
|
163
|
+
} from "@scryme/sdk";
|
|
164
|
+
|
|
165
|
+
// 1. Fetch organization-scoped customers
|
|
166
|
+
async function listCustomers() {
|
|
167
|
+
const customers = await customersGetCustomers(orgSlug, { limit: 10 });
|
|
168
|
+
console.log("Customers list:", customers.data);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 2. Create custom CRM fields and records
|
|
172
|
+
async function logDealRecord() {
|
|
173
|
+
// Create a record under the 'deal' definition
|
|
174
|
+
const record = await crmControllerCreateRecord(orgSlug, {
|
|
175
|
+
objectId: "def_deal_id",
|
|
176
|
+
ownerId: "member_sales_rep_01",
|
|
177
|
+
data: {
|
|
178
|
+
title: "Enterprise Upgrade 2026",
|
|
179
|
+
amount: 450000,
|
|
180
|
+
stage: "discovery",
|
|
181
|
+
expectedCloseDate: "2026-12-31"
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const recordId = record.data.id;
|
|
186
|
+
|
|
187
|
+
// Add rich markdown notes to the deal's timeline
|
|
188
|
+
await crmControllerCreateNote(orgSlug, {
|
|
189
|
+
recordId,
|
|
190
|
+
content: "# Kickoff Meeting Notes\n- Client loved the POS speed.\n- Wants M-Pesa automated routing.",
|
|
191
|
+
timelineDate: new Date().toISOString()
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Fetch unified timelines containing all activities and notes
|
|
195
|
+
const timeline = await crmControllerGetTimeline(recordId, orgSlug);
|
|
196
|
+
console.log("Deal Timeline:", timeline.data);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### π« 4. Loyalty & Marketing
|
|
201
|
+
Track customer rewards, redeem points for discounts, and validate vouchers at Checkout.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import {
|
|
205
|
+
loyaltyGetCustomerStatus,
|
|
206
|
+
loyaltyRedeemReward,
|
|
207
|
+
loyaltyValidateVoucher
|
|
208
|
+
} from "@scryme/sdk";
|
|
209
|
+
|
|
210
|
+
// 1. Get customer points balance, tier level, and available rewards
|
|
211
|
+
async function checkLoyalty(customerId: string) {
|
|
212
|
+
const status = await loyaltyGetCustomerStatus(customerId, orgSlug);
|
|
213
|
+
console.log(`Tier: ${status.data.tier}, Balance: ${status.data.points} pts`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 2. Validate voucher code and check customer eligibility
|
|
217
|
+
async function processDiscount(code: string, customerId: string) {
|
|
218
|
+
try {
|
|
219
|
+
const validation = await loyaltyValidateVoucher(orgSlug, {
|
|
220
|
+
code,
|
|
221
|
+
customerId
|
|
222
|
+
});
|
|
223
|
+
console.log("Voucher Approved:", validation.data);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error("Invalid voucher code:", error);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### π΅ 5. Finance, Petty Cash, & Expenses
|
|
231
|
+
Track spending, top up petty cash drawers, and map payments to utility accounts.
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import {
|
|
235
|
+
expenseControllerCreateExpense,
|
|
236
|
+
pettyCashControllerCreateFund,
|
|
237
|
+
pettyCashControllerTopUpFund,
|
|
238
|
+
utilityAccountControllerCreateAccount
|
|
239
|
+
} from "@scryme/sdk";
|
|
240
|
+
|
|
241
|
+
// 1. Create a physical utility tracking account
|
|
242
|
+
async function setupElectricityMeter() {
|
|
243
|
+
const account = await utilityAccountControllerCreateAccount({
|
|
244
|
+
name: "HQ Power - Meter A",
|
|
245
|
+
provider: "Kenya Power",
|
|
246
|
+
accountNumber: "22334455-01",
|
|
247
|
+
meterNumber: "M-778899",
|
|
248
|
+
type: "ELECTRICITY"
|
|
249
|
+
});
|
|
250
|
+
return account.data.id;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// 2. Record a direct corporate expense
|
|
254
|
+
async function logExpense(utilityAccountId: string) {
|
|
255
|
+
await expenseControllerCreateExpense({
|
|
256
|
+
description: "HQ Monthly Electricity Bill",
|
|
257
|
+
amount: 14500,
|
|
258
|
+
categoryId: "cat_utilities_01",
|
|
259
|
+
paymentMethod: "MPESA",
|
|
260
|
+
utilityAccountId,
|
|
261
|
+
isReimbursable: false,
|
|
262
|
+
isBillable: false
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### π’ 6. Staff, Shifts, & Attendance
|
|
268
|
+
Log clock-ins, check rosters, and manage custom permission sets and roles.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
import {
|
|
272
|
+
attendanceControllerCheckIn,
|
|
273
|
+
attendanceControllerCheckOut,
|
|
274
|
+
roleManagementControllerCreateCustomRole,
|
|
275
|
+
membersControllerGetMembers
|
|
276
|
+
} from "@scryme/sdk";
|
|
277
|
+
|
|
278
|
+
// 1. Employee Clock-In with notes and location validation
|
|
279
|
+
async function clockIn(memberId: string) {
|
|
280
|
+
await attendanceControllerCheckIn(orgSlug, {
|
|
281
|
+
locationId: "loc_nairobi_001",
|
|
282
|
+
notes: "Starting morning shift at register 02"
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// 2. Create high-security roles with customized permissions
|
|
287
|
+
async function setupManagerRole() {
|
|
288
|
+
const role = await roleManagementControllerCreateCustomRole(orgSlug, {
|
|
289
|
+
name: "Vault Auditor",
|
|
290
|
+
description: "Access to petty cash floats and inventory adjustments",
|
|
291
|
+
permissions: [
|
|
292
|
+
"finance:manage-floats",
|
|
293
|
+
"inventory:adjust"
|
|
294
|
+
]
|
|
295
|
+
});
|
|
296
|
+
console.log("Audit Role Created:", role.data);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### π
7. Services, Scheduling, & Bookings
|
|
301
|
+
Manage appointments, track resource utilization, and deduct materials automatically upon completion.
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import {
|
|
305
|
+
servicesControllerCreateBooking,
|
|
306
|
+
servicesControllerCompleteBooking,
|
|
307
|
+
publicServicesControllerRequestOtp,
|
|
308
|
+
publicServicesControllerVerifyOtp
|
|
309
|
+
} from "@scryme/sdk";
|
|
310
|
+
|
|
311
|
+
// 1. Book an appointment for a customer with specific staff/resources
|
|
312
|
+
async function bookAppointment() {
|
|
313
|
+
const booking = await servicesControllerCreateBooking(orgSlug, {
|
|
314
|
+
serviceId: "srv_coffee_cupping_01",
|
|
315
|
+
customerId: "cust_123",
|
|
316
|
+
locationId: "loc_nairobi_001",
|
|
317
|
+
scheduledStartTime: "2026-10-15T09:00:00Z",
|
|
318
|
+
staffIds: ["member_barista_expert_01"],
|
|
319
|
+
resourceIds: ["res_cupping_lab_A"],
|
|
320
|
+
notes: "VIP tasting session"
|
|
321
|
+
});
|
|
322
|
+
console.log("Appointment Booked:", booking.data);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// 2. Complete a booking and auto-deduct standard raw materials
|
|
326
|
+
async function checkoutBooking(bookingId: string) {
|
|
327
|
+
await servicesControllerCompleteBooking(bookingId, orgSlug, {
|
|
328
|
+
actualStartTime: "2026-10-15T09:02:00Z",
|
|
329
|
+
actualEndTime: "2026-10-15T10:15:00Z",
|
|
330
|
+
materials: [
|
|
331
|
+
{ variantId: "var_specialty_beans_cupping", quantity: 0.25 } // 250g beans consumed
|
|
332
|
+
]
|
|
333
|
+
});
|
|
334
|
+
console.log("Booking closed and inventory updated.");
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### π 8. Webhooks & Event Subscriptions
|
|
339
|
+
Subscribe to system events and safely verify incoming signatures.
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
import { webhooksCreate } from "@scryme/sdk";
|
|
343
|
+
|
|
344
|
+
// 1. Register a webhook callback to sync orders to an external ERP
|
|
345
|
+
async function setupWebhook() {
|
|
346
|
+
const webhook = await webhooksCreate(orgSlug, {
|
|
347
|
+
name: "External ERP Sync",
|
|
348
|
+
url: "https://erp.mycompany.com/webhooks/scryme",
|
|
349
|
+
events: ["order.created", "inventory.updated"]
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Use the secret to verify signatures in your endpoint (see Best Practices below)
|
|
353
|
+
console.log("Webhook Registered. HMAC Secret:", webhook.data.secret);
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## π Best Practices
|
|
360
|
+
|
|
361
|
+
### Multi-tenant Organization Scoping
|
|
362
|
+
All core resources are strictly isolated by organization. Ensure you always pass the correct `orgSlug` parameter as required by the endpoints. Passing an invalid or unauthorized `orgSlug` will yield a `401 Unauthorized` or `404 Not Found` response.
|
|
363
|
+
|
|
364
|
+
### Secure Webhook Verification
|
|
365
|
+
When receiving webhook callbacks from Scryme, always verify the webhook signature before processing the payload to prevent spoofing attacks.
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
import * as crypto from "crypto";
|
|
369
|
+
|
|
370
|
+
function verifySignature(
|
|
371
|
+
payload: string,
|
|
372
|
+
signature: string,
|
|
373
|
+
webhookSecret: string
|
|
374
|
+
): boolean {
|
|
375
|
+
// Generate the expected HMAC signature
|
|
376
|
+
const hmac = crypto.createHmac("sha256", webhookSecret);
|
|
377
|
+
const expectedSignature = hmac.update(payload).digest("hex");
|
|
378
|
+
|
|
379
|
+
// Constant-time comparison to prevent timing attacks
|
|
380
|
+
return crypto.timingSafeEqual(
|
|
381
|
+
Buffer.from(signature, "hex"),
|
|
382
|
+
Buffer.from(expectedSignature, "hex")
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### Robust Error Handling
|
|
388
|
+
Scryme V3 API returns standardized error structures. Always wrap your SDK calls in `try/catch` blocks and parse the error fields to display helpful messages to users.
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { isAxiosError } from "axios";
|
|
392
|
+
|
|
393
|
+
try {
|
|
394
|
+
await checkStock();
|
|
395
|
+
} catch (error) {
|
|
396
|
+
if (isAxiosError(error) && error.response) {
|
|
397
|
+
const apiError = error.response.data;
|
|
398
|
+
console.error(`Error (${apiError.error.code}): ${apiError.error.message}`);
|
|
399
|
+
console.error("Details:", apiError.error.details);
|
|
400
|
+
} else {
|
|
401
|
+
console.error("Unexpected Error:", error);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## π License
|
|
409
|
+
|
|
410
|
+
This package is proprietary software belonging to Scryme Ltd. All rights reserved.
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scryme/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"module": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"axios": "^1.18.1"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"orval": "^8.23.0",
|
|
18
|
+
"tsup": "^8.5.1",
|
|
19
|
+
"typescript": "5.7.3",
|
|
20
|
+
"@repo/typescript-config": "0.0.0"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"generate": "orval",
|
|
24
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
25
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
|
|
26
|
+
}
|
|
27
|
+
}
|