> ## Documentation Index
> Fetch the complete documentation index at: https://docs.samsa.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Create an API key and generate your first image with a trained style model in five steps.

This guide takes you from zero to a finished image in five steps: create a key,
verify it, submit a generation, poll for the result, and download it. Every call
targets the base URL:

```
https://api.samsa.ai/public/v1
```

<Note>
  The examples use a fake key (`samsa_sk_example…`) and placeholder ids. Replace
  them with your own. Store your key in an environment variable so it never lands
  in source control:

  ```bash theme={null}
  export SAMSA_API_KEY="samsa_sk_exampleXf9Lp2QyaBcDeFgHiJkLmNoPqRsTuVwx"
  ```
</Note>

## Create an API key

API keys are **organization-owned** and can only be created by an organization
**admin** (`OWNER` or `ADMIN`).

<Steps>
  <Step title="Open your organization settings">
    In the [Samsa app](https://app.samsa.ai), go to your organization settings and
    open the **API Keys** tab.
  </Step>

  <Step title="Create a key">
    Give the key a name. By default it is granted **all scopes**
    (`images.generate`, `images.edit`, `videos.generate`, `models.read`,
    `models.write`, `usage.read`); narrow them if the integration needs less.
    You can also set an optional expiry.
  </Step>

  <Step title="Copy the key now">
    <Warning>
      The full key (`samsa_sk_…`) is shown **exactly once**, at creation. Samsa
      stores only a hash and can never display it again. Copy it immediately and
      keep it somewhere safe — if you lose it, revoke the key and create a new one.
    </Warning>
  </Step>
</Steps>

Keys act **for their organization**: credits are drawn from the organization's
pool, and any images or videos you generate appear in the app under the account
of the admin who created the key.

## Verify the key with `GET /me`

`GET /me` is the fastest way to confirm a key works. It returns the key's
organization, its safe metadata (prefix, scopes, expiry — never the secret), and
the organization's available credit balance.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.samsa.ai/public/v1/me \
    -H "Authorization: Bearer $SAMSA_API_KEY"
  ```

  ```python Python theme={null}
  import os
  import requests

  BASE_URL = "https://api.samsa.ai/public/v1"
  API_KEY = os.environ["SAMSA_API_KEY"]
  HEADERS = {"Authorization": f"Bearer {API_KEY}"}

  resp = requests.get(f"{BASE_URL}/me", headers=HEADERS)
  resp.raise_for_status()
  print(resp.json())
  ```

  ```typescript TypeScript theme={null}
  const BASE_URL = "https://api.samsa.ai/public/v1";
  const API_KEY = process.env.SAMSA_API_KEY!;
  const headers = { Authorization: `Bearer ${API_KEY}` };

  const resp = await fetch(`${BASE_URL}/me`, { headers });
  if (!resp.ok) throw new Error(`GET /me failed: ${resp.status}`);
  console.log(await resp.json());
  ```
</CodeGroup>

```json Response theme={null}
{
  "organization": {
    "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "name": "Acme Inc"
  },
  "api_key": {
    "id": "9c8d7e6f-5a4b-4c3d-2e1f-0a9b8c7d6e5f",
    "name": "Production key",
    "prefix": "samsa_sk_exam",
    "scopes": [
      "images.edit",
      "images.generate",
      "models.read",
      "models.write",
      "usage.read",
      "videos.generate"
    ],
    "expires_at": null
  },
  "credits": {
    "available": 1450
  }
}
```

## Generate an image

Submit a prompt to `POST /images/generations`. Here we also compose one of the
organization's trained **style** models by passing its id as `style_id` — you can
combine `object_ids`, `person_ids`, `setting_ids`, and a `color_palette_id` the
same way. The request returns `202` immediately with a job `id`; the image is
produced asynchronously.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.samsa.ai/public/v1/images/generations \
    -H "Authorization: Bearer $SAMSA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "A minimalist product shot of a ceramic mug on linen, soft daylight",
      "style_id": "2b9d1f7a-3c4e-4a5b-9c8d-0e1f2a3b4c5d",
      "aspect_ratio": "1:1",
      "resolution": "1K",
      "num_outputs": 1
    }'
  ```

  ```python Python theme={null}
  payload = {
      "prompt": "A minimalist product shot of a ceramic mug on linen, soft daylight",
      "style_id": "2b9d1f7a-3c4e-4a5b-9c8d-0e1f2a3b4c5d",
      "aspect_ratio": "1:1",
      "resolution": "1K",
      "num_outputs": 1,
  }

  resp = requests.post(
      f"{BASE_URL}/images/generations",
      headers={**HEADERS, "Content-Type": "application/json"},
      json=payload,
  )
  resp.raise_for_status()
  job = resp.json()
  generation_id = job["id"]
  print(job)
  ```

  ```typescript TypeScript theme={null}
  const payload = {
    prompt: "A minimalist product shot of a ceramic mug on linen, soft daylight",
    style_id: "2b9d1f7a-3c4e-4a5b-9c8d-0e1f2a3b4c5d",
    aspect_ratio: "1:1",
    resolution: "1K",
    num_outputs: 1,
  };

  const submit = await fetch(`${BASE_URL}/images/generations`, {
    method: "POST",
    headers: { ...headers, "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });
  if (!submit.ok) throw new Error(`generation failed: ${submit.status}`);
  const job = await submit.json();
  const generationId = job.id;
  console.log(job);
  ```
</CodeGroup>

```json Response — 202 Accepted theme={null}
{
  "id": "7f9c0e2a-1b3d-4c5e-8f6a-9b0c1d2e3f40",
  "status": "pending",
  "estimated_credits": 5
}
```

<Note>
  The default engine is `nano_banana_pro` (pass `engine` to choose
  `nano_banana_2`). `num_outputs` defaults to **1**; each output costs
  `5` credits at `1K`, scaling with resolution (`1K` ×1, `2K` ×2, `4K` ×4). The
  `style_id` must reference a `completed` model in your organization.
</Note>

## Poll for the result

Poll `GET /images/generations/{id}` until `status` is `completed` (or `failed`).
Statuses are `pending`, `processing`, `completed`, `failed`, and `cancelled`.

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.samsa.ai/public/v1/images/generations/7f9c0e2a-1b3d-4c5e-8f6a-9b0c1d2e3f40 \
    -H "Authorization: Bearer $SAMSA_API_KEY"
  ```

  ```python Python theme={null}
  import time

  while True:
      resp = requests.get(
          f"{BASE_URL}/images/generations/{generation_id}",
          headers=HEADERS,
      )
      resp.raise_for_status()
      result = resp.json()
      if result["status"] in ("completed", "failed", "cancelled"):
          break
      time.sleep(2)

  print(result)
  ```

  ```typescript TypeScript theme={null}
  async function poll(id: string) {
    while (true) {
      const resp = await fetch(`${BASE_URL}/images/generations/${id}`, { headers });
      if (!resp.ok) throw new Error(`poll failed: ${resp.status}`);
      const result = await resp.json();
      if (["completed", "failed", "cancelled"].includes(result.status)) {
        return result;
      }
      await new Promise((r) => setTimeout(r, 2000));
    }
  }

  const result = await poll(generationId);
  console.log(result);
  ```
</CodeGroup>

```json Response — completed theme={null}
{
  "id": "7f9c0e2a-1b3d-4c5e-8f6a-9b0c1d2e3f40",
  "status": "completed",
  "created_at": "2026-07-02T12:00:00Z",
  "credits_used": 5,
  "images": [
    {
      "id": "d4c3b2a1-6f5e-4b3a-9d8c-1e0f2a3b4c5d",
      "url": "https://cdn.samsa.ai/user-.../7f9c0e2a.png?X-Amz-Signature=...",
      "thumbnail_url": "https://cdn.samsa.ai/user-.../7f9c0e2a-thumb.png?X-Amz-Signature=...",
      "width": 1024,
      "height": 1024,
      "seed": 128390
    }
  ],
  "error": null
}
```

## Download the result

Each entry in `images` carries a presigned HTTPS `url` that is valid for **24
hours** — download and store the asset before it expires.

<CodeGroup>
  ```bash curl theme={null}
  curl -o mug.png \
    "https://cdn.samsa.ai/user-.../7f9c0e2a.png?X-Amz-Signature=..."
  ```

  ```python Python theme={null}
  image_url = result["images"][0]["url"]
  img = requests.get(image_url)
  img.raise_for_status()
  with open("mug.png", "wb") as f:
      f.write(img.content)
  ```

  ```typescript TypeScript theme={null}
  const imageUrl = result.images[0].url;
  const img = await fetch(imageUrl);
  const buffer = Buffer.from(await img.arrayBuffer());
  await import("node:fs/promises").then((fs) => fs.writeFile("mug.png", buffer));
  ```
</CodeGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="API reference" icon="terminal" href="/api-reference/introduction">
    The base URL, authentication, and the conventions every endpoint shares.
  </Card>

  <Card title="MCP server" icon="plug" href="/mcp">
    Connect Samsa to Claude, ChatGPT, or any MCP client and generate media as
    tools — over OAuth or an API key.
  </Card>
</CardGroup>

<Tip>
  Prefer push over polling? Pass a `webhook_url` on any generation request to
  receive a signed callback the moment the job reaches a terminal status.
</Tip>
