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

# Quickstart

> Generate your first image with the Mage API in five minutes: create a key, submit a request with curl, poll the status link until it completes, and download the result.

This walkthrough runs one generation from the command line with `curl` and `jq`. You need a Mage account with Gems on it and the API tab in your settings.

<Warning>
  An API key spends the Gems on your account. Use it in server-side code only,
  and never commit it to source control.
</Warning>

<Steps>
  <Step title="Create a key">
    Open [Settings → API](https://www.mage.space/settings?tab=api), create a key, and copy it. The key starts with `mage_sk_` and is shown once; Mage keeps only a hash of it. Export it in your shell:

    ```bash theme={null}
    export MAGE_API_KEY="mage_sk_..."
    ```
  </Step>

  <Step title="Submit a generation">
    Each model has its own endpoint, `POST /v1/{architecture}/generate`. The body holds the fields you want to set; every other field keeps the model's default. This call uses Flux 2.

    ```bash theme={null}
    curl --request POST \
      --url https://api.mage.space/v1/flux2/generate \
      --header "Authorization: Bearer $MAGE_API_KEY" \
      --header "Content-Type: application/json" \
      --data '{ "prompt": "Editorial portrait in soft daylight, 35mm film look", "aspect_ratio": "portrait" }'
    ```

    The response is the request's current state. Gems are charged now, and `status_url` is where to look next.

    ```json theme={null}
    {
      "request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
      "status": "in_progress",
      "architecture": "flux2",
      "model_id": "flux2-dev",
      "created_at": "2026-09-17T14:52:48.000Z",
      "updated_at": "2026-09-17T14:52:49.000Z",
      "billing": { "mode": "gems", "gems_charged": 40 },
      "result": null,
      "error": null,
      "status_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/status",
      "cancel_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/cancel"
    }
    ```

    Keep `request_id`; everything else about the request is reached through it.

    ```bash theme={null}
    export REQUEST_ID="d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff"
    ```
  </Step>

  <Step title="Poll until it finishes">
    Read `status_url` every few seconds until `status` is `completed`, `failed`, or `cancelled`.

    ```bash theme={null}
    while true; do
      STATE=$(curl --silent \
        --url "https://api.mage.space/v1/requests/$REQUEST_ID/status" \
        --header "Authorization: Bearer $MAGE_API_KEY")
      STATUS=$(echo "$STATE" | jq -r .status)
      [ "$STATUS" = "queued" ] || [ "$STATUS" = "in_progress" ] || break
      sleep 3
    done
    echo "$STATE" | jq .
    ```

    A completed request carries the output in `result`.

    ```json theme={null}
    {
      "request_id": "d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff",
      "status": "completed",
      "architecture": "flux2",
      "model_id": "flux2-dev",
      "created_at": "2026-09-17T14:52:48.000Z",
      "updated_at": "2026-09-17T14:53:10.000Z",
      "billing": { "mode": "gems", "gems_charged": 40 },
      "result": {
        "type": "image",
        "url": "https://cdn3.mage.space/temp/30d/user/image.png",
        "width": 1024,
        "height": 1280,
        "seed": 1234567,
        "expires_at": "2026-10-17T14:52:48.000Z",
        "moderation": { "nsfw": false }
      },
      "error": null,
      "status_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/status",
      "cancel_url": "https://api.mage.space/v1/requests/d7e6c0f3-6699-4f6c-bb45-2ad7fd9158ff/cancel"
    }
    ```
  </Step>

  <Step title="Download the output">
    ```bash theme={null}
    curl --output portrait.png "$(echo "$STATE" | jq -r .result.url)"
    ```

    Temporary media expires 30 days after the request, at `result.expires_at`. Copy what you want to keep to your own storage.
  </Step>
</Steps>

## Cancel a request

A live request stops when you `POST` to its `cancel_url`. The response is the request's state afterwards. Gems are not returned for a cancelled request.

```bash theme={null}
curl --request POST \
  --url "https://api.mage.space/v1/requests/$REQUEST_ID/cancel" \
  --header "Authorization: Bearer $MAGE_API_KEY"
```

## Try a video model

The same call reaches every model; only the endpoint and the fields change. This one runs Plum for five seconds at 16:9. Video takes longer than an image, so poll less often.

```bash theme={null}
curl --request POST \
  --url https://api.mage.space/v1/plum/generate \
  --header "Authorization: Bearer $MAGE_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{ "prompt": "A slow push-in on a lighthouse at dusk, waves breaking below", "plum_aspect_ratio": "16:9", "duration": "5" }'
```

Each model's page lists its fields, the tokens each one accepts, its defaults, and its price at those defaults. The playground on the page runs the call for you.

## Next steps

<CardGroup cols={2}>
  <Card title="Requests and lifecycle" icon="rotate" href="/api/requests">
    Statuses, polling, idempotency keys, cancellation, and results.
  </Card>

  <Card title="Models" icon="layer-group" href="/api/models/overview">
    Every model with its endpoint, fields, and price.
  </Card>

  <Card title="Inputs and uploads" icon="upload" href="/api/inputs">
    Send images and video by URL, data URL, or upload.
  </Card>

  <Card title="Errors and retries" icon="triangle-exclamation" href="/api/errors">
    Every error code, what it means, and what to retry.
  </Card>
</CardGroup>
