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

# JavaScript and TypeScript SDK

`@robincompute/sdk` is the official typed client for the RobinCompute API. Chat completions are the start; it also handles wallet-native authentication, structured streaming, React hooks, and the on-chain receipt behind every settled job, with no header parsing required.

***

## Installing

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

***

## First request

```typescript
import { RobinComputeClient } from "@robincompute/sdk"

const client = new RobinComputeClient({
    apiKey: process.env.ROBINCOMPUTE_API_KEY
})

// A plain, non-streaming chat completion
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 how optimistic rollups work." }],
    stream: true
})

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

// Once the stream finishes, its receipt is populated
const receipt = stream.receipt
console.log("Settlement:", receipt.settlementTx)
console.log("Worker:", receipt.workerAddress)
console.log("Credits used:", receipt.creditsCharged)
```

***

## On-chain receipts

Every settled job leaves a receipt on Robinhood Chain: the record, not our word for it. Grab it off the stream object once streaming ends, or look any past job up by ID.

```typescript
// Off a finished stream
const receipt = stream.receipt
// {
//   jobId: "job_8fx2kp3m...",
//   model: "llama-3.3-70b",
//   tier: "max",
//   creditsCharged: 40,
//   usdgValue: 0.40,
//   workerAddress: "0x9e2d5b7a814cf3068d91e4a2b5c60f7d83a41c9e",
//   escrowTx: "0x4b8e2f7c9a1d6053e8b24f9c7a30d1e5f6829c4b7d0a3e8f1c5b9d2a6e470381",
//   settlementTx: "0xd3a91c5e7f2b8064a1c9e5d27b483f0a6e1c8b5d9f2a7043e6b1d8c4a95f7e20",
//   blockNumber: 3218472,
//   proofHash: "sha256:a1b2c3d4..."
// }

// Or look up any past job by its ID
const job = await client.jobs.get("job_8fx2kp3m9qrstvwxyz")
console.log(job.onChain.settlementTx)

// Build a Blockscout explorer link for the settlement
const explorerUrl = `https://robinhoodchain.blockscout.com/tx/${job.onChain.settlementTx}`
```

***

## React hooks

React bindings ship in the same package, under the `@robincompute/sdk/react` entry point.

```typescript
import { useRobinComputeChat } from "@robincompute/sdk/react"

function ChatComponent() {
    const { send, messages, status, balance, lastReceipt } = useRobinComputeChat({
        model: "qwen3-8b",
        apiKey: process.env.NEXT_PUBLIC_ROBINCOMPUTE_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://robinhoodchain.blockscout.com/tx/${lastReceipt.settlementTx}`}>
                        View on Blockscout
                    </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; usdgValue: number } | null
    lastReceipt,    // JobReceipt | null
    error,          // Error | null
    reset           // () => void, wipes the conversation
} = useRobinComputeChat({
    model: "qwen3-8b",
    apiKey: "rcompute_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: "0x7c41f9b8d2a6e3054cf18a9b62d47e0c93f5a1b8",
//   creditsRemaining: 1420,
//   usdgValue: 14.20,
//   lastTopupAt: Date
// }

// Page through 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 RobinComputeWebhookEvent } from "@robincompute/sdk"

// Validate the signature and handle the event inside an Express route
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
    const signature = req.headers["robincompute-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: RobinComputeWebhookEvent = 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 options

```typescript
const client = new RobinComputeClient({
    apiKey: "rcompute_live_...",       // required
    baseURL: "https://api.robincompute.org/v1",  // the default; point elsewhere for testing
    timeout: 180_000,                 // per-request timeout in ms (default: 120000)
    maxRetries: 3,                    // retries automatically on 5xx and 503 (default: 2)
    defaultHeaders: {                 // merged into every request
        "x-app-version": "1.0.0"
    }
})
```

***

## TypeScript types

The types you will reach for most, exported from `@robincompute/sdk`:

```typescript
import type {
    ChatCompletion,
    ChatCompletionChunk,
    ChatCompletionCreateParams,
    JobReceipt,
    Job,
    Account,
    Model,
    RobinComputeModel,       // Model plus tier, workers, latency
    WebhookEvent,
    JobCompletedEvent,
    CreditLowEvent
} from "@robincompute/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.robincompute.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.
