> For the complete documentation index, see [llms.txt](https://docs.usedecentral.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.usedecentral.org/integrations/javascript-sdk.md).

# JavaScript and TypeScript SDK

The `@usedecentral/sdk` package provides typed access to the Decentral API with wallet-native authentication, structured streaming, React hooks, and on-chain receipt retrieval.

***

## Installation

```bash
npm install @usedecentral/sdk
# or
pnpm add @usedecentral/sdk
# or
yarn add @usedecentral/sdk
```

***

## Basic usage

```typescript
import { DecentralClient } from "@usedecentral/sdk"

const client = new DecentralClient({
    apiKey: process.env.DECENTRAL_API_KEY
})

// Non-streaming chat
const response = await client.chat.completions.create({
    model: "qwen3-8b",
    messages: [{ role: "user", content: "What is WebGPU?" }]
})

console.log(response.choices[0].message.content)
console.log("Job ID:", response.jobId)
console.log("Settlement tx:", response.settlementTx)
```

***

## Streaming

```typescript
const stream = await client.chat.completions.create({
    model: "llama-3.3-70b",
    messages: [{ role: "user", content: "Explain Solana's validator architecture." }],
    stream: true
})

for await (const chunk of stream) {
    process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
}

// After the stream ends, the receipt is available
const receipt = stream.receipt
console.log("Settlement:", receipt.settlementTx)
console.log("Worker:", receipt.workerAddress)
console.log("Credits used:", receipt.creditsCharged)
```

***

## On-chain receipts

Every completed job has an on-chain receipt. Retrieve it from the stream object after completion, or fetch it later by job ID.

```typescript
// From a completed stream
const receipt = stream.receipt
// {
//   jobId: "job_8fx2kp3m...",
//   model: "llama-3.3-70b",
//   tier: "max",
//   creditsCharged: 40,
//   usdcValue: 0.40,
//   workerAddress: "9WzDXwBc...",
//   escrowTx: "4xKTgFZb...",
//   settlementTx: "7mNPqRTv...",
//   slot: 321847293,
//   proofHash: "sha256:a1b2c3d4..."
// }

// Fetch any job's receipt by ID
const job = await client.jobs.get("job_8fx2kp3m9qrstvwxyz")
console.log(job.onChain.settlementTx)

// Link directly to Solana Explorer
const explorerUrl = `https://explorer.solana.com/tx/${job.onChain.settlementTx}`
```

***

## React hooks

Import from `@usedecentral/sdk/react`.

```typescript
import { useDecentralChat } from "@usedecentral/sdk/react"

function ChatComponent() {
    const { send, messages, status, balance, lastReceipt } = useDecentralChat({
        model: "qwen3-8b",
        apiKey: process.env.NEXT_PUBLIC_DECENTRAL_API_KEY
    })

    const handleSend = async (text: string) => {
        await send(text)
    }

    return (
        <div>
            <p>Credits remaining: {balance?.creditsRemaining}</p>
            <p>Status: {status}</p>

            {messages.map((msg, i) => (
                <div key={i}>
                    <strong>{msg.role}:</strong> {msg.content}
                </div>
            ))}

            {lastReceipt && (
                <p>
                    Last job settled:{" "}
                    <a href={`https://explorer.solana.com/tx/${lastReceipt.settlementTx}`}>
                        View on Solana
                    </a>
                </p>
            )}
        </div>
    )
}
```

### Hook API

```typescript
const {
    send,           // (message: string) => Promise<void>
    messages,       // Array<{ role: string; content: string }>
    status,         // "idle" | "streaming" | "settling" | "error"
    balance,        // { creditsRemaining: number; usdcValue: number } | null
    lastReceipt,    // JobReceipt | null
    error,          // Error | null
    reset           // () => void, clears the conversation
} = useDecentralChat({
    model: "qwen3-8b",
    apiKey: "dcntrl_live_...",
    systemPrompt: "You are a helpful assistant.",  // optional
    onComplete: (receipt) => { ... },              // optional callback
    onError: (error) => { ... }                    // optional callback
})
```

***

## Account and credits

```typescript
const account = await client.account.get()
// {
//   wallet: "7xKXtg2C...",
//   creditsRemaining: 1420,
//   usdcValue: 14.20,
//   lastTopupAt: Date
// }

// List recent jobs
const jobs = await client.jobs.list({ limit: 10, status: "settled" })
for (const job of jobs.data) {
    console.log(`${job.id}: ${job.model} - ${job.creditsCharged} credits`)
}
```

***

## Webhooks

```typescript
import { verifyWebhookSignature, type DecentralWebhookEvent } from "@usedecentral/sdk"

// Verify and parse a webhook in an Express handler
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
    const signature = req.headers["decentral-signature"] as string
    const isValid = verifyWebhookSignature(
        req.body.toString(),
        signature,
        process.env.WEBHOOK_SECRET!
    )

    if (!isValid) {
        return res.status(400).json({ error: "Invalid signature" })
    }

    const event: DecentralWebhookEvent = JSON.parse(req.body.toString())

    switch (event.event) {
        case "job.completed":
            console.log("Job settled:", event.data.settlementTx)
            break
        case "credit.low":
            console.log("Credits low:", event.data.creditsRemaining)
            break
    }

    res.json({ received: true })
})
```

***

## Client configuration

```typescript
const client = new DecentralClient({
    apiKey: "dcntrl_live_...",       // required
    baseURL: "https://api.usedecentral.org/v1",  // default, override for testing
    timeout: 180_000,                 // request timeout in ms (default: 120000)
    maxRetries: 3,                    // auto-retry on 5xx and 503 (default: 2)
    defaultHeaders: {                 // added to every request
        "x-app-version": "1.0.0"
    }
})
```

***

## TypeScript types

Key types exported from `@usedecentral/sdk`:

```typescript
import type {
    ChatCompletion,
    ChatCompletionChunk,
    ChatCompletionCreateParams,
    JobReceipt,
    Job,
    Account,
    Model,
    DecentralModel,       // extends Model with tier, workers, latency
    WebhookEvent,
    JobCompletedEvent,
    CreditLowEvent
} from "@usedecentral/sdk"
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.usedecentral.org/integrations/javascript-sdk.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
