
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@renderinc/sdk
Advanced tools
The official TypeScript SDK for Render Workflows, providing a simple and intuitive API for managing and executing tasks.
npm install @renderinc/sdk
Or with yarn:
yarn add @renderinc/sdk
Or with pnpm:
pnpm add @renderinc/sdk
Or with Bun:
bun add @renderinc/sdk
Use the Render SDK to run tasks and monitor their execution:
import { Render } from '@renderinc/sdk';
// Create a Render SDK instance (uses RENDER_API_KEY from environment)
const render = new Render();
// Run a task and wait for completion
const result = await render.workflows.runTask('my-workflow/my-task', [42, 'hello']);
console.log('Status:', result.status);
console.log('Results:', result.results);
// Or start a task and decide when to await the result
const run = await render.workflows.startTask('my-workflow/my-task', [42, 'hello']);
console.log('Task run ID:', run.taskRunId);
const details = await run.get();
// List recent task runs
const taskRuns = await render.workflows.listTaskRuns({ limit: 10 });
Alternatively, you can create a workflows client directly:
import { createWorkflowsClient } from '@renderinc/sdk/workflows';
const client = createWorkflowsClient();
const result = await client.runTask('my-workflow/my-task', [42, 'hello']);
Define tasks that can be executed by the workflow system:
import { task, startTaskServer } from '@renderinc/sdk/workflows';
// Simple task
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
// Async task with subtask execution
task(
{ name: 'addSquares' },
async function addSquares(a: number, b: number): Promise<number> {
const result1 = await square(a);
const result2 = await square(b);
return result1 + result2;
}
);
// Task with custom options
task(
{
name: 'retryableTask',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
backoffScaling: 1.5,
},
timeoutSeconds: 86400, // 24h
plan: 'starter',
},
async function retryableTask(input: string): Promise<string> {
// Task implementation
return input.toUpperCase();
}
);
// The task server starts automatically when running in a workflow environment
// (when RENDER_SDK_SOCKET_PATH is set). No need to call startTaskServer() explicitly.
//
// To disable auto-start, set RENDER_SDK_AUTO_START=false in your environment.
new Render(options?)Creates a new Render SDK instance with access to all Render products.
Options:
token?: string - API token (defaults to RENDER_API_KEY env var)baseUrl?: string - Base URL (defaults to https://api.render.com)useLocalDev?: boolean - Use local development modelocalDevUrl?: string - Local development URLownerId?: string - Default owner ID for object storage (falls back to RENDER_WORKSPACE_ID env var)region?: string - Default region for object storage (falls back to RENDER_REGION env var)Properties:
workflows - WorkflowsClient instance for managing workflow tasksexperimental - ExperimentalClient instance for object storage and other experimental APIsExample:
import { Render } from '@renderinc/sdk';
const render = new Render({
token: 'your-api-token',
baseUrl: 'https://api.render.com',
});
// Access workflows client
const result = await render.workflows.runTask('my-workflow/task', [42]);
The workflows client is accessible via render.workflows or can be created directly using createWorkflowsClient:
import { createWorkflowsClient } from '@renderinc/sdk/workflows';
const client = createWorkflowsClient({
token: 'your-api-token',
baseUrl: 'https://api.render.com',
});
render.workflows.runTask(taskSlug, inputData, signal?)Runs a task and waits for completion.
Parameters:
taskSlug: string - Task slug in format "workflow-slug/task-name"inputData: any[] - Input data as array of parameterssignal?: AbortSignal - Optional abort signal for cancellationReturns: Promise<TaskRunDetails>
Example:
const render = new Render();
const result = await render.workflows.runTask('my-workflow/square', [5]);
console.log('Results:', result.results);
render.workflows.startTask(taskSlug, inputData, signal?)Starts a task run and returns a TaskRunResult. Results are not streamed until you call .get() on the returned result. Use this when you need the task run ID, want to defer awaiting, or want fire-and-forget.
Parameters:
taskSlug: string - Task slug in format "workflow-slug/task-name"inputData: any[] - Input data as array of parameterssignal?: AbortSignal - Optional abort signal for cancellationReturns: Promise<TaskRunResult>
Example:
const render = new Render();
// Start a task and grab its ID
const run = await render.workflows.startTask('my-workflow/square', [5]);
console.log('Task run ID:', run.taskRunId);
// Await the result when you're ready
const result = await run.get();
console.log('Results:', result.results);
render.workflows.taskRunEvents(taskRunIds, signal?)Streams task run events as an async iterable. Yields a TaskRunDetails for each terminal event (completed, failed, or canceled) received on the stream.
Parameters:
taskRunIds: string[] - One or more task run IDs to subscribe tosignal?: AbortSignal - Optional abort signal for cancellationReturns: AsyncGenerator<TaskRunDetails>
Example:
const render = new Render();
const run1 = await render.workflows.startTask('my-workflow/square', [3]);
const run2 = await render.workflows.startTask('my-workflow/square', [6]);
// The stream stays open until you break or abort.
const pending = new Set([run1.taskRunId, run2.taskRunId]);
for await (const event of render.workflows.taskRunEvents([...pending])) {
console.log('Event:', event.status, event.id, event.results);
pending.delete(event.id);
if (pending.size === 0) break;
}
render.workflows.getTaskRun(taskRunId)Gets task run details by ID.
Parameters:
taskRunId: string - Task run IDReturns: Promise<TaskRunDetails>
Example:
const render = new Render();
const details = await render.workflows.getTaskRun('task-run-id');
render.workflows.cancelTaskRun(taskRunId)Cancels a running task.
Parameters:
taskRunId: string - Task run ID to cancelReturns: Promise<void>
Example:
const render = new Render();
const run = await render.workflows.startTask('my-workflow/square', [5]);
await render.workflows.cancelTaskRun(run.taskRunId);
render.workflows.listTaskRuns(params)Lists task runs with optional filters.
Parameters:
params.limit?: number - Maximum number of resultsparams.cursor?: string - Pagination cursorparams.ownerId?: string[] - Filter by owner IDsReturns: Promise<TaskRun[]>
Example:
const render = new Render();
const taskRuns = await render.workflows.listTaskRuns({ limit: 10 });
task(options, func)Registers a function as a task.
Parameters:
options: RegisterTaskOptions - Task configuration
name: string - Task name (required)retry?: RetryOptions - Optional retry configuration
maxRetries: number - Maximum number of retrieswaitDurationMs: number - Wait duration between retries in millisecondsbackoffScaling?: number - Backoff multiplier (default: 1.5)timeoutSeconds?: number - Maximum execution time in secondsplan?: string - Resource plan for task execution (e.g., "starter", "standard", "pro")func: TaskFunction - The task function to registerReturns: The registered function with the same signature
Usage:
// Basic usage
const myTask = task(
{ name: 'myTask' },
function myTask(arg: string): string {
return arg.toUpperCase();
}
);
// With retry, timeout, and plan options
task(
{
name: 'retryableTask',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
backoffScaling: 1.5,
},
timeoutSeconds: 300,
plan: 'starter',
},
function retryableTask(arg: string): string {
return arg.toUpperCase();
}
);
// Async task with subtasks
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
task(
{ name: 'addSquares' },
async function addSquares(a: number, b: number): Promise<number> {
const result1 = await square(a);
const result2 = await square(b);
return result1 + result2;
}
);
startTaskServer()Starts the task server and listens for task execution requests.
Returns: Promise<void>
Example:
await startTaskServer();
TaskRunStatusenum TaskRunStatus {
PENDING = 'pending',
RUNNING = 'running',
COMPLETED = 'completed',
FAILED = 'failed',
CANCELED = 'canceled',
}
TaskRuninterface TaskRun {
id: string;
taskId: string;
status: TaskRunStatus;
startedAt?: string;
completedAt?: string;
parentTaskRunId: string;
rootTaskRunId: string;
retries: number;
}
TaskRunDetailsinterface TaskRunDetails {
id: string;
taskId: string;
status: TaskRunStatus;
results?: any;
error?: string;
startedAt?: string;
completedAt?: string;
}
TaskRunResultclass TaskRunResult {
readonly taskRunId: string;
get(): Promise<TaskRunDetails>;
}
RegisterTaskOptionsinterface RegisterTaskOptions {
name: string;
retry?: {
maxRetries: number;
waitDurationMs: number;
backoffScaling?: number; // default 1.5
};
timeoutSeconds?: number;
plan?: string; // e.g., "starter", "standard", "pro"
}
The SDK provides several error classes:
import { Render } from '@renderinc/sdk';
import {
RenderError,
TaskRunError,
ClientError,
ServerError,
AbortError,
} from '@renderinc/sdk';
const render = new Render();
try {
const result = await render.workflows.runTask('my-workflow/task', [42]);
} catch (error) {
if (error instanceof TaskRunError) {
console.error('Task failed:', error.taskRunId, error.message);
} else if (error instanceof ClientError) {
console.error('Client error:', error.statusCode, error.cause);
} else if (error instanceof ServerError) {
console.error('Server error:', error.statusCode, error.cause);
} else if (error instanceof AbortError) {
console.error('Request was aborted');
} else if (error instanceof RenderError) {
console.error('General SDK error:', error.message);
}
}
RENDER_API_KEY - Your Render API key (required)RENDER_WORKSPACE_ID - Default owner ID for object storage (workspace team ID, e.g. tea-xxxxx)RENDER_REGION - Default region for object storage (e.g. oregon, frankfurt)RENDER_USE_LOCAL_DEV - Enable local development mode (true/false)RENDER_LOCAL_DEV_URL - Local development URL (default: http://localhost:8120)RENDER_SDK_MODE - Task execution mode (run or register)RENDER_SDK_SOCKET_PATH - Unix socket path for task communicationWhen running on Render, RENDER_WORKSPACE_ID and RENDER_REGION are set automatically. You can also pass them as constructor options:
import { Render } from '@renderinc/sdk';
const render = new Render(); // Uses env vars for auth + object storage defaults
// Upload (no need to pass ownerId/region when env vars are set)
await render.experimental.storage.objects.put({
key: 'path/to/file.png',
data: Buffer.from('binary content'),
contentType: 'image/png',
});
// Download
const obj = await render.experimental.storage.objects.get({ key: 'path/to/file.png' });
// List
const response = await render.experimental.storage.objects.list();
import { Render } from '@renderinc/sdk';
const render = new Render();
const result = await render.workflows.runTask('my-workflow/square', [5]);
console.log('Square of 5 is:', result.results[0]); // 25
import { task } from '@renderinc/sdk/workflows';
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
task(
{ name: 'pythagorean' },
async function pythagorean(a: number, b: number): Promise<number> {
const aSquared = await square(a);
const bSquared = await square(b);
return Math.sqrt(aSquared + bSquared);
}
);
import { task } from '@renderinc/sdk/workflows';
const divide = task(
{ name: 'divide' },
async function divide(a: number, b: number): Promise<number> {
if (b === 0) {
throw new Error('Cannot divide by zero');
}
return a / b;
}
);
task(
{
name: 'safeDivide',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
},
},
async function safeDivide(a: number, b: number): Promise<number> {
try {
return await divide(a, b);
} catch (error) {
console.error('Division failed:', error);
return 0; // Return default value
}
}
);
import { Render, AbortError } from '@renderinc/sdk';
const render = new Render();
async function runTaskWithCancellation() {
const abortController = new AbortController();
// Cancel the task after 5 seconds
setTimeout(() => abortController.abort(), 5000);
try {
const result = await render.workflows.runTask(
'my-workflow/long-running-task',
[42],
abortController.signal
);
console.log('Task completed:', result.results);
} catch (error) {
if (error instanceof AbortError) {
console.log('Task was cancelled');
} else {
console.error('Task failed:', error);
}
}
}
runTaskWithCancellation();
import { Render } from '@renderinc/sdk';
// Single entry point for all Render products
const render = new Render({
token: process.env.RENDER_API_KEY,
});
async function workflowExample() {
try {
// Run a workflow task
const result = await render.workflows.runTask('my-workflow/process-data', [
{ userId: 123, data: 'example' },
]);
console.log('Workflow completed:', result.status);
console.log('Results:', result.results);
// List and monitor recent task runs
const recentRuns = await render.workflows.listTaskRuns({ limit: 5 });
console.log(`\nRecent task runs: ${recentRuns.length}`);
for (const run of recentRuns) {
console.log(`- ${run.id}: ${run.status} (${run.taskId})`);
}
} catch (error) {
console.error('Error:', error);
}
}
workflowExample();
npm run build
npm test
npm run lint
npm run format
typescript/
├── src/
│ ├── render.ts # Main Render SDK class
│ ├── errors.ts # Error classes
│ ├── index.ts # Main exports
│ ├── version.ts # SDK version and user-agent
│ ├── workflows/ # Workflows functionality
│ │ ├── task.ts # task() function
│ │ ├── runner.ts # startTaskServer() and run()
│ │ ├── executor.ts # TaskExecutor
│ │ ├── registry.ts # TaskRegistry
│ │ ├── uds.ts # Unix socket client
│ │ ├── types.ts # Type definitions
│ │ ├── client/ # REST API client
│ │ │ ├── client.ts # WorkflowsClient class
│ │ │ ├── create-client.ts # createWorkflowsClient() factory
│ │ │ ├── task-run-result.ts # TaskRunResult class
│ │ │ ├── sse.ts # SSE event types
│ │ │ ├── types.ts # Client type definitions
│ │ │ └── index.ts # Exports
│ │ └── index.ts # Workflows exports
│ ├── experimental/ # Experimental features
│ │ └── object/ # Object storage API
│ └── utils/ # Shared utilities
├── examples/
│ ├── client/ # Client example
│ │ ├── main.ts
│ │ └── package.json
│ └── task/ # Task example
│ ├── main.ts
│ └── package.json
├── package.json
├── tsconfig.json
└── README.md
MIT
For issues and questions, please visit:
Contributions are welcome! Please read our contributing guidelines before submitting pull requests.
FAQs
Render SDK for TypeScript
We found that @renderinc/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.