npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@apicity/fal

v0.7.3

Published

Fal Platform API provider for model management, pricing, usage, and analytics.

Readme

@apicity/fal

npm dependencies TypeScript

Fal Platform API provider for model management, pricing, usage, and analytics.

Runtime dependencies:

  • zod@^4.4.3 — request schemas attached to every POST endpoint as .schema

Installation

npm install @apicity/fal
# or
pnpm add @apicity/fal

Quick Start

import { createFal } from "@apicity/fal";

const fal = createFal({ apiKey: process.env.FAL_API_KEY! });

Real-world example: upload a portrait, render a Sora 2 video

fal's signature flow is upload-once, reuse-everywhere — drop bytes onto fal's CDN via a presigned PUT, then thread the resulting https://*.fal.media/ URL through any model endpoint. The two-step snippet below combines tests/integration/fal-storage-upload-initiate.test.ts (POST initiate → PUT bytes) with tests/integration/fal-sora-2-image-to-video.test.ts (image-to-video generation), so every URL, byte count, and asset id below comes from real recorded HARs.

import { readFile } from "node:fs/promises";
import { createFal } from "@apicity/fal";

const fal = createFal({ apiKey: process.env.FAL_API_KEY! });

// 1. Reserve a signed upload slot. `initiate` returns two URLs: a
//    permanent `file_url` you'll feed to downstream models, and a
//    presigned `upload_url` you PUT the bytes to. Both point at the
//    same fal CDN — no third-party hosting needed.
const slot = await fal.storage.upload.initiate({
  file_name: "man.jpg",
  content_type: "image/jpeg",
});
console.log(slot.file_url);
// → "https://v3b.fal.media/files/b/0a96d564/QR9a1l-E0UuoR6zOHUMlX_man.jpg"
//   (the `cat1.jpg` recording shows the same URL shape with a
//    cat1 suffix; the suffix tracks `file_name` you passed in.)

// 2. PUT the bytes to the presigned URL. fal storage is plain HTTP —
//    no SDK call needed, just `fetch` with a matching Content-Type.
//    The signature on `upload_url` expires after a short window;
//    upload promptly. The resulting `file_url` is durable and
//    fetchable by every fal model endpoint.
const bytes = await readFile("./man.jpg");
const put = await fetch(slot.upload_url, {
  method: "PUT",
  headers: { "Content-Type": "image/jpeg" },
  body: bytes,
});
if (!put.ok) throw new Error(`upload failed: ${put.status}`);

// 3. Hand the now-permanent `file_url` to OpenAI's Sora 2 image-to-
//    video model. fal returns a typed bundle: the MP4, a webp
//    thumbnail, and a horizontal spritesheet — all hosted on the
//    same fal CDN. `duration` accepts 4 | 8 | 12 | 16 | 20 (seconds);
//    `aspect_ratio` is "auto" | "9:16" | "16:9".
const result = await fal.sora2.imageToVideo({
  prompt: "the man waves at the camera as the wind blows his hair",
  image_url: slot.file_url,
  aspect_ratio: "16:9",
  duration: 4,
});

console.log(result.video.url);
// → "https://v3b.fal.media/files/b/0a96bf3c/8U5wwkg9EC_eK0Jr3XyiR_Vgq1ZZPm.mp4"
console.log(result.video.file_size);
// → 2009236   // ~2 MB MP4 for a 4-second 720p clip
console.log(result.video_id);
// → "video_69e37804033c8191959194ea8aa8fc6e08bf9f3eb453b1b1"
console.log(result.thumbnail?.url);
// → "https://v3b.fal.media/files/b/0a96bf3c/bsgsaBd5IqdwOuufu_qSx_2yOP4u34.webp"
console.log(result.spritesheet?.url);
// → "https://v3b.fal.media/files/b/0a96bf3c/_9tqG1dEuRCEeegOulGrk_pWsHbiNB.bin"

Notes

  • The recorded sora-2 HAR inlines the image as a data:image/jpeg;base64,… URL — fal accepts both inline data URLs and any https:// URL it can reach. Uploading via fal storage first keeps request bodies tiny (350 KB → <1 KB) and lets you reuse the asset across multiple model calls without re-encoding.
  • The package re-exports a one-call uploadFile(provider, { data, filename, contentType }) helper that wraps the initiate-then-PUT dance and returns the file_url directly — use it when you don't need granular control over the lifecycle or signed URL.
  • Every POST endpoint exposes a Zod schema: call fal.sora2.imageToVideo.schema.safeParse(input) to validate a payload before paying for inference.
  • WAN 2.7 reference-to-video validates generated duration as 2–10 seconds. duration: 0 remains limited to source-clip edit-video flows where it means keeping the original clip length.
  • Long-running calls accept an AbortSignal second argument and compose with the package's middleware, e.g. withRetry(fal.sora2.imageToVideo, { retries: 3 }) from @apicity/fal to ride out transient queue / 429s.
  • Errors throw FalError with status, type, request_id, and the parsed body attached: try { ... } catch (e) { if (e instanceof FalError) console.error(e.status, e.body); }.

API Reference

72 endpoints across 19 groups. Each method mirrors an upstream URL path.

bytedance

POST https://api.fal.ai/v1/fal-ai/bytedance/seed-speech/tts/v2

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedSpeech.tts.v2({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedance2p0.fast.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/reference-to-video

Cost tier: prohibitive

const res = await fal.bytedance.seedance2p0.fast.referenceToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/fast/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedance2p0.fast.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedance2p0.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/reference-to-video

Cost tier: prohibitive

const res = await fal.bytedance.seedance2p0.referenceToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/bytedance/seedance-2.0/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedance2p0.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/bytedance/seedream/v5/lite/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedream.v5.lite.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/bytedance/seedream/v5/lite/text-to-image

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.bytedance.seedream.v5.lite.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

falAi

POST https://api.fal.ai/v1/fal-ai/elevenlabs/speech-to-text/scribe-v2

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.falAi.elevenlabs.speechToText.scribeV2({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

gptImage1p5

POST https://api.fal.ai/v1/fal-ai/gpt-image-1.5

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.gptImage1p5({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/gpt-image-1.5/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.gptImage1p5.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

hunyuan

POST https://api.fal.ai/v1/fal-ai/hunyuan-image/v3/instruct/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.hunyuan.v3.instructEdit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

klingVideo

POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.o3p4k.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/reference-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.o3p4k.referenceToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/o3/4k/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.o3p4k.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/v3/pro/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.v3.pro.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/v3/pro/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.v3.pro.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/v3/standard/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.v3.standard.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/kling-video/v3/standard/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.klingVideo.v3.standard.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

models

DELETE https://api.fal.ai/v1/models/requests/{param}/payloads

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.requests.payloads({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models/pricing

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.pricing({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models/requests/by-endpoint

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.requests.byEndpoint({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models/requests/{param}/payloads

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.requests.payloads({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/models/pricing/estimate

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.pricing.estimate({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models/pricing

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.pricing({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/models/pricing/estimate

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.pricing.estimate({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/models/requests/by-endpoint

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.requests.byEndpoint({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

DELETE https://api.fal.ai/v1/models/requests/{param}/payloads

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.models.requests.payloads({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

nanoBanana

POST https://api.fal.ai/v1/fal-ai/nano-banana/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/nano-banana

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

nanoBanana2

POST https://api.fal.ai/v1/fal-ai/nano-banana-2/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana2.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/nano-banana-2

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana2.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

nanoBanana2Lite

POST https://api.fal.ai/v1/google/nano-banana-lite/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana2Lite.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/google/nano-banana-2-lite

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBanana2Lite.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

nanoBananaPro

POST https://api.fal.ai/v1/fal-ai/nano-banana-pro/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBananaPro.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/nano-banana-pro

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.nanoBananaPro.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

queue

POST https://api.fal.ai/v1/POST

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.queue.submit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/POST

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.queue.submit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

qwenImage

POST https://api.fal.ai/v1/fal-ai/qwen-image

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.qwenImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/qwen-image-edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.qwenImage.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

serverless

POST https://api.fal.ai/v1/serverless/logs/stream

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.logs({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/serverless/files/file/local/{param}

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.files.uploadLocal({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/serverless/files/file/url/{param}

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.files.uploadUrl({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/serverless/files/file/local/{param}

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.files.uploadLocal({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/serverless/files/file/url/{param}

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.files.uploadUrl({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/serverless/logs/stream

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.serverless.logs({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

sora2

POST https://api.fal.ai/v1/fal-ai/sora-2/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.sora2.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/sora-2/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.sora2.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

storage

POST https://rest.fal.ai/storage/upload/complete-multipart

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.storage.upload.completeMultipart({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://rest.fal.ai/storage/upload/initiate

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.storage.upload.initiate({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://rest.fal.ai/storage/upload/initiate-multipart

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.storage.upload.initiateMultipart({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

veo3p1

POST https://api.fal.ai/v1/fal-ai/veo3.1/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.veo3p1.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/veo3.1

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.veo3p1.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

wan

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/edit-video

Cost tier: prohibitive

const res = await fal.wan.v2p7.editVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/pro/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.pro.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/pro/text-to-image

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.pro.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/reference-to-video

Cost tier: prohibitive

const res = await fal.wan.v2p7.referenceToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/text-to-image

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.textToImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/fal-ai/wan/v2.7/text-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.wan.v2p7.textToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

workflows

GET https://api.fal.ai/v1/workflows

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.workflows({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

GET https://api.fal.ai/v1/workflows

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.v1.workflows({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

xai

POST https://api.fal.ai/v1/xai/grok-imagine-image

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineImage({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/xai/grok-imagine-image/edit

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineImage.edit({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/xai/grok-imagine-video/edit-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineVideo.editVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/xai/grok-imagine-video/extend-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineVideo.extendVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/xai/grok-imagine-video/image-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineVideo.imageToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

POST https://api.fal.ai/v1/xai/grok-imagine-video/reference-to-video

Cost tier: prohibitive

Upstream docs ↗

const res = await fal.xai.grokImagineVideo.referenceToVideo({ /* ... */ });

Source: packages/provider/fal/src/fal.ts

Middleware

import { createFal, withRetry } from "@apicity/fal";

const fal = createFal({ apiKey: process.env.FAL_API_KEY! });
const models = withRetry(fal.get.v1.models, { retries: 3 });

Part of the apicity monorepo.

License

MIT — see LICENSE.