TypeScript and Python SDKs
Typed clients generated from the OpenAPI document: run a tool, wait for a run, fetch results.
Both SDKs are generated from our OpenAPI document, so every tool input is typed. Same calls in TypeScript and Python.
Before you start
You need an API key (it starts with af_live_). Sign up with your email and you get
2,000 free credits.
1. Install
The packages go on npm and PyPI soon. Until then you can call the HTTP API directly (last step) or use MCP.
2. Run a tool
Set PULLWIRE_API_KEY in your environment, or pass the key in code. run waits for the results and returns them with the credits used.
import { createPullwire } from '@af/sdk';
const pw = createPullwire(); // reads PULLWIRE_API_KEY
const { run, results } = await pw.run('youtube-transcripts', {"videos":["https://www.youtube.com/watch?v=jNQXAC9IVRw"],"maxResults":3});
console.log(run.creditsUsed, results[0]);3. Bigger jobs
start returns right away; waitForRun / wait_for_run checks every 2 seconds until the run is done.
const queued = await pw.start('youtube-transcripts', {"videos":["https://www.youtube.com/watch?v=jNQXAC9IVRw"],"maxResults":3});
const done = await pw.waitForRun(queued.id);
const rows = await pw.results(done.id); // or pw.resultsCsv(done.id)4. Errors
Every error comes with a stable code: INSUFFICIENT_CREDITS (402), INVALID_INPUT (400), RATE_LIMITED (429), UNAUTHORIZED (401). The SDKs throw PullwireError with status, code and message.
import { PullwireError } from '@af/sdk';
try {
await pw.run('youtube-transcripts', { videos: [] });
} catch (err) {
if (err instanceof PullwireError) console.log(err.status, err.code, err.message);
}5. Any other language
The API is plain HTTPS and JSON. The full OpenAPI 3.1 document lives at /api/v1/openapi.json, so you can generate a client for Go, Ruby or anything else.
curl -X POST https://pullwire.dev/api/v1/tools/youtube-transcripts/runs \
-H "x-api-key: YOUR_API_KEY" \
-H "content-type: application/json" \
-d '{"videos":["https://www.youtube.com/watch?v=jNQXAC9IVRw"],"maxResults":3}'The call waits up to 25 seconds for the results. For bigger jobs add ?async=1 to the URL: you get a run id back right away and fetch the results a bit later.