Skip to Content
NoCam API

Quickstart

From a key to your first photo and video, in five minutes.

1. Set your key

You need a key: nc_test_… is free and makes sample results, nc_live_… spends credits on real models.

export NOCAM_API_KEY="nc_test_your_key_here"

2. See what's on sale

No key needed for this one.

curl https://api.nocamclub.com/v1/models

Each model has an id, an input_schema (the options it takes) and prices.

3. Make a photo

Prefer: wait=60 holds the call until the photo is ready, for up to 60 seconds.

curl https://api.nocamclub.com/v1/generations \
  -H "Authorization: Bearer $NOCAM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait=60" \
  -H "Idempotency-Key: my-first-photo" \
  -d '{
    "model": "gpt-image-2",
    "input": {
      "prompt": "A yellow taxi in the rain at night, a sign that says OPEN LATE",
      "resolution": "1K",
      "aspect_ratio": "16:9"
    }
  }'

The answer has status: "succeeded" and a link in outputs[0].url. If 60 seconds weren't enough you get 202 and status: "running": go to step 5 to poll it.

4. Use your own photo

Send a public address, or upload the file first (see Uploads). In the prompt, call the first photo img1, the second img2.

curl https://api.nocamclub.com/v1/generations \
  -H "Authorization: Bearer $NOCAM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait=60" \
  -d '{
    "model": "nano-banana-2",
    "input": {
      "prompt": "img1 riding a skateboard on a rooftop at sunset, phone photo",
      "images": ["https://cdn.nocamclub.com/static/test/mascot.jpg"],
      "resolution": "1K",
      "aspect_ratio": "3:4"
    }
  }'

5. Make a video and wait for it

Videos take minutes, longer than one call should stay open. Start it, keep the id, and poll.

const headers = { Authorization: `Bearer ${process.env.NOCAM_API_KEY}`, "Content-Type": "application/json" };

const started = await fetch("https://api.nocamclub.com/v1/generations", {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": "my-first-video" },
  body: JSON.stringify({
    model: "muse-video",
    input: {
      prompt: 'img1 looks at the camera and says: "Hi, this is a quick test."',
      images: ["https://cdn.nocamclub.com/static/test/mascot.jpg"],
    },
  }),
}).then((r) => r.json());

let generation = started;
while (generation.status === "queued" || generation.status === "running") {
  await new Promise((resolve) => setTimeout(resolve, generation.poll_after_ms ?? 3000));
  generation = await fetch(generation.urls.self, { headers }).then((r) => r.json());
}

if (generation.status === "succeeded") console.log(generation.outputs[0].url);
else console.log(generation.error.code, generation.error.message); // The credits are back.

6. Keep what you made

Result links stop working after 7 days. Download what you want to keep.

Next

  • How generations work: statuses, cancel, delete.
  • Errors: what each code means and what to do.
  • Models: which model for which job, and how to write prompts for it.

On this page