@dotbots-boutique/server-sdk
v1.8.0
Published
DotBots Backend SDK — server-side AI calls, payments, and user lookups via the DotBots proxy
Maintainers
Readme
@dotbots-boutique/server-sdk
The official backend SDK for DotBots Boutique. Use this package to make AI calls, trigger payments and retrieve user information from your Deno backend — without a browser or user session.
When to use this SDK
Use the backend SDK when logic must run server-side:
- Webhook handlers
- Background jobs and scheduled tasks
- Multi-step backend processing flows
- Any operation that runs without a user actively waiting in the browser
For user-facing interactions in the browser, use the frontend SDK (@dotbots-boutique/auth-sdk).
Installation
npm install @dotbots-boutique/server-sdkAlways use the latest version — check the current version before installing:
https://www.npmjs.com/package/@dotbots-boutique/server-sdk
Pin the exact version in package.json — do not use @latest. Update regularly.
Or in Deno:
import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk';Environment variables
These are injected automatically by the DotBots platform — no manual configuration needed:
DOTBOTS_APP_ID=uuid
DOTBOTS_APP_SECRET=...
DOTBOTS_API_URL=https://api.dotbots.boutique
ENVIRONMENT=test|prodSetup
Initialise once at app startup, before handling any requests:
import { DotBotsBackend } from 'npm:@dotbots-boutique/server-sdk';
const dotbots = new DotBotsBackend({
appId: Deno.env.get('DOTBOTS_APP_ID')!,
appSecret: Deno.env.get('DOTBOTS_APP_SECRET')!,
apiUrl: Deno.env.get('DOTBOTS_API_URL') ?? 'https://api.dotbots.boutique',
environment: Deno.env.get('ENVIRONMENT') ?? 'prod'
});
// Must be called before any other methods
await dotbots.initialize();initialize() fetches the proxy URL from the platform. It must complete before any AI calls, payments or user lookups are made.
AI calls
// orgId required when feature is configured as paidBy = 'org' in the platform (default)
const response = await dotbots.ai('generate-summary', {
messages: [
{ role: 'user', content: 'Summarise the following document: ...' }
],
orgId: user.orgId
});
console.log(response.content);
console.log(`Cost: ${response.cost.tokens} tokens`);
// Feature configured as paidBy = 'app' in platform — no orgId needed
const response = await dotbots.ai('internal-classification', {
messages: [{ role: 'user', content: 'Classify this text...' }]
});Streaming
let result = '';
await dotbots.aiStream(
'generate-text',
{
messages: [{ role: 'user', content: 'Write a report...' }],
orgId: user.orgId
},
(delta) => {
result += delta;
// optionally forward to client via SSE
},
(finalResponse) => {
console.log(`Completed — cost: ${finalResponse.cost.tokens} tokens`);
}
);Payments
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:
// orgId is optional — SDK sends default org from app secret context
await dotbots.charge('data-export', { quantity: 1 });
// Explicitly provide orgId when charging a specific org
await dotbots.charge('data-export', {
orgId: user.orgId,
quantity: 1
});
// Feature paidBy = 'app' — no orgId needed
await dotbots.charge('internal-job');Getting user info
const user = await dotbots.getUser(userId);
console.log(user.name, user.orgId, user.roles);Error handling
import { DotBotsBackend, DotBotsBackendError } from 'npm:@dotbots-boutique/server-sdk';
try {
const response = await dotbots.ai('generate-text', { messages, orgId });
} catch (error) {
if (error instanceof DotBotsBackendError) {
switch (error.code) {
case 'AI_INSUFFICIENT_BALANCE':
// Org has no tokens — notify user
break;
case 'AI_FEATURE_NOT_FOUND':
// Feature not configured in platform — developer error
console.error('AI feature not configured in DotBots platform');
break;
case 'AI_CALL_FAILED':
// Provider error — retry or fallback
break;
case 'UNAUTHORIZED':
// Invalid app secret — check DOTBOTS_APP_SECRET env variable
break;
}
}
}Sending notifications
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.
const notificationAppSecret = Deno.env.get('DOTNOTIFICATIONS_APP_SECRET')!;
// Platform notification — userExternalId required
await dotbots.sendNotification({
notificationAppSecret,
userOrganisationExternalId: user.orgId,
userExternalId: user.id,
code: 'invoice.created',
language: 'nl',
parameters: { invoiceNr: 'INV-42', amount: '99,50' }
});
// Email notification — email required
await dotbots.sendNotification({
notificationAppSecret,
userOrganisationExternalId: user.orgId,
email: user.email,
code: 'invoice.created',
parameters: { invoiceNr: 'INV-42', amount: '99,50' }
});
// SMS notification — phone required
await dotbots.sendNotification({
notificationAppSecret,
userOrganisationExternalId: user.orgId,
phone: user.phone,
code: 'invoice.created',
parameters: { invoiceNr: 'INV-42', amount: '99,50' }
});Which identifier to include depends on the notification type configured in dotNotifications. Use code to identify the notification. In the platform admin you can copy a ready-made example payload per notification with the correct code and parameter keys.
Always call this server-to-server — the app secret must never appear in the browser.
Error codes
| Code | Description |
|------|-------------|
| AI_FEATURE_NOT_FOUND | Feature not configured in the platform |
| AI_PROVIDER_NOT_CONFIGURED | API key not set for the AI provider |
| AI_INSUFFICIENT_BALANCE | Organisation balance is 0 and awaiting top-up |
| AI_CALL_FAILED | AI provider returned an error |
| CHARGE_FAILED | Payment failed |
| USER_NOT_FOUND | User not found |
| UNAUTHORIZED | Invalid app secret |
| NOTIFICATION_NOT_FOUND | Notification code does not belong to this app |
| NO_TEMPLATE_CONFIGURED | No template configured for this notification |
Frontend SDK vs Backend SDK
| | Frontend SDK | Backend SDK |
|--|-------------|-------------|
| Package | @dotbots-boutique/auth-sdk | @dotbots-boutique/server-sdk |
| Runtime | Browser | Deno / Node |
| Auth | User JWT (iframe) | App secret |
| AI calls | ✅ | ✅ |
| Payments | ✅ | ✅ |
| User context | Automatic | Manual via orgId |
| Use case | User interactions | Webhooks, jobs, server logic |
Rule of thumb: if there is a user actively waiting in the browser, use the frontend SDK. If the logic runs in the background or server-side, use the backend SDK.
Security
DOTBOTS_APP_SECRETis injected by the platform and must never be logged, returned in API responses or stored anywhere other than environment variables.- The proxy URL is fetched dynamically at startup — never hardcode it.
- All communication between the backend SDK and the proxy is server-to-server. The app secret is never exposed to the browser.
