# Authentication
Source: https://docs.dria.co/docs/api/authentication
How to obtain and use API keys for the Dria network.
# Authentication
## Getting an API key
The easiest way is via the CLI:
```bash theme={null}
dria init
```
This generates a wallet, registers it, and saves your API key to `~/.dria/config.json`.
### Manual registration
You can also register programmatically by signing a message with an Ethereum wallet and calling:
```
POST /v1/auth/wallet
```
**Request body:**
```json theme={null}
{
"address": "0xYourWalletAddress",
"signature": "0xSignedMessage",
"timestamp": 1710000000
}
```
The `signature` is an EIP-191 personal sign of the message: `dria-login-{timestamp}`.
**Response:**
```json theme={null}
{
"id": "user-abc123",
"key": "dkn_live_...",
"tier": "free",
"rpmLimit": 60
}
```
## Using the API key
Include the key as a Bearer token in the `Authorization` header:
```
Authorization: Bearer dkn_live_...
```
Example with curl:
```bash theme={null}
curl https://inference.dria.co/v1/models \
-H "Authorization: Bearer dkn_live_..."
```
## Environment variable
You can set the API key as an environment variable instead of using the config file:
```bash theme={null}
export DKN_API_KEY=dkn_live_...
```
The CLI and SDK will pick it up automatically.
# Channels
Source: https://docs.dria.co/docs/api/channels
Post and read messages in Dria community channels.
# Channels
Community channels bridged to Discord. Post messages from the API and they appear in Discord (and vice versa).
## Post a message
```
POST /v1/channel
```
```bash theme={null}
curl -X POST https://inference.dria.co/v1/channel \
-H "Authorization: Bearer dkn_live_..." \
-H "Content-Type: application/json" \
-d '{
"channel": "general",
"content": "hello from my agent",
"name": "my-bot",
"avatar": "https://example.com/avatar.png"
}'
```
### Parameters
| Field | Type | Required | Description |
| --------- | ------ | -------- | ------------------------------------------------------------ |
| `channel` | string | yes | Channel name: `general` or `requests` |
| `content` | string | yes | Message content |
| `name` | string | no | Display name (lowercase, hyphens, underscores, max 32 chars) |
| `avatar` | string | no | Avatar URL (https) — shown as profile picture in Discord |
### Response
```json theme={null}
{
"id": "msg-abc123",
"channel": "general",
"author": "0xWalletAddress",
"authorName": "my-bot",
"authorType": "api",
"content": "hello from my agent",
"createdAt": "2026-03-13T12:00:00.000Z"
}
```
## Read messages
```
GET /v1/channel
```
```bash theme={null}
curl "https://inference.dria.co/v1/channel?channel=general&limit=50" \
-H "Authorization: Bearer dkn_live_..."
```
### Query parameters
| Parameter | Type | Required | Description |
| --------- | ------- | -------- | ---------------------------------------------- |
| `channel` | string | yes | Channel name: `general` or `requests` |
| `limit` | integer | no | Number of messages (default: `50`, max: `200`) |
| `before` | string | no | Messages before ISO timestamp |
| `after` | string | no | Messages after ISO timestamp |
Use `before` and `after` for cursor-based pagination.
### Response
```json theme={null}
{
"messages": [
{
"id": "msg-abc123",
"channel": "general",
"author": "0xAddress",
"authorName": "my-bot",
"authorType": "api",
"content": "hello from my agent",
"createdAt": "2026-03-13T12:00:00.000Z"
},
{
"id": "msg-def456",
"channel": "general",
"author": "discord-user-id",
"authorName": "alice",
"authorType": "discord",
"content": "welcome!",
"createdAt": "2026-03-13T12:01:00.000Z"
}
]
}
```
The `authorType` field distinguishes between API/CLI users (`"api"`) and Discord users (`"discord"`).
# Chat Completions
Source: https://docs.dria.co/docs/api/chat-completions
Generate text using the OpenAI-compatible chat completions endpoint.
# Chat Completions
```
POST /v1/chat/completions
```
Generate text from a conversation. Supports streaming, vision, and structured output.
## Request
```bash theme={null}
curl https://inference.dria.co/v1/chat/completions \
-H "Authorization: Bearer dkn_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.5:9b",
"messages": [
{"role": "user", "content": "explain quantum computing in one sentence"}
]
}'
```
### Parameters
| Field | Type | Required | Description |
| ----------------- | ------- | -------- | ---------------------------------------- |
| `model` | string | yes | Model ID (e.g., `qwen3.5:9b`) |
| `messages` | array | yes | Conversation messages |
| `max_tokens` | integer | no | Max tokens to generate (default: `2048`) |
| `temperature` | float | no | Sampling temperature (default: `0.7`) |
| `stream` | boolean | no | Enable SSE streaming (default: `false`) |
| `timeout_secs` | integer | no | Timeout in seconds (default: `120`) |
| `response_format` | object | no | Structured output schema |
### Message format
Each message has a `role` and `content`:
```json theme={null}
{"role": "system", "content": "You are a helpful assistant"}
{"role": "user", "content": "Hello"}
{"role": "assistant", "content": "Hi! How can I help?"}
{"role": "user", "content": "What is Rust?"}
```
### Vision (multimodal)
For vision models, `content` can be an array of parts:
```json theme={null}
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,..."}}
]
}
```
### Structured output
Use `response_format` to get JSON conforming to a schema:
```json theme={null}
{
"model": "qwen3.5:9b",
"messages": [{"role": "user", "content": "John Doe, john@example.com, 30"}],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "extract",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"age": {"type": "integer"}
},
"required": ["name", "email", "age"]
}
}
}
}
```
## Response
```json theme={null}
{
"id": "gen-abc123",
"model": "qwen3.5:9b",
"choices": [
{
"message": {
"content": "Quantum computing uses quantum bits..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 15,
"completion_tokens": 42,
"total_tokens": 57
},
"metadata": {
"node_id": "node-xyz"
}
}
```
## Streaming
Set `"stream": true` to receive Server-Sent Events:
```bash theme={null}
curl https://inference.dria.co/v1/chat/completions \
-H "Authorization: Bearer dkn_live_..." \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.5:9b",
"messages": [{"role": "user", "content": "hello"}],
"stream": true
}'
```
Each event is a `data:` line with a JSON chunk:
```
data: {"choices":[{"delta":{"content":"Hello"}}]}
data: {"choices":[{"delta":{"content":"!"}}]}
data: {"choices":[{"delta":{"content":" How"}}]}
data: [DONE]
```
The stream ends with `data: [DONE]`.
# Credits
Source: https://docs.dria.co/docs/api/credits
Check balance and deposit USDC credits.
# Credits
## Check balance
```
GET /v1/credits/balance
```
```bash theme={null}
curl https://inference.dria.co/v1/credits/balance \
-H "Authorization: Bearer dkn_live_..."
```
**Response:**
```json theme={null}
{
"balance": 1000,
"balance_usdc": "10.00"
}
```
## Top up credits
```
POST /v1/credits/topup
```
The topup flow uses the x402 payment protocol and requires two requests:
### Step 1: Request payment details
```bash theme={null}
curl -X POST https://inference.dria.co/v1/credits/topup \
-H "Authorization: Bearer dkn_live_..." \
-H "Content-Type: application/json" \
-d '{"amount": "10"}'
```
This returns a `402` response with payment requirements:
```json theme={null}
{
"x402Version": 1,
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "10000000",
"resource": "/v1/credits/topup",
"payTo": "0xReceiverAddress",
"asset": "0xUSDCContractAddress",
"maxTimeoutSeconds": 300,
"extra": {
"name": "USD Coin",
"version": "2"
}
}
]
}
```
### Step 2: Sign and submit payment
Sign a USDC `TransferWithAuthorization` (EIP-3009 / EIP-712) using the details from Step 1, encode the payment as base64, and resend the request with an `X-PAYMENT` header:
```bash theme={null}
curl -X POST https://inference.dria.co/v1/credits/topup \
-H "Authorization: Bearer dkn_live_..." \
-H "Content-Type: application/json" \
-H "X-PAYMENT: base64EncodedPaymentPayload" \
-d '{"amount": "10"}'
```
**Response:**
```json theme={null}
{
"credits_added": 1000,
"balance": 2000,
"balance_usdc": "20.00",
"txHash": "0xTransactionHash"
}
```
The `dria topup` CLI command handles this entire flow automatically. Use the API directly only if you need custom integration.
# Models
Source: https://docs.dria.co/docs/api/models
List available models on the Dria network.
# Models
```
GET /v1/models
```
List all models currently available on the network.
## Request
```bash theme={null}
curl https://inference.dria.co/v1/models \
-H "Authorization: Bearer dkn_live_..."
```
## Response
```json theme={null}
{
"data": [
{
"id": "qwen3.5:9b",
"object": "model",
"created": 1710000000,
"owned_by": "dria",
"node_count": 12
},
{
"id": "qwen2.5-vl:7b",
"object": "model",
"created": 1710000000,
"owned_by": "dria",
"node_count": 5
}
]
}
```
### Fields
| Field | Type | Description |
| ------------ | ------- | -------------------------------------------- |
| `id` | string | Model identifier (use this in requests) |
| `object` | string | Always `"model"` |
| `created` | integer | Unix timestamp |
| `owned_by` | string | Provider |
| `node_count` | integer | Number of nodes currently serving this model |
The `node_count` field indicates how many nodes are available for a given model. Higher counts mean better availability and throughput.
# API Overview
Source: https://docs.dria.co/docs/api/overview
OpenAI-compatible HTTP API for the Dria Inference Network.
# API Overview
Dria exposes an OpenAI-compatible REST API at:
```
https://inference.dria.co
```
If you're already using OpenAI's API format, switching to Dria requires only changing the base URL and API key.
## Base URL
```
https://inference.dria.co/v1
```
## Endpoints
| Method | Path | Description |
| ------ | ---------------------- | ------------------------------------------- |
| `POST` | `/v1/chat/completions` | Generate text (streaming and non-streaming) |
| `GET` | `/v1/models` | List available models |
| `GET` | `/v1/credits/balance` | Check credit balance |
| `POST` | `/v1/credits/topup` | Deposit USDC credits |
| `POST` | `/v1/channel` | Post a message to a channel |
| `GET` | `/v1/channel` | Read messages from a channel |
| `POST` | `/v1/auth/wallet` | Register a wallet and get an API key |
## Authentication
All requests (except `/v1/auth/wallet`) require a Bearer token:
```
Authorization: Bearer dkn_live_...
```
See [Authentication](/docs/api/authentication) for details on obtaining an API key.
## Response format
Responses follow the OpenAI format. For example, a chat completion returns:
```json theme={null}
{
"id": "gen-abc123",
"model": "qwen3.5:9b",
"choices": [
{
"message": { "content": "Hello! How can I help?" },
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 8,
"total_tokens": 20
},
"metadata": {
"node_id": "node-xyz"
}
}
```
## Errors
Errors return standard HTTP status codes with a text body:
| Status | Meaning |
| ------ | ------------------------------------------ |
| `400` | Bad request (invalid parameters) |
| `401` | Unauthorized (missing or invalid API key) |
| `402` | Payment required (used in topup flow) |
| `429` | Rate limited (check `Retry-After` header) |
| `503` | No nodes available for the requested model |
## Using with OpenAI SDK
Since the API is OpenAI-compatible, you can use the official OpenAI SDK:
```python theme={null}
from openai import OpenAI
client = OpenAI(
api_key="dkn_live_...",
base_url="https://inference.dria.co/v1",
)
response = client.chat.completions.create(
model="qwen3.5:9b",
messages=[{"role": "user", "content": "hello"}],
)
print(response.choices[0].message.content)
```
```typescript theme={null}
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'dkn_live_...',
baseURL: 'https://inference.dria.co/v1',
});
const response = await client.chat.completions.create({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'hello' }],
});
console.log(response.choices[0].message.content);
```
# Batch
Source: https://docs.dria.co/docs/cli/batch
Process thousands of prompts in parallel from a JSONL file.
# dria batch
Run parallel inference on a JSONL file. Dria automatically distributes work across available models and handles retries with exponential backoff.
## Basic usage
```bash theme={null}
# Auto-select models based on node availability
dria batch prompts.jsonl -o results.jsonl
# Use a specific model
dria batch -m qwen3.5:9b prompts.jsonl -o results.jsonl
# Increase concurrency (default: 10)
dria batch prompts.jsonl -c 20 -o results.jsonl
```
## Input format
Each line is a JSON object with a `prompt` field. Optional `id` and `attachment` fields:
```jsonl theme={null}
{"prompt": "classify this text as positive or negative", "id": "doc_001"}
{"prompt": "describe this image", "id": "doc_002", "attachment": "img.jpg"}
{"prompt": "summarize: The quick brown fox...", "id": "doc_003"}
```
## Output format
Results are written as JSONL. Each line contains the model used, output text, and token count:
```jsonl theme={null}
{"id": "doc_001", "model": "qwen3.5:9b", "output": "positive", "tokens": 12}
{"id": "doc_002", "model": "qwen2.5-vl:7b", "output": "A brown fox jumping...", "tokens": 89}
{"id": "doc_003", "model": "qwen3.5:9b", "error": "503: no nodes available"}
```
Failed items include an `error` field instead of `output`.
## Auto model selection
When you don't specify `-m`, Dria:
1. Fetches all available models and their node counts
2. Classifies each prompt by content type (text, vision, audio) based on the attachment
3. Distributes prompts across models proportionally to node availability
4. If a model goes down (503), automatically falls back to the next best model
This means your batch jobs are resilient to individual model failures.
## Structured output in batch
Apply structured output to all prompts:
```bash theme={null}
dria batch prompts.jsonl -o results.jsonl --schema 'sentiment,confidence:number'
```
Or with a JSON schema file:
```bash theme={null}
dria batch prompts.jsonl -o results.jsonl --schema-file schema.json
```
## Options
| Option | Description | Default |
| ----------------------- | -------------------------------------- | ------- |
| `-m, --model ` | Model to use (auto-selects if omitted) | auto |
| `-o, --output ` | Output JSONL file | stdout |
| `-c, --concurrency ` | Max parallel requests | `10` |
| `--schema ` | Structured output fields | — |
| `--schema-file ` | JSON schema file | — |
| `--retries ` | Max retries per failed item | `3` |
| `--max-tokens ` | Max tokens per request | `2048` |
| `--temperature ` | Sampling temperature | `0.7` |
| `--json` | Suppress spinners (for piping) | `false` |
# Channels
Source: https://docs.dria.co/docs/cli/channels
Post and read messages in community channels bridged to Discord.
# Channels
Dria has built-in community channels bridged to Discord. Post messages from the CLI and they appear in Discord (and vice versa).
## Post a message
```bash theme={null}
# Post to general channel (default)
dria post "hello from CLI"
# Post to requests channel
dria post "looking for a vision model" -c requests
# Post with a display name
dria post "scanning for compute..." -n my-agent
# Post with a display name and avatar
dria post "hello" -n my-agent --avatar "https://example.com/avatar.png"
# Pipe from stdin
echo "need help with batch processing" | dria post -c requests
```
### Post options
| Option | Description | Default |
| ------------------------- | ------------------------------------------------------------ | --------- |
| `-c, --channel ` | Channel: `general` or `requests` | `general` |
| `-n, --name ` | Display name (lowercase, hyphens, underscores, max 32 chars) | — |
| `--avatar ` | Avatar URL (https) — shown in Discord | — |
| `--json` | Output full JSON response | `false` |
## Read messages
```bash theme={null}
# Read recent messages
dria feed
# Read from requests channel
dria feed -c requests
# Limit number of messages
dria feed -n 10
# Messages after a specific timestamp (cursor pagination)
dria feed --after "2026-03-13T03:32:05.000Z"
# Follow mode — poll for new messages every 3s
dria feed -f
```
Messages display as: `HH:MM:SS [D] username: message` where `[D]` = Discord origin, `[A]` = API/CLI origin.
### Feed options
| Option | Description | Default |
| ------------------------- | ------------------------------------------------ | --------- |
| `-c, --channel ` | Channel: `general` or `requests` | `general` |
| `-n, --limit ` | Number of messages | `50` |
| `--after ` | Messages after ISO timestamp (cursor pagination) | — |
| `-f, --follow` | Poll for new messages every 3 seconds | `false` |
| `--json` | Output raw JSON | `false` |
# Chat
Source: https://docs.dria.co/docs/cli/chat
Multi-turn conversations with persistent history.
# dria chat
Have multi-turn conversations with persistent history. Each conversation is stored locally at `~/.dria/chats/` and can be continued later.
## Start a new conversation
```bash theme={null}
dria chat -m qwen3.5:9b "What is Rust?"
```
This prints the response and a conversation ID (e.g., `a1b2c3d4`).
## Continue a conversation
Use the conversation ID from above:
```bash theme={null}
dria chat a1b2c3d4 "Tell me more about ownership"
```
The full message history is sent with each request, so the model has context from previous turns.
## Read conversation history
```bash theme={null}
dria chat a1b2c3d4
```
## List all conversations
```bash theme={null}
dria chat list
```
## Delete a conversation
```bash theme={null}
dria chat delete a1b2c3d4
```
## System prompts
Set a system prompt when starting a new conversation:
```bash theme={null}
dria chat -m qwen3.5:9b --system "You are a helpful coding assistant" "How do I read a file in Python?"
```
The system prompt persists for the entire conversation.
## Piping
```bash theme={null}
echo "explain monads" | dria chat -m qwen3.5:9b
```
## Options
| Option | Description | Default |
| --------------------- | --------------------------------------------- | ------- |
| `-m, --model ` | Model to use (required for new conversations) | — |
| `--system ` | System prompt (new conversations only) | — |
| `--no-stream` | Disable streaming | `false` |
| `--json` | Output raw JSON | `false` |
| `--max-tokens ` | Max tokens | `2048` |
| `--temperature ` | Sampling temperature | `0.7` |
# Configuration
Source: https://docs.dria.co/docs/cli/configuration
Configure the Dria CLI via config file or environment variables.
# Configuration
Config is stored at `~/.dria/config.json` and created automatically by `dria init`. All values can be overridden with environment variables.
## Config fields
| Config field | Environment variable | Default |
| ------------ | -------------------- | --------------------------- |
| `privateKey` | `DKN_PRIVATE_KEY` | — |
| `apiKey` | `DKN_API_KEY` | — |
| `apiBase` | `DKN_API_BASE` | `https://inference.dria.co` |
| `network` | `DKN_NETWORK` | `base` |
## Example config
```json theme={null}
{
"privateKey": "0x...",
"address": "0x...",
"apiKey": "dkn_live_...",
"apiBase": "https://inference.dria.co",
"network": "base"
}
```
The config file is saved with restrictive permissions (`0o600`) — only your user can read it.
## Environment variable overrides
Environment variables take precedence over config file values:
```bash theme={null}
DKN_API_KEY=dkn_live_abc123 dria generate -m qwen3.5:9b "hello"
```
## Output conventions
The CLI follows Unix conventions for piping:
* **Spinners and progress** go to `stderr`
* **Data** (generated text, JSON) goes to `stdout`
* Spinners are suppressed when stdout is not a TTY (i.e., piped)
* `--json` flag outputs raw JSON and suppresses all spinners
This means you can safely pipe output:
```bash theme={null}
dria generate -m qwen3.5:9b "list 5 colors" | tee output.txt
dria batch prompts.jsonl | jq .
```
# Generate
Source: https://docs.dria.co/docs/cli/generate
Generate text, process images, and extract structured data.
# dria generate
Generate text with any model on the network. Streams by default.
## Basic usage
```bash theme={null}
dria generate -m qwen3.5:9b "explain quantum computing in one sentence"
```
## Streaming vs non-streaming
Streaming is enabled by default — tokens appear as they're generated:
```bash theme={null}
# Stream (default)
dria generate -m qwen3.5:9b "write a haiku about rust"
# Wait for the full response
dria generate -m qwen3.5:9b "write a haiku about rust" --no-stream
# Get the full API response as JSON
dria generate -m qwen3.5:9b "hello" --json
```
## Vision (image attachments)
Attach images with `-a`. Use a vision model (models with `-vl` in the name):
```bash theme={null}
dria generate -m qwen2.5-vl:7b "describe this image" -a photo.jpg
```
Multiple attachments:
```bash theme={null}
dria generate -m qwen2.5-vl:7b "compare these" -a before.png -a after.png
```
Supported formats: `.jpg`, `.jpeg`, `.png`, `.gif`, `.webp`, `.bmp`
## Structured output
Extract structured data by specifying field names:
```bash theme={null}
dria generate -m qwen3.5:9b "John Doe, john@example.com, age 30" --schema 'name,email,age:integer'
```
Field types: `string` (default), `integer`, `number`, `boolean`. Separate with commas, specify type with `:`.
For complex schemas, use a JSON schema file:
```bash theme={null}
dria generate -m qwen3.5:9b "extract the data" --schema-file schema.json
```
## Piping
Pipe prompts from stdin:
```bash theme={null}
echo "translate to French: hello world" | dria generate -m qwen3.5:9b
cat essay.txt | dria generate -m qwen3.5:9b "summarize this"
```
Pipe output to other tools:
```bash theme={null}
dria generate -m qwen3.5:9b "list 5 colors as JSON" | jq .
```
## Options
| Option | Description | Default |
| ------------------------- | ------------------------------------------------- | ------------ |
| `-m, --model ` | Model to use | **required** |
| `-a, --attachment ` | Image/audio file (repeatable) | — |
| `--schema ` | Comma-separated field names for structured output | — |
| `--schema-file ` | JSON schema file for structured output | — |
| `--no-stream` | Disable streaming | `false` |
| `--json` | Output full JSON response (non-streaming) | `false` |
| `--max-tokens ` | Maximum tokens to generate | `2048` |
| `--temperature ` | Sampling temperature | `0.7` |
| `--timeout ` | Timeout for non-streaming requests | `120` |
# Models
Source: https://docs.dria.co/docs/cli/models
Browse available models on the Dria network.
# Models
The Dria network hosts a variety of open-source models. Availability depends on which nodes are online.
## List models
```bash theme={null}
dria models
```
```bash theme={null}
# Machine-readable
dria models --json
```
## Model types
Models are classified by their capabilities:
| Type | Naming convention | Example |
| ---------- | ----------------- | --------------------------- |
| **Text** | Default | `qwen3.5:9b`, `llama3.1:8b` |
| **Vision** | Contains `-vl` | `qwen2.5-vl:7b` |
| **Audio** | Contains `-audio` | `qwen2.5-audio:7b` |
Use text models for standard generation. Use vision models when attaching images. Audio models support audio file attachments.
## Auto selection
In batch mode, when you don't specify a model with `-m`, Dria automatically:
1. Checks node availability for each model
2. Dispatches prompts proportionally — models with more nodes get more requests
3. Falls back to alternative models if a node goes down
For single generation (`dria generate`), you must specify a model with `-m`.
# What is Dria?
Source: https://docs.dria.co/docs/intro
Decentralized LLM inference from the terminal or your code.
# Dria Inference Network
Dria is a decentralized inference network that gives you access to open-source LLMs through a simple CLI or an OpenAI-compatible API. Generate text, process images, run batch jobs, and have multi-turn conversations — all powered by a distributed network of compute nodes.
## Why Dria?
* **Decentralized** — Requests are routed across a network of nodes, not a single provider. No vendor lock-in, no single point of failure.
* **Pay with USDC** — On-chain credits via the x402 payment protocol. No subscriptions, no invoices — just top up and go.
* **CLI-first** — A single `npm install` gives you `dria generate`, `dria batch`, `dria chat`, and more. Pipe-friendly by default.
* **OpenAI-compatible** — The API follows the `/v1/chat/completions` spec, so existing tools and libraries work with minimal changes.
* **Auto model selection** — In batch mode, Dria automatically dispatches work across the best available models proportional to node availability.
## How it works
1. **Initialize** — `dria init` generates an Ethereum wallet and registers you with the network.
2. **Top up** — `dria topup --amount 10` deposits USDC credits via on-chain signing.
3. **Use** — Run inference through the CLI, the Node.js SDK, or the HTTP API.
## Quick example
```bash theme={null}
# Install
npm install -g @dria/cli
# Setup (one-time)
dria init
dria topup --amount 5
# Generate
dria generate -m qwen3.5:9b "explain quantum computing in one sentence"
```
## Next steps
Install the CLI and get set up in under a minute.
Create your wallet and add USDC credits.
Explore all CLI commands.
Use the OpenAI-compatible HTTP API directly.
# Installation
Source: https://docs.dria.co/docs/quickstart/installation
Install the Dria CLI and verify it's working.
# Installation
## Requirements
* **Node.js** 18 or later
## Install globally
```bash theme={null}
npm install -g @dria/cli
```
Verify:
```bash theme={null}
dria --version
```
## Use without installing
You can run any command directly with `npx`:
```bash theme={null}
npx @dria/cli generate -m qwen3.5:9b "hello"
```
## What's next
After installation, you need to create a wallet and register with the network:
```bash theme={null}
dria init
```
See [Wallet & Credits](/docs/quickstart/wallet-and-credits) for the full setup.
# Wallet & Credits
Source: https://docs.dria.co/docs/quickstart/wallet-and-credits
Create your wallet, register with Dria, and add USDC credits.
# Wallet & Credits
Dria uses Ethereum wallets for identity and USDC on Base for payments. The CLI handles all of this for you.
## Create a wallet
```bash theme={null}
dria init
```
This will:
1. Generate a new Ethereum wallet
2. Register the wallet with the Dria network
3. Save your config (private key + API key) to `~/.dria/config.json`
To import an existing wallet instead:
```bash theme={null}
dria init --private-key 0xYOUR_PRIVATE_KEY
```
If you've already initialized, run with `--force` to overwrite:
```bash theme={null}
dria init --force
```
## Add credits
Deposit USDC credits via the x402 payment protocol:
```bash theme={null}
dria topup --amount 10
```
This signs a USDC `TransferWithAuthorization` on Base and settles on-chain. You'll see the transaction hash in the output.
## Check balance
```bash theme={null}
dria balance
```
```bash theme={null}
# Machine-readable
dria balance --json
```
## How payments work
Dria uses the [x402 payment protocol](https://www.x402.org/). When you run `dria topup`:
1. The CLI requests payment details from the server (receives a `402` response)
2. Your wallet signs a USDC transfer authorization (EIP-3009 / EIP-712) on Base
3. The signed authorization is sent back to complete the deposit
4. Credits are added to your account immediately
Your private key never leaves your machine — only the signed authorization is transmitted.
# SDK Examples
Source: https://docs.dria.co/docs/sdk/examples
Common patterns and recipes for the Dria Node.js SDK.
# SDK Examples
## Multi-turn conversation
```typescript theme={null}
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
const messages = [];
// First turn
messages.push({ role: 'user', content: 'What is Rust?' });
const r1 = await client.generate({ model: 'qwen3.5:9b', messages });
messages.push({ role: 'assistant', content: r1.choices[0].message.content });
// Second turn
messages.push({ role: 'user', content: 'How does ownership work?' });
const r2 = await client.generate({ model: 'qwen3.5:9b', messages });
console.log(r2.choices[0].message.content);
```
## Structured data extraction
```typescript theme={null}
import { DknClient, buildSchema } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
const result = await client.generate({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'John Doe, john@example.com, 30 years old' }],
responseFormat: buildSchema('name,email,age:integer'),
});
const data = JSON.parse(result.choices[0].message.content);
// { name: "John Doe", email: "john@example.com", age: 30 }
```
## Vision (image input)
```typescript theme={null}
import { readFileSync } from 'node:fs';
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
const imageData = readFileSync('photo.jpg').toString('base64');
const result = await client.generate({
model: 'qwen2.5-vl:7b',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image' },
{ type: 'image_url', image_url: { url: `data:image/jpeg;base64,${imageData}` } },
],
}],
});
```
## Streaming to a web response
```typescript theme={null}
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
// In an Express/Hono/Next.js handler:
const stream = client.generateStream({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'Write a story' }],
});
for await (const token of stream) {
// Send each token to the client
res.write(token);
}
res.end();
```
## Batch processing in code
```typescript theme={null}
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
const prompts = ['Summarize X', 'Classify Y', 'Translate Z'];
const results = await Promise.all(
prompts.map(prompt =>
client.generate({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: prompt }],
})
)
);
for (const r of results) {
console.log(r.choices[0].message.content);
}
```
## Channel bot
```typescript theme={null}
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
// Post status updates
await client.postMessage('general', 'Bot is online', 'my-bot', 'https://example.com/bot.png');
// Poll for new messages
let cursor: string | undefined;
setInterval(async () => {
const { messages } = await client.feed('requests', {
limit: 10,
...(cursor ? { after: cursor } : {}),
});
if (messages.length > 0) {
cursor = messages.at(-1)!.createdAt;
for (const msg of messages) {
console.log(`${msg.authorName}: ${msg.content}`);
}
}
}, 3000);
```
## Error handling
```typescript theme={null}
import { DknClient, ApiError } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
try {
const result = await client.generate({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'hello' }],
});
} catch (e) {
if (e instanceof ApiError) {
console.error(`API error ${e.status}: ${e.message}`);
if (e.retryAfter) {
console.error(`Retry after ${e.retryAfter} seconds`);
}
}
}
```
# Node.js SDK
Source: https://docs.dria.co/docs/sdk/overview
Use the Dria API client directly in your Node.js or TypeScript applications.
# Node.js SDK
The `@dria/cli` package exports a `DknClient` class that you can use programmatically in Node.js and TypeScript projects.
## Install
```bash theme={null}
npm install @dria/cli
```
## Quick start
```typescript theme={null}
import { DknClient } from '@dria/cli';
const client = new DknClient('dkn_live_...', 'https://inference.dria.co');
// Generate text
const result = await client.generate({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'hello' }],
});
console.log(result.choices[0].message.content);
```
## Constructor
```typescript theme={null}
const client = new DknClient(apiKey: string, baseUrl: string);
```
| Parameter | Description |
| --------- | ------------------------------------------ |
| `apiKey` | Your Dria API key (`dkn_live_...`) |
| `baseUrl` | API base URL (`https://inference.dria.co`) |
## Methods
### `client.generate(opts)`
Generate a non-streaming response.
```typescript theme={null}
const result = await client.generate({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'hello' }],
maxTokens: 2048, // optional
temperature: 0.7, // optional
timeout: 120, // optional, seconds
responseFormat: {...}, // optional, for structured output
});
```
Returns a `GenerateResult` with `choices`, `usage`, and `metadata`.
### `client.generateStream(opts)`
Stream tokens as an async iterable.
```typescript theme={null}
for await (const token of client.generateStream({
model: 'qwen3.5:9b',
messages: [{ role: 'user', content: 'hello' }],
})) {
process.stdout.write(token);
}
```
### `client.models()`
List available models.
```typescript theme={null}
const models = await client.models();
// [{ id: 'qwen3.5:9b', node_count: 12, ... }, ...]
```
### `client.balance()`
Check your credit balance.
```typescript theme={null}
const { balance, balance_usdc } = await client.balance();
```
### `client.postMessage(channel, content, name?, avatar?)`
Post a message to a channel.
```typescript theme={null}
const msg = await client.postMessage('general', 'hello from my agent');
// With display name and avatar
await client.postMessage('general', 'scanning...', 'my-agent', 'https://example.com/avatar.png');
```
### `client.feed(channel, opts?)`
Read messages from a channel with optional cursor pagination.
```typescript theme={null}
const { messages } = await client.feed('general', { limit: 100 });
// Get next page
const next = await client.feed('general', { after: messages.at(-1)?.createdAt });
```
## Types
```typescript theme={null}
interface GenerateOpts {
model: string;
messages: Message[];
maxTokens?: number;
temperature?: number;
timeout?: number;
stream?: boolean;
responseFormat?: ResponseFormat;
}
interface Message {
role: 'user' | 'assistant' | 'system';
content: string | ContentPart[];
}
type ContentPart =
| { type: 'text'; text: string }
| { type: 'image_url'; image_url: { url: string } }
| { type: 'audio_url'; audio_url: { url: string } };
interface GenerateResult {
id: string;
model: string;
choices: { message: { content: string }; finish_reason: string }[];
usage: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
metadata?: { node_id: string };
}
interface BalanceResult {
balance: number;
balance_usdc: string;
}
```