@visgate_ai/client
v0.3.5
Published
JavaScript/TypeScript client for Visgate API — unified vision AI gateway (Fal, Replicate, Runway, RunPod).
Maintainers
Readme
@visgate_ai/client
JavaScript/TypeScript SDK for the Visgate API — one client for image and video generation across Fal, Replicate, Runway, and RunPod deployments.
Works in Node.js (18+), browsers, and with React, Vite, Next.js, and vanilla JS.
Install
npm install @visgate_ai/clientQuick Start
import { Client } from "@visgate_ai/client";
const client = new Client(); // reads VISGATE_API_KEY from env (Node)
const result = await client.generate("a sunset over Istanbul");
console.log(result.imageUrl, result.cost, result.provider);
client.close();With explicit API key:
const client = new Client({ apiKey: "vg-..." });
const result = await client.generate("a sunset", { model: "fal-ai/flux/schnell" });
console.log(result.imageUrl);Features
- One client, multi-provider. Fal, Replicate, Runway, and RunPod deployments behind a single API.
- Managed and BYOK modes. Use Visgate-managed keys or bring your own.
- Promise-based API. All methods return Promises; use
async/awaitor.then(). - Automatic retries. Transient errors (429, 5xx) are retried with exponential backoff.
- Typed exceptions. Catch
AuthenticationError,RateLimitError,ProviderError, etc. - TypeScript. Full type definitions included.
- Framework-agnostic. Use in vanilla JS, React, Vite, Next.js.
- Async generation. Video/image async mode with
client.requests.get()for status polling; usage and billing resources.
Authentication
Node.js: Set VISGATE_API_KEY in the environment or pass apiKey in options.
export VISGATE_API_KEY="vg-..."Browser / Vite: Pass apiKey in options (or use import.meta.env.VITE_VISGATE_API_KEY in Vite and pass it to the client).
const client = new Client({ apiKey: "vg-..." });Production / proxy (recommended for browser apps)
Do not put your Visgate API key in the client. Use a server-side proxy that adds the key:
const client = new Client({ proxyUrl: "/api/visgate" });
// No apiKey needed — the proxy adds Authorization on the serverSet VISGATE_API_KEY on the server. This repo includes a ready-made proxy package: server-proxy/ (published as @visgate_ai/server-proxy on npm). See server-proxy/README.md for setup; or implement your own forward that injects the key.
Session-based auth (getToken): When your app has a session token (e.g. Firebase ID token), pass a getToken function so the client sends a fresh Bearer token on each request; the proxy forwards it to the API:
const client = new Client({
proxyUrl: "/api/visgate",
getToken: async () => (await auth.currentUser?.getIdToken()) ?? "",
});The proxy must forward the client's Authorization: Bearer header (e.g. @visgate_ai/server-proxy does this via keyFromRequest). If you use httpOnly cookies, the token is never in the client; your proxy reads the cookie and adds Bearer on the server — in that case do not use getToken; use Client({ proxyUrl: "/api/visgate" }) and ensure requests send credentials so the cookie is sent.
BYOK (Bring Your Own Key)
const client = new Client({
apiKey: "vg-...",
falKey: "fal_...",
replicateKey: "r8_...",
runwayKey: "rw_...",
runpodKey: "rpa_...",
});API Reference
Image Generation
// Quick generation (unified POST /generate)
const result = await client.generate("a cat in space", { model: "fal-ai/flux/schnell" });
console.log(result.status, result.imageUrl, result.cost);
// Full control (POST /images/generate) — matches API ImageGenerateRequest
const result = await client.images.generate("fal-ai/flux/schnell", "a cat in space", {
width: 1024,
height: 1024,
numImages: 1,
negativePrompt: null,
seed: null,
imageUrl: null, // optional: input image for img2img
preferCache: true, // use cache (exact or semantic match)
maxLatencyMs: null, // optional: max acceptable latency (ms)
webhookUrl: null, // optional: callback URL when done
callbackId: null, // optional: id in callback payload
});
// result: id, status, images, model, provider, cost, cacheHit, cacheSource?, latencyMs, savedAmount?, marginPercent?, createdAtVideo Generation
Video generation can take several minutes. To avoid 502 when the request takes longer than proxy/Cloudflare timeout, use async mode (preferAsync: true): the API returns 202 immediately, then poll client.requests.get(requestId) until completed.
Use VIDEO_MODEL_PRESETS for provider model IDs (Fal, Replicate, Runway), or pass a model string (e.g. fal-ai/veo3, replicate/lucataco/cogvideox-5b, runway/gen4_turbo). For image-to-video, set imageUrl or imageFile in options.
import { Client, VIDEO_MODEL_PRESETS } from "@visgate_ai/client";
const client = new Client({ proxyUrl: "/api/visgate", timeout: 300_000 });
// Sync (wait for result; may hit proxy timeout on long videos)
const syncResult = await client.videos.generate(VIDEO_MODEL_PRESETS.fal, "waves on a beach", {
durationSeconds: 6,
skipGcsUpload: true,
});
console.log(syncResult.videoUrl, syncResult.cacheHit, syncResult.cost);
// Async (recommended): returns 202, poll client.requests.get(requestId)
const result = await client.videos.generate("fal-ai/veo3", "waves on a beach", {
durationSeconds: 6,
skipGcsUpload: true, // faster; return provider URL directly
preferAsync: true, // avoids 502 — returns 202, poll client.requests.get(requestId)
imageUrl: null, // optional: input image for img2vid (or use imageFile)
webhookUrl: null, // optional: callback URL when done
callbackId: null, // optional: id in callback payload
params: {}, // optional: extra provider params
});
if (result.status === "accepted") {
let status = await client.requests.get(result.requestId);
while (status.status === "pending" || status.status === "processing") {
await new Promise((r) => setTimeout(r, 3000));
status = await client.requests.get(result.requestId);
}
console.log(status.status, status.outputUrl);
} else {
console.log(result.videoUrl, result.cacheHit, result.status);
}On the server, set the proxy route’s maxDuration (e.g. 300 seconds) so the request is not cut off — see server-proxy/README.md.
Async request status (Requests)
After starting an async generation (video or image with preferAsync: true), poll the request status until completion:
const status = await client.requests.get(result.requestId);
// status: requestId, status ("pending" | "processing" | "completed" | "failed"),
// mediaType, provider, model, outputUrl, errorMessage, createdAt, completedAtModel Discovery
const resp = await client.models.list({ provider: "fal", mediaType: "image", limit: 20 });
for (const m of resp.models) console.log(m.id, m.name);
const model = await client.models.get("fal-ai/flux/schnell");Usage and Billing
const usage = await client.usage.get("month");
console.log(usage.totalRequests, usage.totalBilledCost, usage.cacheHitRate, usage.avgLatency, usage.history);
const logs = await client.usage.logs({ limit: 50 });
const dashboard = await client.usage.dashboard("week");
// Track download event (POST /usage/downloads)
await client.usage.trackDownload("request-id", "https://...", { mediaType: "image" });Billing
const stats = await client.billing.getStats(); // public stats
const info = await client.billing.getInfo(); // org billing info (tier, balance, etc.)
const pricing = await client.billing.getPricing(); // model pricing list
await client.billing.checkout(10, "https://...", { customerEmail: "..." });
await client.billing.updateSubscription("starter");Provider Management
const keys = await client.providers.listKeys();
const balances = await client.providers.balances();Deployments (RunPod BYOK)
// Create deployment from HuggingFace model
const created = await client.deployments.create({
hfModelId: "stabilityai/stable-diffusion-xl-base-1.0",
gpuTier: "medium",
task: "text2img",
});
// List deployments and select one
const list = await client.deployments.list();
const dep = list.deployments[0];
// Get current status/details
const detail = await client.deployments.get(dep.deploymentId);
console.log(detail.status, detail.endpointUrl);
// Run inference on ready deployment
const run = await client.deployments.run(dep.deploymentId, {
prompt: "cinematic cat portrait",
});
console.log(run);
// Optional helpers
const logs = await client.deployments.getLogs(dep.deploymentId);
const cost = await client.deployments.getCost(dep.deploymentId);
const gpus = await client.deployments.listGpus();Health Check
const health = await client.health();
console.log(health.status);Error Handling
import { Client, AuthenticationError, RateLimitError, ProviderError, ValidationError, VisgateError } from "@visgate_ai/client";
const client = new Client({ apiKey: "vg-..." });
try {
const result = await client.generate("a sunset");
} catch (err) {
if (err instanceof AuthenticationError) console.error("Invalid API key");
else if (err instanceof RateLimitError) console.error("Rate limit", err.retryAfter);
else if (err instanceof ProviderError) console.error("Provider error", err.provider);
else if (err instanceof ValidationError) console.error("Validation", err.field);
else if (err instanceof VisgateError) console.error(err.message, err.errorCode);
}Configuration
| Option | Default | Description |
| ------------ | --------------------------- | ------------------------------ |
| apiKey | process.env.VISGATE_API_KEY | Visgate API key (optional when using proxyUrl) |
| proxyUrl | — | Server proxy URL; when set, no key or BYOK is sent |
| baseUrl | https://visgateai.com/api/v1 | API base URL |
| timeout | 120000 (ms) | Request timeout |
| maxRetries | 2 | Retries for 429 and 5xx |
| falKey | — | Fal BYOK key |
| replicateKey | — | Replicate BYOK key |
| runwayKey | — | Runway BYOK key |
| runpodKey | — | RunPod BYOK key (X-Runpod-Key) |
AsyncClient
For API parity with the Python SDK, AsyncClient is also exported; it has the same interface as Client (all methods return Promises).
import { AsyncClient } from "@visgate_ai/client";
const client = new AsyncClient();
const result = await client.generate("a sunset");Repository structure
src/— @visgate_ai/client (client library):generate,images,videos,models,requests(async status),usage,providers,deployments,billingserver-proxy/—@visgate_ai/server-proxy: server-side proxy for Next.js and other Node runtimes. Install withnpm install @visgate_ai/server-proxyor use locally from this repo.examples/— Next.js, vanilla, and Vite examples
License
MIT — see LICENSE.
