# @dzbot/sdk

Your own bot or website, with dzbot as the backend. dzbot already reads your Nitrado server's logs and runs players, linked accounts and alt detection, wallets, the shop and delivery, tickets and factions — the SDK hands all of it to your code.

[Start from the starter bot](https://github.com/siemendev/dzbot-starter) [npm](https://www.npmjs.com/package/@dzbot/sdk)

> The SDK is at 0.x: names may still change until 1.0. It runs on Node 20+, Deno, Bun, Workers and in every modern browser.

## Install

```
npm install @dzbot/sdk
```

The API is part of dzbot Pro: your server needs a Pro plan (or the free trial) for its apps to work.

## A key or Sign in with dzbot

Everything starts with an [app](https://developers.dzbot.de/api/apps) in your server's admin area under **Developers**. It gives you two ways in, and you can use both:

### API key

Your bot or backend acts for itself, with the rights you gave the key. For Discord bots, scripts and servers with their own user management. Secret: server side only.

### Sign in with dzbot

A player signs in on your server's dzbot page and comes back to your app; it acts with their rights. For websites — even without a backend of your own. See [Sign in with dzbot](https://developers.dzbot.de/sdk/oauth).

## new Dzbot(options)

```
import { Dzbot } from '@dzbot/sdk'

const dzbot = new Dzbot({ server: 'your-server', apiKey: process.env.DZBOT_API_KEY })
const me = await dzbot.me() // who the key is, on which server, with which rights
```

| Option | Meaning |
| --- | --- |
| `server` | The subdomain of your server's dzbot page (`your-server` for your-server.dzbot.de). Sent as `X-Server-Subdomain` |
| `apiKey` | A key `dzk_…`. Refused in a browser |
| `oauth` | An `OAuthClient` with a signed-in user, instead of a key |
| `baseUrl` | Default `https://api.dzbot.de` |
| `fetch` | Your own fetch, e.g. for tests |
| `userAgent` | Appended to the SDK's user agent, e.g. `my-bot/1.0` |

| Method | Does |
| --- | --- |
| `me() → Identity` | `GET /api/developer/me`: `kind` (`api_key` or `user`), `server`, `user`, `player` (with `gameId` and `mainPlayerId`), `accounts` (the player and their device-linked alts on the server), `rights`, `app` |
| `request(method, path, { query, body })` | Any endpoint; the answer's JSON |
| `get(path, query?)` / `post(path, body?)` | Shortcuts |
| `search(type, filter?)` | Every row of a list — see [Search](#search) |
| `events.subscribe(names, handler)` | Live events — see [Live events](https://developers.dzbot.de/sdk/live) |
| `configuration()` | A configuration for the typed client — see [Every endpoint](#typed) |

## Search

Every list in dzbot is a type of the [search](https://developers.dzbot.de/api/search). `search()` walks all pages for you; `searchPage()` returns one.

```
for await (const order of dzbot.search('order', { status: ['pending', 'delivered'], created: '7d', sort: '-created' })) {
  console.log(order.code, order.label, order.fields)
}
```

With a key the admin lists are searched (`/api/admin/search`), with a signed-in player what the player sees (`/api/search`); pass `{ area: 'admin' }` as third argument for a staff member's admin lists.

## Helpers

| Helper | Does | Needs |
| --- | --- | --- |
| `players.findByDiscordId(id)` | The player linked to this Discord user, or `null`: `{ id, name, balance, fields }` | `admin.players.view` |
| `players.findByGameAccount(id)` | The player with this Steam64, DayZ or console id | `admin.players.view` |
| `wallet.credit(playerId, amount, reason)` | Adds money to the player's wallet; `{ newBalance }` | `admin.players.change_money` |
| `wallet.debit(playerId, amount, reason)` | Takes money out | `admin.players.change_money` |
| `shop.order({ items, placeId?, position?, factionId? })` | Orders for the signed-in player, paid from their balance; refuses while their cart holds something | Sign in with dzbot, `player.shop.checkout` |

A player's wallet belongs to the organization: one balance shared by all its servers.

## Errors and retries

Every answer outside 2xx throws a `DzbotError` with `status`, `code` (the API's `error`) and `message`. `RateLimitError` (429) carries `retryAfter` in seconds, `PermissionError` (403) the missing `right` when the API names it. A server not on Pro answers `402 feature_requires_pro`.

Reads (`GET`) are retried twice: after `Retry-After` on 429 (up to 60 s) and on 502, 503 and 504. Writes are never retried. With a signed-in user, a 401 refreshes the token once.

## Every endpoint, typed

`@dzbot/sdk/api` is a client generated from the [OpenAPI spec](https://api.dzbot.de/api/docs.json) — the same code the dzbot app runs on. Hand it the client's configuration:

```
import { AdminApi } from '@dzbot/sdk/api'

const admin = new AdminApi(dzbot.configuration())
```

The API carries no stability promise yet: endpoints can change between dzbot releases, and the [migration notes](https://developers.dzbot.de/api/migration) say how. The helpers and the generated client are updated with the SDK.

---

Web page: https://developers.dzbot.de/sdk/ · All pages: https://developers.dzbot.de/llms.txt
