Getting Started
Get up and running with White Rabbit in under 5 minutes.
1. Install​
npm install caller-sdk
# or
yarn add caller-sdk
# or
pnpm add caller-sdk
Requirements: Node.js 18+ or any modern browser environment.
2. Get your API key​
Go to Dashboard → Workspace → Settings → API Keys and create a new key. Label is required (e.g. Development). Leave Allowed Workflows empty for unrestricted access.
You will be shown your credentials once — copy them now:
| Variable | Value | Purpose |
|---|---|---|
WR_API_KEY | ws_... | Authenticates SDK requests |
WR_API_SECRET | base64 string | Signs requests (Ed25519 private key) |
Store them in environment variables — never hardcode credentials:
# .env
WR_API_KEY=ws_your_key_here
WR_API_SECRET=your_api_secret_here
WR_WORKFLOW_ID=your_workflow_uuid_here
3. Initialize the SDK​
import { WorkspaceClient } from 'caller-sdk';
const workspace = new WorkspaceClient({
apiKey: process.env.WR_API_KEY!,
});
That's it. The SDK handles authentication, request signing, and result streaming automatically.
4. Execute your first component​
import { WorkspaceClient, ComponentModule } from 'caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });
const result = await workspace
.call(ComponentModule.RANDOM_UUID, {})
.promise();
console.log(result.uuid); // "a4c2e8f1-39b0-4d7a-83c6-1b5f2e9d0c77"
.promise() submits the component and waits for the result using a Server-Sent Events stream — no polling, no webhooks required.
5. Query a blockchain​
import { WorkspaceClient, ComponentModule } from 'caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });
const { balance } = await workspace
.call(ComponentModule.GET_EVM_ACCOUNT_BALANCE, {
jsonRpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
tokenAddress: '0x0000000000000000000000000000000000000000', // native ETH
account: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
})
.promise();
console.log(balance); // "1000000000000000000" (wei)
6. Trigger a workflow​
For multi-step workflows, use WorkflowClient with your workspace key and the workflow UUID:
import { WorkflowClient } from 'caller-sdk';
const workflow = new WorkflowClient({
apiKey: process.env.WR_API_KEY!,
workflowId: process.env.WR_WORKFLOW_ID!,
});
// Trigger and wait for all stages to finish
const { runId } = await workflow.trigger();
const run = await workflow.waitForRun(runId);
console.log(run.status); // "COMPLETED"
console.log(run.totalUsage); // credits consumed
What's next?​
Execute Component → All delivery modes — SSE, webhook, and fire-and-forget.
Execute Workflow → Trigger, stream, and inspect workflow runs.
Component Library → Browse all 40+ components with schemas.
SDK Types → Full TypeScript type reference.
Common patterns​
Error handling​
import { WorkspaceClient, ComponentModule, CallerSDKError } from 'caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });
try {
const result = await workspace
.call(ComponentModule.BROADCAST_EVM_TRANSACTION, {
jsonRpcUrl: 'https://rpc.example.com',
signedTransaction: '0x...',
})
.promise();
} catch (err) {
if (err instanceof CallerSDKError) {
// Validation errors are thrown synchronously before any network call
console.error(err.message); // Human-readable
console.error(err.details); // Zod validation errors or API error body
}
}
Fire and forget with webhook​
import { WorkspaceClient, ComponentModule } from 'caller-sdk';
const workspace = new WorkspaceClient({ apiKey: process.env.WR_API_KEY! });
// Returns immediately — result is delivered to your webhook
const execution = await workspace
.call(ComponentModule.WAIT_FOR_EVM_TRANSACTION, {
jsonRpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
transactionHash: '0xabc123...',
})
.execute({
callbackUrl: 'https://your-app.com/webhooks/wr',
callbackSecret: process.env.WR_CALLBACK_SECRET,
});
console.log('Tracking:', execution.id); // poll or stream this ID
Live workflow progress​
import { WorkflowClient } from 'caller-sdk';
const workflow = new WorkflowClient({
apiKey: process.env.WR_API_KEY!,
workflowId: process.env.WR_WORKFLOW_ID!,
});
const { runId } = await workflow.trigger();
const sub = workflow.stream(runId, {
onUpdate(event) {
const pending = event.output.pendingStageCount ?? '?';
console.log(`${event.status} — ${pending} stages remaining`);
},
});
// sub.close() to unsubscribe early; stream auto-closes on completion