Node.js Client
Use @indreamai/client for typed API access in Node.js and Edge runtimes.
Install
pnpm add @indreamai/clientRuntime Support
- Node.js 18+ runtime
- Edge runtimes with standard Web APIs:
- Cloudflare Workers
- Vercel Edge Functions
- Deno Deploy
Initialize Client
import { IndreamClient } from '@indreamai/client'
const client = new IndreamClient({
apiKey: process.env.INDREAM_API_KEY!,
baseURL: 'https://api.indream.ai',
timeout: 60_000,
maxRetries: 2,
})Search Illustrations
Search by keyword when you need a supported hand-drawn illustration name.
const items = await client.illustrations.search('creative')
console.log(items)Create Export
OpenAPI enforces active export concurrency per account.
If your account already has two active export tasks, exports.create returns 422 OPEN_API_EXPORT_CONCURRENCY_LIMIT_EXCEEDED.
const created = await client.exports.create({
editorState,
ratio: '9:16',
scale: 0.6,
fps: 30,
format: 'mp4',
})created.durationSeconds is the actual export duration. created.billedStandardSeconds is the billing unit.
Project Workflow
const project = await client.projects.create({
title: 'Launch draft',
editorState,
})
const asset = await client.uploads.upload(heroFile, {
filename: 'hero.png',
contentType: 'image/png',
projectId: project.projectId,
})
await client.projects.sync(project.projectId, {
editorState: {
...editorState,
assets: {
...editorState.assets,
hero: {
type: 'image',
remoteUrl: asset.fileUrl,
remoteKey: asset.fileKey,
},
},
},
})
const createdFromProject = await client.projects.createExport(project.projectId, {
ratio: '9:16',
scale: 0.6,
fps: 30,
format: 'mp4',
})
const done = await client.exports.wait(createdFromProject.taskId)
console.log(done.projectId, done.status)Get and List
const task = await client.exports.get(created.taskId)
const page = await client.exports.list({
pageSize: 20,
pageCursor: null,
createdByApiKeyId: null,
})
console.log(page.items.length, page.nextPageCursor)
console.log(page.items[0]?.createdByApiKeyId)Wait Helper
const done = await client.exports.wait(created.taskId, {
timeoutMs: 10 * 60 * 1000,
pollIntervalMs: 2000,
})wait stops at terminal statuses. It throws APIError when the terminal status is FAILED or CANCELED.
Returned task snapshots include both durationSeconds and billedStandardSeconds.
Verify and Parse Webhook
import { parseExportWebhookEvent, verifyExportWebhookRequest } from '@indreamai/client'
const rawBody = await request.text()
const isValid = await verifyExportWebhookRequest({
webhookSecret: process.env.INDREAM_WEBHOOK_SECRET!,
rawBody,
headers: request.headers,
maxSkewSeconds: 300, // optional
})
if (!isValid) {
throw new Error('Invalid webhook signature')
}
const event = parseExportWebhookEvent(JSON.parse(rawBody))
console.log(event.eventType)
console.log(
event.task.taskId,
event.task.status,
event.task.durationSeconds,
event.task.billedStandardSeconds
)eventType values are EXPORT_STARTED, EXPORT_COMPLETED, EXPORT_FAILED.
event.task has the same shape as client.exports.get(taskId) result.
durationSeconds is the real export duration, while billedStandardSeconds is the billing unit.
verifyExportWebhookRequest validates both signature headers and timestamp skew window.
Editor Helpers
import type { TEditorStateV1 } from '@indreamai/client'
const editorState = {
// ...full editor state payload
} satisfies TEditorStateV1
const capabilities = await client.editor.capabilities()
const validation = await client.editor.validate(editorState)
console.log(capabilities.captionAnimations.in.map((preset) => preset.id))
console.log(validation.valid)Error Handling
import { AuthError, RateLimitError, ValidationError } from '@indreamai/client'
try {
await client.editor.validate(editorState)
} catch (error) {
if (error instanceof AuthError) {
// Invalid credentials or permission issue.
} else if (error instanceof ValidationError) {
// Payload is invalid and must be fixed.
} else if (error instanceof RateLimitError) {
// Retry with backoff.
}
}Resources
For source code, issues, and contributions, check out our GitHub repository. Install directly from @indreamai/client to get the latest package.
Last updated on