---
title: "Getting started"
description: "Make a key, quote an image, run it, and read the result."
url: https://docs.roasos.com/quickstart
---

# Getting started

This page is one complete flow. It makes a still image with [Nano Banana Pro](/models/image/nano-banana-pro). The image costs **2 credits** at the default resolution.

Every paid action in roasOS uses the same four steps: **key, quote, run, poll**. The steps hold on both entry paths. Read the flow as REST calls from your own code, or as instructions to an AI agent.

## 1. Make a key

Make an API key in your [workspace settings](https://www.roasos.com/settings/workspace). A key starts with `roasos_sk_`. You need a Growth plan or a Scale plan.

Keep the key on your server. Send it as a bearer token.

```bash
export ROASOS_API_KEY="roasos_sk_..."
```

Test the key:

```bash
curl https://api.roasos.com/v1/account \
  -H "Authorization: Bearer $ROASOS_API_KEY"
```

The response gives your workspace, your plan and your credit balance. Refer to [Authentication](/authentication).

The same key opens the REST API and the MCP server. You need no second credential.

## 2. Quote, run, poll

<Tabs items="['REST API', 'AI agent']">
  <Tab value="REST API">
    ### Quote the image

    Send the request with `quote_only: true`. roasOS calculates the price and spends nothing.

    Each paid request also needs an `Idempotency-Key` header. The value is your own unique text of 16 to 255 characters. Use the same value for the quote and for the run.

    ```bash
    curl -X POST https://api.roasos.com/v1/image/nano-banana-pro \
      -H "Authorization: Bearer $ROASOS_API_KEY" \
      -H "Idempotency-Key: my-first-image-0001" \
      -H "Content-Type: application/json" \
      -d '{
        "quote_only": true,
        "prompt": "A red sneaker on a white background, studio product photo, soft top light."
      }'
    ```

    The response gives the price and a `quote_id`:

    ```json
    {
      "data": {
        "kind": "quote",
        "quote_id": "7f3c1a52-9b04-4e6d-8a71-2c5f0d9e4b13",
        "credits": 2,
        "expires_at": "2026-08-22T10:14:11Z",
        "confirmation": { "model": "nano-banana-pro", "example": "1_image_1K" }
      }
    }
    ```

    A quote is valid for 10 minutes.

    ### Run the image

    Send the **same body** and the &#x2A;*same `Idempotency-Key`**. Put the `quote_id` in place of `quote_only`.

    <Callout type="warn">
      This step uses your credits.
    </Callout>

    ```bash
    curl -X POST https://api.roasos.com/v1/image/nano-banana-pro \
      -H "Authorization: Bearer $ROASOS_API_KEY" \
      -H "Idempotency-Key: my-first-image-0001" \
      -H "Content-Type: application/json" \
      -d '{
        "quote_id": "7f3c1a52-9b04-4e6d-8a71-2c5f0d9e4b13",
        "prompt": "A red sneaker on a white background, studio product photo, soft top light."
      }'
    ```

    The response is a job:

    ```json
    {
      "data": {
        "id": "3d9b6c40-51ae-4f28-9c37-8e0a4b71d562",
        "kind": "image",
        "model": "nano-banana-pro",
        "status": "queued",
        "credits_reserved": 2,
        "links": {
          "status": "/v1/jobs/3d9b6c40-51ae-4f28-9c37-8e0a4b71d562/status",
          "result": "/v1/jobs/3d9b6c40-51ae-4f28-9c37-8e0a4b71d562/result"
        }
      }
    }
    ```

    ### Poll, then read the result

    Poll the status every few seconds:

    ```bash
    curl https://api.roasos.com/v1/jobs/3d9b6c40-51ae-4f28-9c37-8e0a4b71d562/status \
      -H "Authorization: Bearer $ROASOS_API_KEY"
    ```

    ```json
    { "data": { "id": "3d9b6c40-51ae-4f28-9c37-8e0a4b71d562", "status": "processing", "updated_at": "..." } }
    ```

    When the status is `completed`, read the result:

    ```bash
    curl https://api.roasos.com/v1/jobs/3d9b6c40-51ae-4f28-9c37-8e0a4b71d562/result \
      -H "Authorization: Bearer $ROASOS_API_KEY"
    ```

    ```json
    {
      "data": {
        "id": "3d9b6c40-51ae-4f28-9c37-8e0a4b71d562",
        "kind": "image",
        "model": "nano-banana-pro",
        "status": "completed",
        "result": {
          "images": ["https://cdn.roasos.com/workspaces/ws_01/images-1.png"]
        }
      }
    }
    ```
  </Tab>

  <Tab value="AI agent">
    ### Connect the server

    Add the roasOS MCP server to your client. This command adds it to Claude Code:

    ```bash
    claude mcp add --transport http roasos https://mcp.roasos.com/mcp \
      --header "Authorization: Bearer $ROASOS_API_KEY"
    ```

    A client that reads a JSON configuration takes the same three values under `mcpServers`:

    ```json
    {
      "mcpServers": {
        "roasos": {
          "type": "http",
          "url": "https://mcp.roasos.com/mcp",
          "headers": { "Authorization": "Bearer roasos_sk_..." }
        }
      }
    }
    ```

    <Callout type="warn">
      A paid tool needs one more transport header: `Idempotency-Key`. The client sends a new value for each new paid request, so that a retry keeps the same billing identity. A read tool needs the API key alone. Refer to [Connect an AI agent (MCP)](/mcp).
    </Callout>

    A read tool needs no other header. Ask the agent to list the catalog, and it calls `roasos_get_catalog` for 0 credits.

    ### Quote the image

    Ask for the price first:

    > Quote a Nano Banana Pro image of a red sneaker on a white background, studio product photo, soft top light.

    The agent calls `roasos_image_nano_banana_pro` with `quote_only: true`. It answers with the same quote envelope as the REST path: 2 credits, one `quote_id`, and a 10-minute expiry.

    ### Run the image

    The paid tool never approves your spend by itself. A call with no `quote_only` and no `quote_id` answers `quote_required`. Confirm the price in words:

    > Confirm that quote.

    The agent calls the same tool with the `quote_id`. This step uses your credits.

    ### Poll, then read the result

    > Poll that job, then give me the image URL.

    The agent calls `roasos_get_job_status` until the status is `completed`. It then calls `roasos_get_job_result` and reads the URL from `result.images`. Both tools are free.
  </Tab>
</Tabs>

<Callout>
  `GET /v1/jobs/{id}/result` gives `409 run_not_completed` until the job is terminal. Poll the status endpoint first. Refer to [Jobs](/concepts/jobs).
</Callout>

The result file is immutable. Send its URL as the media input of your next request. One example is the first frame of a video.

## Next steps

<Cards>
  <Card title="Nano Banana Pro" href="/models/image/nano-banana-pro">
    One page per model endpoint: the fields, the media roles and the prices.
  </Card>

  <Card title="Workflows" href="/workflows">
    One call for a whole creative job: analyze, remix, recast, animate, statics.
  </Card>

  <Card title="Quotes and credits" href="/concepts/quotes-and-credits">
    How roasOS calculates a price and charges your credits.
  </Card>

  <Card title="Jobs" href="/concepts/jobs">
    The job envelope, the five statuses, and the read paths.
  </Card>

  <Card title="Research competitor ads" href="/workflows/research-ads">
    Read the real ads that one company runs on Facebook.
  </Card>

  <Card title="Connect an AI agent (MCP)" href="/mcp">
    The endpoint, the client recipes and the whole tool list.
  </Card>
</Cards>
