https://github.com/wyre-technology/node-datto-bcdr
Comprehensive, fully-typed Node.js/TypeScript library for the Datto BCDR (Backup Portal) API
https://github.com/wyre-technology/node-datto-bcdr
api-client backup bcdr datto kaseya msp sdk typescript
Last synced: 2 days ago
JSON representation
Comprehensive, fully-typed Node.js/TypeScript library for the Datto BCDR (Backup Portal) API
- Host: GitHub
- URL: https://github.com/wyre-technology/node-datto-bcdr
- Owner: wyre-technology
- License: apache-2.0
- Created: 2026-04-30T03:27:37.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-06-09T01:55:21.000Z (3 days ago)
- Last Synced: 2026-06-09T03:18:12.055Z (3 days ago)
- Topics: api-client, backup, bcdr, datto, kaseya, msp, sdk, typescript
- Language: TypeScript
- Size: 844 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# @wyre-technology/node-datto-bcdr
Comprehensive, fully-typed Node.js / TypeScript client library for the
[Datto BCDR (Backup Portal) API v1](https://api.datto.com/v1).
[](LICENSE)
## Features
- Full coverage of BCDR endpoints: devices, assets, backups, screenshots, offsite, alerts, activity log
- HMAC-SHA256 request signing built in (no manual header construction)
- Automatic page-based pagination via async iterators
- Token-bucket rate limiting tuned for the 120 req/min Datto BCDR limit
- Typed error hierarchy with a dedicated `DattoBcdrSignatureError` for clock-skew failures
- ESM and CommonJS dual exports, full `.d.ts` types
- Zero `any` in the public API
## Install
```bash
npm install @wyre-technology/node-datto-bcdr
```
The package is published to GitHub Packages under the `@wyre-technology` scope.
Add this to a project-local `.npmrc`:
```
@wyre-technology:registry=https://npm.pkg.github.com
```
## Quick start
```typescript
import { DattoBcdrClient } from '@wyre-technology/node-datto-bcdr';
const client = new DattoBcdrClient({
apiKey: process.env.DATTO_BCDR_PUBLIC_KEY!, // public key
apiSecretKey: process.env.DATTO_BCDR_PRIVATE_KEY!, // private key (HMAC secret)
});
// List one page of devices
const page = await client.devices.list({ page: 1, perPage: 100 });
console.log(page.pagination.totalItems);
// Iterate every device, fetching pages on demand
for await (const device of client.devices.listAll({ perPage: 250 })) {
console.log(device.serialNumber, device.hostname);
}
```
## Configuration
```typescript
new DattoBcdrClient({
apiKey: 'public-key',
apiSecretKey: 'private-key',
// Optional — override base URL (defaults to https://api.datto.com/v1)
apiUrl: 'https://api.datto.com/v1',
// Optional — tune client-side rate limiting
rateLimit: {
enabled: true,
maxRequests: 120,
windowMs: 60_000,
throttleThreshold: 0.8,
retryAfterMs: 5_000,
maxRetries: 3,
},
});
```
## Authentication: HMAC-SHA256 signing
Every request is signed with three headers:
| Header | Value |
| ------------------------- | ---------------------------------------------- |
| `X-Datto-API-Key` | The public key |
| `X-Datto-API-Timestamp` | Unix epoch seconds (UTC) |
| `X-Datto-API-Signature` | Hex-encoded HMAC-SHA256 of the canonical input |
The string-to-sign is:
```
+ "\n" + + "\n" + + "\n" +
```
For GET requests the body is the empty string. **Query parameters are sorted
alphabetically by key** before signing, and the same canonical URL is used
for both the fetch and the signature.
> **Clock skew matters.** Datto rejects requests whose timestamp is more than
> roughly 5 minutes off UTC. If your host clock drifts you will see
> `DattoBcdrSignatureError`s.
## API surface
```typescript
client.devices.list(params) // page of devices
client.devices.listAll(params) // async iterable
client.devices.get(serialNumber)
client.assets.list(serialNumber, params)
client.assets.listAll(serialNumber, params)
client.assets.get(serialNumber, agentId)
client.backups.list(serialNumber, agentId, params)
client.backups.listAll(serialNumber, agentId, params)
client.screenshots.list(serialNumber, agentId, params)
client.screenshots.listAll(serialNumber, agentId, params)
client.screenshots.getImage(serialNumber, agentId, epoch) // → Buffer (PNG)
client.offsite.get(serialNumber)
client.alerts.list(params)
client.alerts.listAll(params)
client.activity.list(params)
client.activity.listAll(params)
```
## Error handling
```typescript
import {
DattoBcdrError,
DattoBcdrAuthenticationError,
DattoBcdrSignatureError,
DattoBcdrForbiddenError,
DattoBcdrNotFoundError,
DattoBcdrRateLimitError,
DattoBcdrServerError,
} from '@wyre-technology/node-datto-bcdr';
try {
await client.devices.get('SN-1');
} catch (err) {
if (err instanceof DattoBcdrSignatureError) {
// Likely clock skew — sync NTP
} else if (err instanceof DattoBcdrRateLimitError) {
await new Promise((r) => setTimeout(r, err.retryAfter));
} else if (err instanceof DattoBcdrNotFoundError) {
// ...
} else {
throw err;
}
}
```
## Development
```bash
npm install
npm test
npm run typecheck
npm run lint
npm run build
```
## License
Apache-2.0