helpdesk-app-framework-sdk 1.0.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/LICENSE +177 -0
- package/README.md +587 -0
- package/build/baf_sdk.js +2107 -0
- package/build/baf_sdk.js.map +1 -0
- package/build/baf_sdk.min.js +1 -0
- package/lib/apis/context.js +172 -0
- package/lib/apis/instance.js +225 -0
- package/lib/apis/metadata.js +156 -0
- package/lib/apis/request.js +196 -0
- package/lib/client.js +422 -0
- package/lib/index.js +99 -0
- package/lib/utils.js +202 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
# BoldDesk App Framework SDK
|
|
2
|
+
|
|
3
|
+
The BoldDesk App Framework (BAF) SDK is a JavaScript library that simplifies cross-frame communication between iframed apps and the BoldDesk App Framework, enabling seamless integration of custom applications into the BoldDesk helpdesk platform.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The BAF SDK provides a unified interface for:
|
|
8
|
+
- **Data Access**: Retrieve and update ticket, contact, and chat information
|
|
9
|
+
- **Event Handling**: Listen to and respond to platform events
|
|
10
|
+
- **Cross-Frame Communication**: Safely communicate between iframes and the host
|
|
11
|
+
- **API Requests**: Make secure HTTP requests through BoldDesk proxy
|
|
12
|
+
- **App Instances**: Manage app instances and multi-instance scenarios
|
|
13
|
+
- **Context & Metadata**: Access runtime context and app metadata
|
|
14
|
+
|
|
15
|
+
## Getting Started
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install bolddesk_app_framework_sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Basic Usage
|
|
24
|
+
|
|
25
|
+
```html
|
|
26
|
+
<script src="path/to/baf_sdk.min.js"></script>
|
|
27
|
+
<script>
|
|
28
|
+
const client = BAFClient.init((context) => {
|
|
29
|
+
console.log('App initialized!');
|
|
30
|
+
console.log('User:', context.user.name);
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Or as an ES Module
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
import BAFClient from 'bolddesk_app_framework_sdk';
|
|
39
|
+
|
|
40
|
+
const client = BAFClient.init((context) => {
|
|
41
|
+
console.log('App initialized!');
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Core Concepts
|
|
46
|
+
|
|
47
|
+
### Client Initialization
|
|
48
|
+
|
|
49
|
+
Initialize the SDK when your app loads:
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
const client = BAFClient.init((context) => {
|
|
53
|
+
// Called when app is registered and ready
|
|
54
|
+
console.log('Module:', context.module); // ticket, contact, chat, etc.
|
|
55
|
+
console.log('Object ID:', context.objectId); // Current object being viewed
|
|
56
|
+
console.log('User:', context.user.name); // Current user information
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The `init()` function returns a Client instance that provides access to all APIs.
|
|
61
|
+
|
|
62
|
+
## API Reference
|
|
63
|
+
|
|
64
|
+
### Context API
|
|
65
|
+
|
|
66
|
+
Access runtime environment information through the `context` object.
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
// Get organization details
|
|
70
|
+
client.context.getOrgId();
|
|
71
|
+
client.context.getOrgName();
|
|
72
|
+
|
|
73
|
+
// Get brand information
|
|
74
|
+
client.context.getBrandId();
|
|
75
|
+
client.context.getBrandName();
|
|
76
|
+
|
|
77
|
+
// Get current module and object
|
|
78
|
+
client.context.getModule(); // 'ticket', 'contact', 'chat', etc.
|
|
79
|
+
client.context.getObjectId(); // ID of current object
|
|
80
|
+
|
|
81
|
+
// Get user information
|
|
82
|
+
client.context.getUser(); // Full user object
|
|
83
|
+
client.context.getUserId();
|
|
84
|
+
client.context.getUserEmail();
|
|
85
|
+
client.context.getUserName();
|
|
86
|
+
client.context.getUserTimezone();
|
|
87
|
+
|
|
88
|
+
// Get plan information
|
|
89
|
+
const plan = client.context.getPlan();
|
|
90
|
+
console.log(plan.id, plan.name);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Metadata API
|
|
94
|
+
|
|
95
|
+
Access app and installation metadata through the `metadata` object.
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
// Get app information
|
|
99
|
+
client.metadata.getAppId();
|
|
100
|
+
client.metadata.getAppName();
|
|
101
|
+
client.metadata.getVersion();
|
|
102
|
+
|
|
103
|
+
// Get installation details
|
|
104
|
+
client.metadata.getInstallationId();
|
|
105
|
+
client.metadata.getInstallDate();
|
|
106
|
+
|
|
107
|
+
// Check permissions
|
|
108
|
+
if (client.metadata.hasReadAccess()) {
|
|
109
|
+
// App has read permission
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (client.metadata.hasWriteAccess()) {
|
|
113
|
+
// App has write permission
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Check status
|
|
117
|
+
client.metadata.isActive();
|
|
118
|
+
client.metadata.isEnabled();
|
|
119
|
+
|
|
120
|
+
// Get locations
|
|
121
|
+
const locations = client.metadata.getLocations();
|
|
122
|
+
console.log(locations); // ['desk.ticket.view.rightpanel', ...]
|
|
123
|
+
|
|
124
|
+
// Check if location is supported
|
|
125
|
+
if (client.metadata.isLocationSupported('desk.ticket.view.rightpanel')) {
|
|
126
|
+
// Location is supported
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Data API (get/set)
|
|
131
|
+
|
|
132
|
+
Retrieve and update data from the platform context.
|
|
133
|
+
|
|
134
|
+
#### Get Data
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
// Get single data point
|
|
138
|
+
client.get('ticket.subject').then(data => {
|
|
139
|
+
console.log(data['ticket.subject']);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Get multiple data points
|
|
143
|
+
client.get(['ticket.subject', 'ticket.description']).then(data => {
|
|
144
|
+
console.log(data['ticket.subject']);
|
|
145
|
+
console.log(data['ticket.description']);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Error handling
|
|
149
|
+
client.get('ticket.id')
|
|
150
|
+
.then(data => console.log(data))
|
|
151
|
+
.catch(error => console.error('Error:', error));
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### Set Data
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// Update single field
|
|
158
|
+
client.set('ticket.subject', 'Updated Subject')
|
|
159
|
+
.then(() => console.log('Updated!'))
|
|
160
|
+
.catch(error => console.error('Error:', error));
|
|
161
|
+
|
|
162
|
+
// Set structured data
|
|
163
|
+
client.set('ticket.customFields', {
|
|
164
|
+
field1: 'value1',
|
|
165
|
+
field2: 'value2'
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Event Handling (on/off)
|
|
170
|
+
|
|
171
|
+
Listen to platform events and react to changes.
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
// Listen for ticket updates
|
|
175
|
+
client.on('ticket.updated', (ticket) => {
|
|
176
|
+
console.log('Ticket updated:', ticket);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Listen for custom events
|
|
180
|
+
client.on('contact.selected', (contact) => {
|
|
181
|
+
console.log('Contact selected:', contact);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Remove specific listener
|
|
185
|
+
const handler = (ticket) => console.log(ticket);
|
|
186
|
+
client.on('ticket.updated', handler);
|
|
187
|
+
client.off('ticket.updated', handler);
|
|
188
|
+
|
|
189
|
+
// Remove all listeners for an event
|
|
190
|
+
client.off('ticket.updated');
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Invoke Actions (invoke)
|
|
194
|
+
|
|
195
|
+
Execute platform-exposed methods.
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
// Open a modal
|
|
199
|
+
client.invoke('modal.open', {
|
|
200
|
+
title: 'Confirm Action',
|
|
201
|
+
message: 'Are you sure?',
|
|
202
|
+
buttons: ['Yes', 'No']
|
|
203
|
+
}).then(result => {
|
|
204
|
+
console.log('User clicked:', result);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Show notification
|
|
208
|
+
client.invoke('notification.show', {
|
|
209
|
+
type: 'success',
|
|
210
|
+
message: 'Operation completed'
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Navigate to view
|
|
214
|
+
client.invoke('navigation.goto', {
|
|
215
|
+
view: 'ticket',
|
|
216
|
+
id: '12345'
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Custom Events (trigger)
|
|
221
|
+
|
|
222
|
+
Emit custom events to communicate with other parts of the system.
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
// Emit custom event
|
|
226
|
+
client.trigger('custom.dataUpdated', {
|
|
227
|
+
status: 'success',
|
|
228
|
+
recordId: '12345'
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Listen for your own events
|
|
232
|
+
client.on('custom.dataUpdated', (data) => {
|
|
233
|
+
console.log('Data updated:', data);
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Capability Check (has)
|
|
238
|
+
|
|
239
|
+
Check if a specific capability or data path is available.
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
// Check if a custom field exists
|
|
243
|
+
client.has('ticket.custom_field_123').then(exists => {
|
|
244
|
+
if (exists) {
|
|
245
|
+
console.log('Custom field is available');
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Check if a capability is available
|
|
250
|
+
client.has('capability.updateTicket').then(available => {
|
|
251
|
+
if (available) {
|
|
252
|
+
console.log('Can update tickets');
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Request API (Secure Proxy)
|
|
258
|
+
|
|
259
|
+
Make HTTP requests securely through the BoldDesk proxy.
|
|
260
|
+
|
|
261
|
+
**Important**: Storage and resources APIs are not available in Zendesk-compatible mode.
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
// Basic GET request
|
|
265
|
+
client.request.get('https://api.example.com/data')
|
|
266
|
+
.then(response => console.log(response.data))
|
|
267
|
+
.catch(error => console.error(error));
|
|
268
|
+
|
|
269
|
+
// POST request with data
|
|
270
|
+
client.request.post('https://api.example.com/tickets', {
|
|
271
|
+
subject: 'New Ticket',
|
|
272
|
+
priority: 'high'
|
|
273
|
+
}).then(response => console.log('Created:', response.data));
|
|
274
|
+
|
|
275
|
+
// Using full request method
|
|
276
|
+
client.request.request({
|
|
277
|
+
url: 'https://api.example.com/users',
|
|
278
|
+
method: 'GET',
|
|
279
|
+
headers: {
|
|
280
|
+
'Authorization': 'Bearer {{setting.api_key}}' // Secure setting placeholder
|
|
281
|
+
},
|
|
282
|
+
params: {
|
|
283
|
+
status: 'active',
|
|
284
|
+
limit: 20
|
|
285
|
+
},
|
|
286
|
+
timeout: 30000,
|
|
287
|
+
autoRetry: true,
|
|
288
|
+
maxRetry: 3
|
|
289
|
+
}).then(response => {
|
|
290
|
+
console.log('Status:', response.status);
|
|
291
|
+
console.log('Data:', response.data);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// PUT request
|
|
295
|
+
client.request.put('https://api.example.com/tickets/123', {
|
|
296
|
+
status: 'resolved'
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// DELETE request
|
|
300
|
+
client.request.delete('https://api.example.com/tickets/123');
|
|
301
|
+
|
|
302
|
+
// PATCH request
|
|
303
|
+
client.request.patch('https://api.example.com/tickets/123', {
|
|
304
|
+
priority: 'low'
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### Request Options
|
|
309
|
+
|
|
310
|
+
| Option | Type | Required | Default | Description |
|
|
311
|
+
|--------|------|----------|---------|-------------|
|
|
312
|
+
| `url` | string | Yes | - | Full URL of API endpoint |
|
|
313
|
+
| `method` | string | Yes | - | HTTP method (GET, POST, PUT, DELETE, PATCH) |
|
|
314
|
+
| `headers` | object | No | {} | HTTP headers |
|
|
315
|
+
| `params` | object | No | - | Query parameters |
|
|
316
|
+
| `body` | object/string | No | - | Request payload (POST/PUT/PATCH) |
|
|
317
|
+
| `timeout` | number | No | 15000 | Timeout in ms (max 30000) |
|
|
318
|
+
| `autoRetry` | boolean | No | true | Auto-retry on 429/5xx |
|
|
319
|
+
| `maxRetry` | number | No | 3 | Max retry attempts |
|
|
320
|
+
| `retryDelay` | number | No | 1000 | Delay between retries (ms) |
|
|
321
|
+
|
|
322
|
+
#### Request Limitations
|
|
323
|
+
|
|
324
|
+
- Maximum request payload: 100 KB
|
|
325
|
+
- Maximum response size: 6 MB
|
|
326
|
+
- Default timeout: 15 seconds (configurable up to 30 seconds)
|
|
327
|
+
- Rate limit: 50 requests per minute per app per account
|
|
328
|
+
- Binary file upload/download: Not supported
|
|
329
|
+
|
|
330
|
+
### Instance API
|
|
331
|
+
|
|
332
|
+
Manage app instances (for multi-instance widgets).
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
// Get current instance
|
|
336
|
+
const currentInstance = client.instance.current();
|
|
337
|
+
console.log('Instance ID:', currentInstance.getId());
|
|
338
|
+
|
|
339
|
+
// Get specific instance
|
|
340
|
+
const instance = client.instance.get('instance-id-123');
|
|
341
|
+
|
|
342
|
+
// Get all active instances
|
|
343
|
+
const allInstances = client.instance.all();
|
|
344
|
+
allInstances.forEach(inst => {
|
|
345
|
+
console.log(inst.getId());
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Create new instance
|
|
349
|
+
client.instance.create({
|
|
350
|
+
widgets: ['widget1', 'widget2']
|
|
351
|
+
}).then(instance => {
|
|
352
|
+
console.log('Created instance:', instance.getId());
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Send message to other instances
|
|
356
|
+
client.instance.send(['instance-1', 'instance-2'], 'update-channel', {
|
|
357
|
+
type: 'refresh',
|
|
358
|
+
data: newData
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Receive messages from other instances
|
|
362
|
+
client.instance.receive('update-channel', (message) => {
|
|
363
|
+
console.log('Received message:', message);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Resize widget
|
|
367
|
+
client.instance.resize(500); // Set height to 500px
|
|
368
|
+
|
|
369
|
+
// Close current instance
|
|
370
|
+
client.instance.close();
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Widget Locations
|
|
374
|
+
|
|
375
|
+
Apps can be placed in specific locations in the BoldDesk UI:
|
|
376
|
+
|
|
377
|
+
| Location | Area | Description |
|
|
378
|
+
|----------|------|-------------|
|
|
379
|
+
| `desk.menu.left` | Left Sidebar | Full-screen app in left menu |
|
|
380
|
+
| `desk.ticket.view.rightpanel` | Right Panel (Ticket View) | Contextual panel on ticket page |
|
|
381
|
+
| `desk.contact.view.rightpanel` | Right Panel (Contact View) | Contextual panel on contact page |
|
|
382
|
+
| `desk.contactgroup.view.rightpanel` | Right Panel (Contact Group View) | Contextual panel on contact group page |
|
|
383
|
+
| `desk.chat.view.rightpanel` | Right Panel (Chat View) | Contextual panel on chat page |
|
|
384
|
+
| `desk.cti.widget` | Bottom-Left | CTI widget in bottom-left corner |
|
|
385
|
+
|
|
386
|
+
## Manifest Configuration
|
|
387
|
+
|
|
388
|
+
Your app requires a `manifest.json` file:
|
|
389
|
+
|
|
390
|
+
```json
|
|
391
|
+
{
|
|
392
|
+
"name": "My BoldDesk App",
|
|
393
|
+
"version": "1.0.0",
|
|
394
|
+
"frameworkVersion": "1.0.0",
|
|
395
|
+
"product": "BoldDesk",
|
|
396
|
+
"developer": {
|
|
397
|
+
"name": "John Doe",
|
|
398
|
+
"contactEmail": "john@example.com",
|
|
399
|
+
"supportEmail": "support@example.com",
|
|
400
|
+
"websiteUrl": "https://myapp.com",
|
|
401
|
+
"privacyUrl": "https://myapp.com/privacy",
|
|
402
|
+
"termsOfUseUrl": "https://myapp.com/terms"
|
|
403
|
+
},
|
|
404
|
+
"widgets": [
|
|
405
|
+
{
|
|
406
|
+
"name": "Ticket Widget",
|
|
407
|
+
"location": "desk.ticket.view.rightpanel",
|
|
408
|
+
"url": "widgets/ticket/index.html"
|
|
409
|
+
}
|
|
410
|
+
],
|
|
411
|
+
"trustedDomains": [
|
|
412
|
+
"https://api.example.com",
|
|
413
|
+
"https://cdn.example.com"
|
|
414
|
+
],
|
|
415
|
+
"settings": {
|
|
416
|
+
"enablePermission": true,
|
|
417
|
+
"enableReadPermission": true,
|
|
418
|
+
"enableWritePermission": false,
|
|
419
|
+
"fields": [
|
|
420
|
+
{
|
|
421
|
+
"key": "api_key",
|
|
422
|
+
"label": "API Key",
|
|
423
|
+
"type": "text",
|
|
424
|
+
"required": true,
|
|
425
|
+
"secure": true
|
|
426
|
+
}
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
"internalAuth": {
|
|
430
|
+
"authType": "oauth",
|
|
431
|
+
"clientId": "your-client-id",
|
|
432
|
+
"clientSecret": "your-client-secret",
|
|
433
|
+
"authorizeUri": "https://auth.example.com/oauth/authorize",
|
|
434
|
+
"accessTokenUri": "https://auth.example.com/oauth/token",
|
|
435
|
+
"redirectUri": "https://myapp.com/oauth/callback",
|
|
436
|
+
"scopes": ["read", "write"]
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Security Best Practices
|
|
442
|
+
|
|
443
|
+
1. **Never expose sensitive data in client code**
|
|
444
|
+
- Use `secure: true` in manifest for sensitive settings
|
|
445
|
+
- Reference settings as `{{setting.key}}` in API requests
|
|
446
|
+
- Platform replaces values server-side
|
|
447
|
+
|
|
448
|
+
2. **Validate all data**
|
|
449
|
+
- Validate user input before API calls
|
|
450
|
+
- Check response data types and values
|
|
451
|
+
- Handle errors gracefully
|
|
452
|
+
|
|
453
|
+
3. **Use trusted domains**
|
|
454
|
+
- Only add domains to `trustedDomains` that you control
|
|
455
|
+
- Verify HTTPS certificates for external APIs
|
|
456
|
+
|
|
457
|
+
4. **Handle permissions**
|
|
458
|
+
- Check `metadata.hasReadAccess()` and `metadata.hasWriteAccess()`
|
|
459
|
+
- Gracefully degrade functionality for limited permissions
|
|
460
|
+
|
|
461
|
+
## Error Handling
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
// Handle promise errors
|
|
465
|
+
client.get('ticket.id')
|
|
466
|
+
.then(data => console.log(data))
|
|
467
|
+
.catch(error => {
|
|
468
|
+
console.error('Error:', error.message);
|
|
469
|
+
// Show user-friendly error message
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// Try-catch with async/await
|
|
473
|
+
async function fetchTicketData() {
|
|
474
|
+
try {
|
|
475
|
+
const data = await client.get('ticket.id');
|
|
476
|
+
console.log(data);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
console.error('Failed to fetch ticket:', error);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
## Development
|
|
484
|
+
|
|
485
|
+
### Build
|
|
486
|
+
|
|
487
|
+
```bash
|
|
488
|
+
npm install
|
|
489
|
+
npm run build
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
### Development Build
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
npm run build:dev
|
|
496
|
+
npm run server # Serve at http://localhost:9001
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Testing
|
|
500
|
+
|
|
501
|
+
```bash
|
|
502
|
+
npm test
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Linting
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
npm run lint
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
## Limitations & Compatibility
|
|
512
|
+
|
|
513
|
+
- **Storage API**: Not available (use secure settings or your own backend)
|
|
514
|
+
- **Resources API**: Not available (resources are managed via manifest)
|
|
515
|
+
- **Binary transfers**: Not supported via request proxy
|
|
516
|
+
- **CORS**: Handled by proxy (no direct CORS in app code)
|
|
517
|
+
- **Maximum payload**: 100 KB requests, 6 MB responses
|
|
518
|
+
- **Rate limiting**: 50 requests/minute per app per account
|
|
519
|
+
|
|
520
|
+
## Examples
|
|
521
|
+
|
|
522
|
+
### Complete Ticket Widget
|
|
523
|
+
|
|
524
|
+
```javascript
|
|
525
|
+
import BAFClient from 'bolddesk_app_framework_sdk';
|
|
526
|
+
|
|
527
|
+
const client = BAFClient.init(async (context) => {
|
|
528
|
+
console.log('App loaded for:', context.module);
|
|
529
|
+
|
|
530
|
+
try {
|
|
531
|
+
// Get ticket data
|
|
532
|
+
const data = await client.get([
|
|
533
|
+
'ticket.subject',
|
|
534
|
+
'ticket.description',
|
|
535
|
+
'ticket.status',
|
|
536
|
+
'ticket.requester.email'
|
|
537
|
+
]);
|
|
538
|
+
|
|
539
|
+
console.log('Ticket:', data);
|
|
540
|
+
|
|
541
|
+
// Listen for updates
|
|
542
|
+
client.on('ticket.updated', (ticket) => {
|
|
543
|
+
console.log('Ticket updated:', ticket);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
// Listen for status changes
|
|
547
|
+
client.on('ticket.statusChanged', (status) => {
|
|
548
|
+
console.log('New status:', status);
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
} catch (error) {
|
|
552
|
+
console.error('Error loading ticket:', error);
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### API Integration Example
|
|
558
|
+
|
|
559
|
+
```javascript
|
|
560
|
+
// Make secure API request with auth
|
|
561
|
+
client.request.post('https://api.partner.com/sync', {
|
|
562
|
+
ticketId: ticketData.id,
|
|
563
|
+
subject: ticketData.subject,
|
|
564
|
+
description: ticketData.description
|
|
565
|
+
}, {
|
|
566
|
+
headers: {
|
|
567
|
+
'Authorization': 'Bearer {{setting.partner_api_key}}',
|
|
568
|
+
'X-App-Version': '1.0.0'
|
|
569
|
+
},
|
|
570
|
+
timeout: 30000,
|
|
571
|
+
autoRetry: true
|
|
572
|
+
}).then(response => {
|
|
573
|
+
console.log('Sync successful:', response.data);
|
|
574
|
+
}).catch(error => {
|
|
575
|
+
console.error('Sync failed:', error);
|
|
576
|
+
});
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## Support
|
|
580
|
+
|
|
581
|
+
For issues, questions, or feature requests, please contact support@bolddesk.com or visit https://www.bolddesk.com/developer
|
|
582
|
+
|
|
583
|
+
## License
|
|
584
|
+
|
|
585
|
+
Licensed under the Apache License, Version 2.0. See LICENSE file for details.
|
|
586
|
+
|
|
587
|
+
Copyright © 2026 BoldDesk
|