@dotbots-boutique/server-sdk 0.4.0 → 0.5.1

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 CHANGED
@@ -16,13 +16,13 @@ For user-facing interactions in the browser, use the frontend SDK (`@dotbots-bou
16
16
  ## Installation
17
17
 
18
18
  ```bash
19
- npm install @dotbots-boutique/server-sdk
19
+ npm install @dotbots-boutique/server-sdk@0.4.0
20
20
  ```
21
21
 
22
22
  Or in Deno:
23
23
 
24
24
  ```typescript
25
- import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk';
25
+ import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk@0.4.0';
26
26
  ```
27
27
 
28
28
  ## Environment variables
@@ -32,8 +32,7 @@ These are injected automatically by the DotBots platform — no manual configura
32
32
  ```
33
33
  DOTBOTS_APP_ID=uuid
34
34
  DOTBOTS_APP_SECRET=...
35
- PLATFORM_API_URL=https://api.dotbots.ai
36
- DOTBOTS_PROXY_URL=https://proxy.dotbots.ai
35
+ DOTBOTS_API_URL=https://api.dotbots.boutique
37
36
  ENVIRONMENT=test|prod
38
37
  ```
39
38
 
@@ -42,12 +41,12 @@ ENVIRONMENT=test|prod
42
41
  Initialise once at app startup, before handling any requests:
43
42
 
44
43
  ```typescript
45
- import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk';
44
+ import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk@0.4.0';
46
45
 
47
46
  const dotbots = new DotBotsBackend({
48
47
  appId: Deno.env.get('DOTBOTS_APP_ID')!,
49
48
  appSecret: Deno.env.get('DOTBOTS_APP_SECRET')!,
50
- apiUrl: Deno.env.get('PLATFORM_API_URL') ?? 'https://api.dotbots.ai',
49
+ apiUrl: Deno.env.get('DOTBOTS_API_URL') ?? 'https://api.dotbots.boutique',
51
50
  environment: Deno.env.get('ENVIRONMENT') ?? 'prod'
52
51
  });
53
52
 
@@ -55,7 +54,7 @@ const dotbots = new DotBotsBackend({
55
54
  await dotbots.initialize();
56
55
  ```
57
56
 
58
- `initialize()` must be called before any other methods. If `DOTBOTS_PROXY_URL` is set, the proxy URL is used directly. Otherwise it fetches the proxy URL from the platform.
57
+ `initialize()` fetches the proxy URL from the platform. It must complete before any AI calls, payments or user lookups are made.
59
58
 
60
59
  ## AI calls
61
60
 
@@ -103,16 +102,17 @@ await dotbots.aiStream(
103
102
  The `paidBy` value is configured per feature in the platform — default is `org`. Your code only needs to provide `orgId` when the feature charges the organisation:
104
103
 
105
104
  ```typescript
106
- // Feature paidBy = 'org' (default) provide orgId
105
+ // orgId is optional SDK sends default org from app secret context
106
+ await dotbots.charge('data-export', { quantity: 1 });
107
+
108
+ // Explicitly provide orgId when charging a specific org
107
109
  await dotbots.charge('data-export', {
108
110
  orgId: user.orgId,
109
111
  quantity: 1
110
112
  });
111
113
 
112
114
  // Feature paidBy = 'app' — no orgId needed
113
- await dotbots.charge('internal-job', {
114
- quantity: 1
115
- });
115
+ await dotbots.charge('internal-job');
116
116
  ```
117
117
 
118
118
  ## Getting user info
@@ -125,7 +125,7 @@ console.log(user.name, user.orgId, user.roles);
125
125
  ## Error handling
126
126
 
127
127
  ```typescript
128
- import { DotBotsBackend, DotBotsBackendError } from 'npm:@dotbots-boutique/server-sdk';
128
+ import { DotBotsBackend, DotBotsBackendError } from 'npm:@dotbots-boutique/server-sdk@0.4.0';
129
129
 
130
130
  try {
131
131
  const response = await dotbots.ai('generate-text', { messages, orgId });
@@ -150,6 +150,30 @@ try {
150
150
  }
151
151
  ```
152
152
 
153
+ ## Sending notifications
154
+
155
+ Send a notification to a user. The notification type (email, SMS, platform), templates and placeholders are configured in the DotBots platform — your code only provides the parameters.
156
+
157
+ ```typescript
158
+ await dotbots.sendNotification({
159
+ userExternalId: user.id,
160
+ userOrganisationExternalId: user.orgId,
161
+ code: 'invoice.created', // as defined in the platform
162
+ language: 'nl', // optional
163
+ parameters: { // optional — key-values for {{placeholders}}
164
+ invoiceNr: 'INV-42',
165
+ amount: '99,50'
166
+ },
167
+ important: false // optional — marks as important
168
+ });
169
+ ```
170
+
171
+ Use `code` to identify the notification — it is the recommended approach. In the platform admin you can copy a ready-made example payload per notification with the correct `code` and parameter keys already filled in.
172
+
173
+ **Always call this server-to-server** — the app secret must never appear in the browser.
174
+
175
+ ---
176
+
153
177
  ## Error codes
154
178
 
155
179
  | Code | Description |
@@ -161,6 +185,8 @@ try {
161
185
  | `CHARGE_FAILED` | Payment failed |
162
186
  | `USER_NOT_FOUND` | User not found |
163
187
  | `UNAUTHORIZED` | Invalid app secret |
188
+ | `NOTIFICATION_NOT_FOUND` | Notification code does not belong to this app |
189
+ | `NO_TEMPLATE_CONFIGURED` | No template configured for this notification |
164
190
 
165
191
  ## Frontend SDK vs Backend SDK
166
192
 
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AiResponse, BackendAiRequest, DotBotsBackendConfig, DotBotsUser } from './types';
1
+ import type { AiResponse, BackendAiRequest, DotBotsBackendConfig, DotBotsUser, SendNotificationRequest, SendNotificationResponse } from './types';
2
2
  export declare class DotBotsBackend {
3
3
  private appId;
4
4
  private appSecret;
@@ -9,7 +9,7 @@ export declare class DotBotsBackend {
9
9
  initialize(): Promise<void>;
10
10
  ai(feature: string, request: BackendAiRequest, onDelta?: (delta: string) => void): Promise<AiResponse>;
11
11
  aiStream(feature: string, request: BackendAiRequest, onDelta: (delta: string) => void, onDone?: (response: AiResponse) => void): Promise<void>;
12
- charge(featureCode: string, options: {
12
+ charge(featureCode: string, options?: {
13
13
  paidBy?: 'org' | 'app';
14
14
  orgId?: string;
15
15
  quantity?: number;
@@ -18,6 +18,7 @@ export declare class DotBotsBackend {
18
18
  amount: bigint;
19
19
  }>;
20
20
  getUser(userId: string): Promise<DotBotsUser>;
21
+ sendNotification(request: SendNotificationRequest): Promise<SendNotificationResponse>;
21
22
  private baseHeaders;
22
23
  private getProxyUrl;
23
24
  }
package/dist/client.js CHANGED
@@ -38,29 +38,9 @@ class DotBotsBackend {
38
38
  }));
39
39
  }
40
40
  async ai(feature, request, onDelta) {
41
- if (onDelta !== undefined) {
42
- return new Promise((resolve, reject) => {
43
- this.aiStream(feature, request, onDelta, resolve).catch(reject);
44
- });
45
- }
46
- const response = await fetch(`${this.getProxyUrl()}/ai/call`, {
47
- method: 'POST',
48
- headers: this.baseHeaders(),
49
- body: JSON.stringify({
50
- feature,
51
- messages: request.messages,
52
- tools: request.tools,
53
- stream: false,
54
- maxTokens: request.maxTokens,
55
- paidBy: request.paidBy,
56
- orgId: request.orgId,
57
- }),
41
+ return new Promise((resolve, reject) => {
42
+ this.aiStream(feature, request, onDelta ?? (() => { }), resolve).catch(reject);
58
43
  });
59
- if (!response.ok) {
60
- const body = (await response.json().catch(() => ({})));
61
- throw new errors_1.DotBotsBackendError(body.error ?? 'AI_CALL_FAILED', response.status);
62
- }
63
- return (await response.json());
64
44
  }
65
45
  async aiStream(feature, request, onDelta, onDone) {
66
46
  const response = await fetch(`${this.getProxyUrl()}/ai/call`, {
@@ -98,10 +78,13 @@ class DotBotsBackend {
98
78
  onDelta(data.delta);
99
79
  else if (data.type === 'done')
100
80
  onDone?.(data);
81
+ else if (data.type === 'error') {
82
+ throw new errors_1.DotBotsBackendError(data.error ?? 'AI_CALL_FAILED', 500);
83
+ }
101
84
  }
102
85
  }
103
86
  }
104
- async charge(featureCode, options) {
87
+ async charge(featureCode, options = {}) {
105
88
  const response = await fetch(`${this.getProxyUrl()}/payments/charge`, {
106
89
  method: 'POST',
107
90
  headers: this.baseHeaders(),
@@ -125,6 +108,18 @@ class DotBotsBackend {
125
108
  }
126
109
  return (await response.json());
127
110
  }
111
+ async sendNotification(request) {
112
+ const response = await fetch(`${this.getProxyUrl()}/notifications/send`, {
113
+ method: 'POST',
114
+ headers: this.baseHeaders(),
115
+ body: JSON.stringify(request),
116
+ });
117
+ if (!response.ok) {
118
+ const body = (await response.json().catch(() => ({})));
119
+ throw new errors_1.DotBotsBackendError(body.error ?? 'NOTIFICATION_FAILED', response.status);
120
+ }
121
+ return (await response.json());
122
+ }
128
123
  baseHeaders() {
129
124
  return {
130
125
  'Content-Type': 'application/json',
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { DotBotsBackend } from './client';
2
2
  export { DotBotsBackendError } from './errors';
3
- export type { AiImage, AiMessage, AiResponse, AiTool, AiToolCall, AiToolParameter, BackendAiRequest, DotBotsBackendConfig, DotBotsUser, } from './types';
3
+ export type { AiImage, AiMessage, AiResponse, AiTool, AiToolCall, AiToolParameter, BackendAiRequest, DotBotsBackendConfig, DotBotsUser, SendNotificationRequest, SendNotificationResponse, } from './types';
4
4
  export { AppSecretsStore } from './proxy/app-secrets';
5
5
  export { handleAiCall, handleCharge, handleGetUser, handleInternalAppSecrets, resolveAuth, } from './proxy/handlers';
6
6
  export type { AuthResult, CryptoHelpers, DbClient, FeatureConfig, JwtPayload, UserRecord, } from './proxy/types';
package/dist/types.d.ts CHANGED
@@ -65,3 +65,17 @@ export interface DotBotsUser {
65
65
  email?: string;
66
66
  name?: string;
67
67
  }
68
+ export interface SendNotificationRequest {
69
+ userExternalId: string;
70
+ userOrganisationExternalId: string;
71
+ code?: string;
72
+ notificationDescriptionId?: string;
73
+ language?: string;
74
+ parameters?: Record<string, string>;
75
+ important?: boolean;
76
+ }
77
+ export interface SendNotificationResponse {
78
+ id: string;
79
+ type: string;
80
+ status: string;
81
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotbots-boutique/server-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "DotBots Backend SDK — server-side AI calls, payments, and user lookups via the DotBots proxy",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",