# Quickstart

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

Source: https://docs.nocamclub.com/quickstart

## 1. Set your key

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

```bash
export NOCAM_API_KEY="nc_test_your_key_here"
```

## 2. See what's on sale

No key needed for this one.

```bash
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**

```bash
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"
    }
  }'
```

**JavaScript**

```js
const res = await fetch("https://api.nocamclub.com/v1/generations", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NOCAM_API_KEY}`,
    "Content-Type": "application/json",
    Prefer: "wait=60",
    "Idempotency-Key": "my-first-photo",
  },
  body: JSON.stringify({
    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",
    },
  }),
});
const generation = await res.json();
console.log(generation.status, generation.outputs[0]?.url);
```

**Python**

```python
import os, requests

res = requests.post(
    "https://api.nocamclub.com/v1/generations",
    headers={
        "Authorization": f"Bearer {os.environ['NOCAM_API_KEY']}",
        "Prefer": "wait=60",
        "Idempotency-Key": "my-first-photo",
    },
    json={
        "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",
        },
    },
    timeout=90,
)
generation = res.json()
print(generation["status"], generation["outputs"][0]["url"] if generation["outputs"] else None)
```

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](https://docs.nocamclub.com/api/uploads.md)). In the prompt, call the first photo `img1`, the second `img2`.

```bash
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.

**JavaScript**

```js
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.
```

**Python**

```python
import os, time, requests

headers = {"Authorization": f"Bearer {os.environ['NOCAM_API_KEY']}"}

generation = requests.post(
    "https://api.nocamclub.com/v1/generations",
    headers={**headers, "Idempotency-Key": "my-first-video"},
    json={
        "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"],
        },
    },
    timeout=60,
).json()

while generation["status"] in ("queued", "running"):
    time.sleep(generation.get("poll_after_ms", 3000) / 1000)
    generation = requests.get(generation["urls"]["self"], headers=headers, timeout=30).json()

if generation["status"] == "succeeded":
    print(generation["outputs"][0]["url"])
else:
    print(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](https://docs.nocamclub.com/api/generations.md): statuses, cancel, delete.
- [Errors](https://docs.nocamclub.com/errors.md): what each code means and what to do.
- [Models](https://docs.nocamclub.com/models.md): which model for which job, and how to write prompts for it.
