@blitzreels/sdk
Typed TypeScript client for the BlitzReels public API.
Use client.clipBatches.getForAsset({ assetId }) to recover the latest persisted
batch for a source video, including batches that have not created clips yet.
The response is { batch: null } when the workspace has no batch for that asset.
Official website: https://blitzreels.com/
The SDK is the shared API layer used by the BlitzReels CLI and external TypeScript integrations. It is intentionally free of Next.js/server-only imports.
Install
npm install @blitzreels/sdk
Usage
import { BlitzReelsClient } from "@blitzreels/sdk";
const client = new BlitzReelsClient({
apiKey: process.env.BLITZREELS_API_KEY ?? "",
baseUrl: "https://blitzreels.com/api/v1",
});
const auth = await client.auth.validate();
const projects = await client.projects.list({
limit: 20,
cursor: undefined,
offset: undefined,
search: undefined,
status: "active",
});
The API key authorizes one workspace. Use installed TypeScript declarations for exact method inputs. Discover available operations through capabilities, then read the generated API contract. The SDK owns transport; consumers add application consent/authentication and UI mapping.
Uploaded-video publishing accepts workspace media assets without an existing
BlitzReels project. MP4, MOV, and WebM inputs are checked against every selected
provider before any target is scheduled.
Duration and dimensions must already be available on the media asset.
Pending metadata returns a retryable conflict with error_details.reason: media_asset_processing
and error_details.media_asset_id, before copying media or creating a publishing source/post.
Poll client.media.get({ assetId }), then retry scheduling with that same ID.
Failed processing or completed assets without metadata return a non-retryable validation_error.
TikTok direct posts require an explicit privacyLevel; TikTok drafts do not.
Use containsSyntheticMedia once per request so BlitzReels maps the declaration
to each provider's native field.
API requests fail with a retryable timeout error after 30 seconds by default.
Set requestTimeoutMs in the client config when an integration needs a different deadline.
Scheduled network posts
This source adds X text posts and LinkedIn/Threads text or exported-media posts. Availability depends on the deployed server configuration and the connected account's permissions. X remains disabled until free API access has been verified; these methods do not enable paid API calls. LinkedIn targets personal profiles, not organization Pages.
const receipt = await client.publishing.scheduleNetworkPost({
platform: "linkedin",
connectionId,
projectId: null,
exportId: null,
caption: "Testing scheduled publishing from BlitzReels.",
scheduledFor,
timezone: "Europe/Paris",
idempotencyKey,
});
const status = await client.publishing.getPost({ postId: receipt.post_id });
Pass both projectId and exportId for a completed media export, or both null for text.
Use listConnections() to resolve the intended destination before scheduling.
Reuse the same idempotency key and request body after a timeout to recover the original receipt.
A scheduled receipt is queue acceptance; inspect each target's status and provider ID for publication.
An uncertain publication requires checking the provider before submitting a new post.
Local API
const client = new BlitzReelsClient({
apiKey: process.env.BLITZREELS_API_KEY ?? "",
baseUrl: "http://localhost:3100/api/v1",
});
Local/development API keys use br_test_...; production keys use br_live_....
Source, releases, and license
The npm package is publicly installable, but its canonical source is private and proprietary.
Published behavior depends on the installed package version.
Large uploads use multipart transfer; BLITZREELS_REQUEST_TIMEOUT_MS controls SDK API requests.
Admin recovery and other internal operator resources are not exported or included in the public artifact.
See LICENSE for the package terms.
Generation resolution
generation.images and generation.videos accept resolution and forward it to REST.
Omit it or pass null to use the model default.
generation.options({ kind: "image" }) and generation.options({ kind: "video" })
return per-model parameters.resolution (supported, values, default, reason).
Unsupported explicit settings fail validation; they are never silently discarded.
Image options include credit_cost_by_resolution. A separate quality tier is unavailable,
as reported by parameters.quality. Image job results include the requested resolution,
measured width/height when available, and credits used.
Generation inputs share model-aware validation with REST and MCP.
generation.videos() accepts endFrameAssetId, referenceVideoAssetIds, and referenceAudioAssetIds.
Reference-only Seedance models do not require sourceAssetId; a supplied source becomes the first reference.
endFrameAssetId requires a source first frame and cannot be mixed with reference arrays.
Discover per-model counts, duration limits, audio behavior, seed/negative-prompt support, and providers
with generation.options({ kind: "video" }). Unsupported explicit settings are rejected.
generateAudio: null (or omission) uses model behavior. enhancePrompt: true uses the shared BlitzReels brain
with model grammar, bounded reference previews, frame roles, and audio intent.
catalog.voices() reads the built-in /voices catalog and returns { voices: [...] }.
voices.list/get/clone/archive manage cloned voices under /workspace/voices; list returns { items: [...] }.
Voice IDs are validated against generation.options({ kind: "voiceover" }).voices, including provider and preview URLs.
For source-video editing, generation.planBrief({ prompt, model, durationSeconds, aspectRatio })
returns an execution contract. Pass model: null for intent-based selection.
generation.videos accepts transformation with character-to-source role bindings and keepOriginalAudio.
The original soundtrack switch is separate from generateAudio; the source determines editing duration.
See source video editing for the workflow and current verification boundary.
Faceless input and prompt improvement
generation.faceless accepts inputMode: "topic" | "script" and improvePrompt: boolean.
Topics are drafted into narration before the reviewable production plan is created.
For authored scripts, improvePrompt: false preserves the narration exactly.
Omitted values retain script input with improvement disabled for existing clients.
Mutation recovery
client.contentReview.submit({ projectId, expectedProjectRevision, caption, reason, language, idempotencyKey })
adds a nonempty saved video or carousel to the workspace review queue. It returns draftId, the submitted
Project revision, the initial review version and mutationReceipt. No rendering, charges or publication occurs.
Repeat the same inputs and key to recover the receipt across web, MCP and SDK clients for the same workspace user.
Changed inputs, stale revisions and duplicate Project submissions conflict; existing review decisions stay saved.
client.mutations.lookup({ operation, idempotencyKey }) reads a receipt for the current API key and workspace.
Use project.create or generation.image.create with the key saved before submission.
The result is { receipt: null } when no record is found at read time; an outstanding request can still be accepted.
Completed receipts expose resource IDs, not prompts, lease tokens or internal errors.
Their status describes submission rather than background job completion.
media.finalizeUpload accepts an optional idempotencyKey.
Reuse it with identical finalization inputs to recover a lost response without reading a removed duplicate object.
A failed attempt can retry the same key; an in-progress attempt can be reclaimed only after five stale minutes.
Unified publishing
client.publishing.createPost({ post, idempotencyKey }) uses the shared PublishingPostInput contract.
Call validatePost(post) for live preflight and capabilities() for supported formats and platform limits.
The CLI lifecycle guide contains the same JSON input and defaults.
const post = {
source: { type: "media_asset" as const, media_asset_id: assetId },
caption: "My caption",
mode: "now" as const,
targets: [
{ platform: "instagram" as const, connection_id: instagramId, share_to_story: true },
{ platform: "facebook" as const, connection_id: facebookId, video_format: "reel" as const },
],
};
const validation = await client.publishing.validatePost(post);
if (!validation.valid) throw new Error(JSON.stringify(validation.issues));
const receipt = await client.publishing.createPost({ post, idempotencyKey: "launch-post-1" });
const current = await client.publishing.getPost({ postId: receipt.post_id });
A successful create confirms acceptance; read target receipts to confirm publication.
getPublishingPostSchema() and publishingPostInputSchema expose the contract without authentication.
listPosts({ status, limit, offset }) is bounded; defaults are 20 and 0, with a maximum page size of 100.
cancelTarget, retryTarget and rescheduleTarget require targetId, expectedRevision and idempotencyKey.
Rescheduling additionally takes scheduledFor. Reuse a key with identical inputs after a lost response.
Create a draft with post.mode: draft and no schedule.
updateDraft({ postId, expectedRevision, post, idempotencyKey }) replaces an unscheduled draft.
scheduleDraft({ postId, expectedRevision, mode: "now", idempotencyKey }) validates and promotes that same ID.
For later publication, use mode: "schedule" with scheduledFor.
deleteDraft({ postId, expectedRevision, idempotencyKey }) soft-deletes only unscheduled drafts.
REST uses POST /publishing/posts, POST /publishing/posts/validate, GET /publishing/posts,
GET /publishing/posts/{postId}, and GET /publishing/capabilities.
Draft edits use PATCH /publishing/posts/{postId}/draft; promotion uses POST /publishing/posts/{postId}/schedule.
Draft deletion uses DELETE /publishing/posts/{postId}/draft?expected_revision=....
Target actions use POST /publishing/targets/{targetId}/{cancel|retry|reschedule}.
All new publishing writes require Idempotency-Key. Revision fields in REST use expected_revision.
Meta native Reel-to-Story sharing remains an explicit manual follow-up in receipts.
share_to_story never silently uploads a separate Story. Standalone Stories, recurring queues, first comments,
provider audio/collaborators and publishing webhooks are not part of this release.
Deploy the matching API and 0194_publishing_drafts migration before using these new package methods.
Web research (local source)
client.knowledge.research exposes list, quote, start, get, cancel and resume.
Use list({ status: "all", limit: 10, offset: 0 }) to find saved workspace jobs, including work started by another agent.
Pages cap at 20 summaries; status: "active" selects queued/running jobs.
Server rollout requires configured research pricing and a validated runtime.
Pass explicit prompt, productUrl (or null), seriesId (or null), language, maxSources and maxCredits to quote.
Start with the unchanged request plus the returned quoteId and a caller-generated idempotencyKey.
Repeat that start input/key after a disconnect to recover the accepted job.
Read { jobId } to inspect credits, diagnostics, captures and the saved brief reference.
delivery.dispatched reports queue acknowledgment, not completion.
Cancel stops future work; resume can spend the accepted remaining budget at the original rates.
Creative spending
client.creativeSource.usage({ before: null, limit: 25 }) reads workspace spending caps and job receipts.
Use nextCursor as before for the next page. coveredOperations lists protected job families; currently recipes, research, screenshots and isolated source builds.
Unknown provider costs retain their reservation. costBasis distinguishes reported costs from allocated upper bounds.
Recipe quotes retain their existing credit estimate; workspace/global monetary admission is checked atomically on start.
Saved recipe versions
client.recipes.listVersions({ projectId, offset: 0, limit: 20 }) lists immutable template versions,
including the current Project revision and latest saved version. client.recipes.inspectVersion accepts
projectId, version, section, sourceRevisionId, path, offset and limit.
Sections are overview, variables, artifacts, dependencies, assets and source.
Use null for source selection outside the source section. Source inspection requires the saved source revision ID;
a null path lists files, and a path reads one exact saved file, including package manifests and lockfiles.
Each collection defaults to 20 rows and permits at most 100. Text previews report truncation after 4,096 characters.
These reads use retained snapshots and current template permissions. Public template visibility does not grant
cross-workspace version access. Saving/copying through public job endpoints is separate unfinished work.
Recipe writes use client.recipes.quote({ request, limits }), followed by
client.recipes.start({ request, limits, quoteId, maxCredits, idempotencyKey }).
The request is { kind: "capture", value: { projectId, expectedProjectRevision, expectedVersion } } or
{ kind: "copy", value: { templateProjectId, version, projectId, expectedProjectRevision } }.
Copy targets an existing empty Project; optional source/nested mappings select additional destination Projects.
Limits bound transfer bytes, stored bytes, operations and storage requests; their maxima are in the shared schema.
Poll client.recipes.get({ jobId }); cancel({ jobId }) stops new work without erasing completed outputs.
Retry identical start inputs/key to recover admission and queue delivery. The SDK sends Idempotency-Key as a header.
Start returns an admission receipt and current job, not a completed render. Pricing configuration is required.
Source execution quotes are available through source quote --spec-file FILE --json and
client.creativeSource.quote({ projectId, revision, compositionId, frame, output }).
Pass the returned id as build quoteId to reject changed prices or settings.
A null quote accepts current configured bounds; all builds reserve against the same workspace/global USD caps.
Export estimates
const quote = await client.exports.quote({
projectId,
expectedRevision: null,
resolution: "1080p",
renderMode: "auto",
frameRate: null,
});
This read returns eligibility, estimated credits and the maximum USD workspace reservation without starting work. Unavailable rates have a null amount and a reason. Admission rechecks current limits; the quote reserves nothing.
Audio quotes are read-only and share the same budget guard as generation and saved-audio recovery:
const audioQuote = await client.generation.quoteAudio({
kind: "music", characters: null, seconds: 30, preview: true, recovery: false, narrationTake: false,
});
maximumUsd includes the bounded worker retries, provider request, transfer and initial retention.
Unknown rates return a null maximum and a denial reason. Recovery quotes use recovery: true and exclude a new provider purchase.
Admission checks current limits again. Existing unknown dispatches retain their reservation and never auto-dispatch another job.
Image, video and standalone prompt quotes use the same read-only budget interface:
const visualQuote = await client.generation.quote({
kind: "video", model: "kling-2.1", seconds: 5, resolution: null,
sourceImageModel: "fal-ai/nano-banana-2", enhancePrompt: true,
});
sourceImageModel includes one generated starting image for image-to-video; use null for an existing source.
enhancePrompt includes one enhancement. The combined maximum uses the earliest policy expiry and current credit/budget limits.
For a standalone enhancement use kind: "prompt" with null model, seconds, resolution and sourceImageModel.
The returned limits describe the configured envelope; actual generation still validates its full inputs and rechecks admission.
No quote reserves funds, buys provider work or locks a price. Unavailable combined prices return a null maximum.
Set narrationTake: true on a voiceover quote for direct narration and voice previews.
The character envelope applies to prepared speech, including directions; final generation checks the actual prepared text.
Recovery quotes reserve processing/IO without buying replacement speech. Existing audio-job narration uses its parent allowance.
Read frame costs with projects.quotePreview({ projectId, expectedRevision: null, frameCount: 3, targetWidth: 768, mode: "analyze" }).
Snapshot and carousel preview options accept idempotencyKey; a successful retry reuses retained output and refreshes URLs.
Changed retry inputs conflict, and uncertain jobs require reconciliation before replacement.