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

# Developer API Quickstart

> Create an Account API key, run a CREAO agent from your backend, and handle the result.

## Before you start

Use this guide when your backend calls the CREAO Developer API directly.

| Requirement     | Value                                               |
| --------------- | --------------------------------------------------- |
| Product surface | [Developer Console](https://developer.creao.ai/)    |
| Base URL        | `https://developer.creao.ai`                        |
| Auth key        | Account API key starting with `cr_sk_`              |
| Caller          | Your server, worker, queue consumer, or backend job |
| Main run route  | `POST /v1/runs`                                     |

<Warning>
  Never send a `cr_sk_` Account API key to browser frontend code, mobile apps, public repositories, analytics events, or client logs.
</Warning>

<Note>
  If you are using `agent.creao.ai` in the browser, start with [Using CREAO](/getting-started/quickstart). If you need an app-scoped key for one browser-created agent, see [API Trigger](/pro/api-trigger). This page covers the Developer Platform `/v1/*` API.
</Note>

## 1. Create an Account API key

Open [Developer Console](https://developer.creao.ai/), go to **API Keys**, and create an Account API key. Store it in your backend secret manager.

For local testing, set it as an environment variable:

```bash theme={null}
export CREAO_API_KEY="cr_sk_your_key_here"
```

## 2. Create or choose an agent

You can create a personal agent through the API, or copy an existing `agent_id` from Developer Console.

```bash theme={null}
curl -X POST https://developer.creao.ai/v1/agents \
  -H "Authorization: Bearer $CREAO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stock Analysis Agent",
    "description": "Builds a stock analysis memo from public filings and price history.",
    "skill_content": "# Stock Analysis Agent\n\nBuild a concise stock analysis memo from the provided ticker, company, and reporting period.",
    "config": {
      "inputs": {
        "ticker": { "type": "string" },
        "reporting_period": { "type": "string" }
      }
    },
    "write_autonomy": "full_auto"
  }'
```

The response includes an `agent_id`:

```json theme={null}
{
  "agent_id": "00000000-0000-4000-8000-000000000000",
  "name": "Stock Analysis Agent",
  "status": "active"
}
```

## 3. Start an async run

Use async runs for jobs that can finish in the background. Store the returned `run_id` and `conversation_id`.

```bash theme={null}
curl -X POST https://developer.creao.ai/v1/runs \
  -H "Authorization: Bearer $CREAO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "00000000-0000-4000-8000-000000000000",
    "input": {
      "ticker": "AAPL",
      "reporting_period": "2025 Q4"
    }
  }'
```

```json theme={null}
{
  "run_id": "11111111-1111-4111-8111-111111111111",
  "status": "pending",
  "agent_id": "00000000-0000-4000-8000-000000000000",
  "conversation_id": "22222222-2222-4222-8222-222222222222"
}
```

## 4. Poll for completion

Poll `GET /v1/runs/{run_id}` until the status is terminal.

```bash theme={null}
curl https://developer.creao.ai/v1/runs/11111111-1111-4111-8111-111111111111 \
  -H "Authorization: Bearer $CREAO_API_KEY"
```

Terminal statuses are `completed`, `failed`, and `cancelled`.

```json theme={null}
{
  "run_id": "11111111-1111-4111-8111-111111111111",
  "status": "completed",
  "agent_id": "00000000-0000-4000-8000-000000000000",
  "conversation_id": "22222222-2222-4222-8222-222222222222",
  "result": {
    "text": "Stock analysis memo..."
  },
  "usage": {
    "credits": 12
  }
}
```

## 5. Continue context

Pass a previous `conversation_id` when follow-up runs should share context with earlier work.

```bash theme={null}
curl -X POST https://developer.creao.ai/v1/runs \
  -H "Authorization: Bearer $CREAO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "00000000-0000-4000-8000-000000000000",
    "conversation_id": "22222222-2222-4222-8222-222222222222",
    "input": {
      "ticker": "AAPL",
      "reporting_period": "2025 Q4",
      "follow_up": "Add a downside-risk section and summarize the key valuation assumptions."
    }
  }'
```

`conversation_id` is opaque and account-scoped. Store your own user, tenant, or workflow ID next to it in your database.

## Realtime streaming

Use `POST /v1/realtime/runs` when your product needs live output over Server-Sent Events instead of polling.

```bash theme={null}
curl -N -X POST https://developer.creao.ai/v1/realtime/runs \
  -H "Authorization: Bearer $CREAO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "00000000-0000-4000-8000-000000000000",
    "input": {
      "ticker": "AAPL",
      "reporting_period": "2025 Q4"
    }
  }'
```

The stream emits typed events such as `run.created`, `output_text.delta`, `artifact.created`, `run.completed`, `run.failed`, and `error`. See [Streaming Events](/developer-api/streaming-events).

## Webhooks

For async runs, include `webhook_url` when your backend should receive the terminal result.

```bash theme={null}
curl -X POST https://developer.creao.ai/v1/runs \
  -H "Authorization: Bearer $CREAO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "00000000-0000-4000-8000-000000000000",
    "input": { "ticker": "AAPL", "reporting_period": "2025 Q4" },
    "webhook_url": "https://api.example.com/webhooks/creao"
  }'
```

Your webhook endpoint should accept duplicate terminal notifications and verify that the `run_id` belongs to a request your system created. Polling remains the fallback if delivery fails. See [Webhooks](/developer-api/webhooks).

## Production checklist

* Keep `cr_sk_` keys in a server-side secret store.
* Store `agent_id`, `run_id`, and `conversation_id` as separate identifiers.
* Treat `conversation_id` as opaque; do not parse it or use it as your user ID.
* Retry `429` responses only after `Retry-After` when the header is present.
* Use idempotency in your own queue or job table before creating non-idempotent runs.
* Map stable `error` codes from [Errors](/developer-api/errors), not English messages.
* Use [Rate Limits](/developer-api/rate-limits) and Developer Console to understand account-level throughput.
