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

# Quickstart

> Go from API key to first Decart output in minutes

Get your first successful Decart result in under 5 minutes.

## Prerequisites

* A Decart account at [platform.decart.ai](https://platform.decart.ai)
* An [API key](/getting-started/authentication)

```bash theme={null}
export DECART_API_KEY="your-api-key-here"
```

<Tip>
  Using an AI coding agent? Run `npx skills add https://docs.platform.decart.ai` to teach it Decart's APIs, or [connect the MCP server](/getting-started/ai-coding-agents) for live docs search.
</Tip>

## Pick your first integration path

<Tabs>
  <Tab title="Realtime">
    ### 1) Install SDK

    ```bash theme={null}
    npm install @decartai/sdk
    ```

    ### 2) Connect camera + model

    ```typescript theme={null}
    import { createDecartClient, models } from "@decartai/sdk";

    const model = models.realtime("lucy-latest");

    // Request camera access — will throw if the user denies permission
    let stream: MediaStream;
    try {
      stream = await navigator.mediaDevices.getUserMedia({
        video: { frameRate: model.fps, width: model.width, height: model.height },
        audio: true,
      });
    } catch (err) {
      if (err instanceof DOMException && err.name === "NotAllowedError") {
        console.error("Camera permission denied. Please allow camera access and reload.");
      } else {
        console.error("Could not access camera:", err);
      }
      throw err;
    }

    const client = createDecartClient({ apiKey: process.env.DECART_API_KEY });

    const realtimeClient = await client.realtime.connect(stream, {
      model,
      mirror: "auto",
      onRemoteStream: (remoteStream) => {
        document.getElementById("output").srcObject = remoteStream;
      },
      onError: (err) => {
        console.error("Realtime connection error:", err);
      },
      onDisconnect: (reason) => {
        console.log("Disconnected:", reason);
      },
      initialState: {
        prompt: { text: "Substitute the character in the video with an anime-style hero with spiky silver hair and glowing blue eyes.", enhance: true },
      },
    });

    // Switch to a different transformation on the fly
    await realtimeClient.setPrompt("Substitute the character in the video with a Renaissance oil painting portrait.");
    ```

    ### Expected result

    You should see the transformed stream rendered in your output video element.

    <Warning>
      **Common issues:**

      * **Camera permission denied** — the browser will prompt the user. If denied, `getUserMedia` throws a `NotAllowedError`.
      * **No camera found** — throws a `NotFoundError`. Check that a video device is connected.
      * **Connection drops** — the `onDisconnect` callback fires. In production, implement reconnection logic.
    </Warning>

    <Tip>
      For browser/mobile production setups, use [Client Tokens](/getting-started/client-tokens) instead of exposing a permanent API key.
    </Tip>
  </Tab>

  <Tab title="Video Editing">
    ### 1) Submit + poll with the SDK

    ```typescript theme={null}
    import { createDecartClient, models } from "@decartai/sdk";
    import { writeFileSync } from "fs";

    const client = createDecartClient({ apiKey: process.env.DECART_API_KEY });

    const result = await client.queue.submitAndPoll({
      model: models.video("lucy-latest"),
      data: "https://example.com/input_video.mp4",
      prompt: "Transform into Studio Ghibli animation style",
      onStatusChange: (job) => console.log(`Status: ${job.status}`),
    });

    if (result.status === "completed") {
      const buffer = Buffer.from(await result.data.arrayBuffer());
      writeFileSync("transformed_video.mp4", buffer);
    }
    ```

    ### 2) Same flow in multiple languages

    <CodeGroup>
      ```typescript JavaScript SDK theme={null}
      import { createDecartClient, models } from "@decartai/sdk";

      const client = createDecartClient({ apiKey: process.env.DECART_API_KEY });

      const result = await client.queue.submitAndPoll({
        model: models.video("lucy-latest"),
        data: "https://example.com/input_video.mp4",
        prompt: "Transform into Studio Ghibli animation style",
        onStatusChange: (job) => console.log(job.status),
      });
      ```

      ```python Python SDK theme={null}
      import asyncio
      import os
      from decart import DecartClient, models

      async def main():
          async with DecartClient(api_key=os.getenv("DECART_API_KEY")) as client:
              result = await client.queue.submit_and_poll({
                  "model": models.video("lucy-latest"),
                  "data": "https://example.com/input_video.mp4",
                  "prompt": "Transform into Studio Ghibli animation style",
                  "on_status_change": lambda job: print(job.status),
              })

      asyncio.run(main())
      ```

      ```bash cURL theme={null}
      JOB_ID=$(curl -s -X POST https://api.decart.ai/v1/jobs/lucy-latest \
        -H "X-API-KEY: $DECART_API_KEY" \
        -F "data=@input_video.mp4" \
        -F "prompt=Transform into Studio Ghibli animation style" | jq -r '.job_id')

      while true; do
        STATUS=$(curl -s -H "X-API-KEY: $DECART_API_KEY" \
          https://api.decart.ai/v1/jobs/$JOB_ID | jq -r '.status')
        [ "$STATUS" = "completed" ] && break
        [ "$STATUS" = "failed" ] && exit 1
        sleep 2
      done

      curl -H "X-API-KEY: $DECART_API_KEY" \
        https://api.decart.ai/v1/jobs/$JOB_ID/content --output transformed_video.mp4
      ```
    </CodeGroup>

    ### Expected result

    You should have `transformed_video.mp4` in your current directory.
  </Tab>

  <Tab title="Image Editing">
    ```typescript theme={null}
    import { createDecartClient, models } from "@decartai/sdk";
    import { readFileSync } from "fs";

    const client = createDecartClient({ apiKey: process.env.DECART_API_KEY });

    const imageBuffer = readFileSync("input.jpg");
    const imageBlob = new Blob([imageBuffer], { type: "image/jpeg" });

    const result = await client.process({
      model: models.image("lucy-image-2"),
      prompt: "Transform into a watercolor painting style",
      data: imageBlob,
      resolution: "720p",
    });

    document.querySelector("img").src = URL.createObjectURL(result);
    ```
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="Lucy 2.1 Realtime" icon="sparkles" href="/models/realtime/lucy-2.1">
    Start with the flagship realtime model for character transformation.
  </Card>

  <Card title="JavaScript Realtime SDK" icon="js" href="/sdks/javascript-realtime">
    Full WebRTC integration guide.
  </Card>

  <Card title="Client Tokens" icon="shield" href="/getting-started/client-tokens">
    Secure browser/mobile realtime authentication.
  </Card>

  <Card title="Models" icon="layer-group" href="/getting-started/models">
    Pick the best model for your use case.
  </Card>

  <Card title="Examples Hub" icon="code" href="/examples/overview">
    Browse official examples and realtime-first starter projects.
  </Card>

  <Card title="Use Cases" icon="lightbulb" href="/examples/use-cases">
    See complete realtime and batch product patterns.
  </Card>
</CardGroup>
