# Getting started with the Node SDK

Install the SDK, submit your first job, and poll it to completion — the submit-and-poll loop every VEED model shares.

Every VEED model works the same way: you submit a job, the API accepts it
immediately, and you poll until it is done. This guide walks that loop end to
end in Node, using Fabric 1.0 as the
example — swap the client method and the inputs and the shape is identical for
every other model.

## Install

```bash
npm install @veedstudio/sdk
```

The client reads `VEED_API_KEY` from the environment, so export the workspace
key you created in the dashboard:

```bash
export VEED_API_KEY="vp_..."
```

## The whole loop

```javascript
import { Veed } from "@veedstudio/sdk";

const client = new Veed(); // reads VEED_API_KEY

const job = await client.fabric.generate({
  audio_url: "https://static-assets.veed.io/api-examples/fabric-input.mp3",
  image_url: "https://static-assets.veed.io/api-examples/fabric-input.png",
  resolution: "720p",
});
console.log(job.result);
```

That is the entire integration. `generate()` submits the job and polls for you,
honouring the interval the API advertises
(`10` seconds for this
model), so you do not write a retry loop by hand.

## What this model takes

- `image_url` · url · required — URL of the source image to animate.
- `audio_url` · url · required — URL of the audio track to lip-sync to.
- `resolution` · enum · required — Output video resolution. Accepts `720p`, `480p`.

Both URLs must be publicly reachable over http(s) — the renderer fetches them
itself, so a signed URL is fine but a localhost address is not.

`resolution` accepts `720p, 480p`.
It is required, and the reference and playground both show `720p` as
the example, which is the resolution most callers want.

## Submitting and polling by hand

If you would rather drive the two calls yourself — a queue worker that persists
the job id, say — they are just the two endpoints the SDK wraps:

`POST /v1/fabric-1.0` — [reference](https://api.veed.io/docs/api/post-v1-fabric-1-0.md)

`GET /v1/fabric-1.0/{job_id}` — [reference](https://api.veed.io/docs/api/get-v1-fabric-1-0-job-id.md)

```javascript
import { Veed } from "@veedstudio/sdk";

const client = new Veed(); // reads VEED_API_KEY

const job = await client.fabric.submit({
  audio_url: "https://static-assets.veed.io/api-examples/fabric-input.mp3",
  image_url: "https://static-assets.veed.io/api-examples/fabric-input.png",
  resolution: "720p",
});
console.log(job.status);
```

The submit call answers `202` with a `job_id` and a status. Poll the second
endpoint with that id until `status` leaves `PROCESSING`:

```javascript
import { Veed } from "@veedstudio/sdk";

const client = new Veed(); // reads VEED_API_KEY

const job = await client.fabric.get("<job_id>");
console.log(job.status);
```

The job envelope you get back is the same either way:

- `credits_charged` · integer · optional — Credits charged for the job. Present once the job is COMPLETED and the final charge is known.
- `credits_estimated` · integer · optional — Credits quoted before the job ran. Present only on the response that created the job. This is an estimate, not the price: the charged amount can be higher or lower.
- `error` · object · optional — Failure information. Present once the job has FAILED.
- `job_id` · uuid · required — Stable identifier of the job and of the resource it produces.
- `result` · object · optional — The produced resource. Present once the job is COMPLETED.
- `status` · enum · required — Current lifecycle state of the job. Accepts `PROCESSING`, `COMPLETED`, `FAILED`, `CANCELLED`.

`status` moves through `PROCESSING, COMPLETED, FAILED, CANCELLED`. Only
`COMPLETED` carries a `result`; only `FAILED` carries an `error`.

## When a job fails

An accepted job can still fail while rendering, and the failure is reported on
the poll response rather than as an HTTP error. The codes this model can return
are `input_validation, content_moderation, invalid_file, audio_too_long, transload_failed, generation_failed, timeout`.

Treat anything other than `COMPLETED` and `PROCESSING` as terminal: a
`CANCELLED` or `FAILED` job will not change state again, and polling it further
only burns rate limit.

## What it costs

It costs $0.08–$0.15 per second of the generated video, billed on the output rather
than on the source image. The [pricing page](https://api.veed.io/pricing) breaks that down per
resolution.

## Next

- Try the same inputs in the playground before you write any code
- Every other model follows this submit-and-poll shape — the reference pages
list the inputs each one takes
