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

# API Overview

> REST API for reading your Chartcastr sources and the latest pulse (chart image + AI summary + long analysis) for each source. Authenticated with an API key.

## Overview

The Chartcastr Public API is a small, read-only REST surface for fetching your data sources and the latest [pulse](/admin/pulses) for each — the chart image, the short AI summary, and the long AI analysis.

It's the same data you see in your dashboard, available programmatically for embeds, internal tools, AI agents, or any integration project that needs structured access to your delivered insights.

<Note>
  For richer agent-style access (search, verify, deep links) use the [MCP integrations](/integrations/ai-tools) — Claude, ChatGPT, Cursor, and Codex all connect via API key.
</Note>

## Base URL

```
https://public.api.chartcastr.com/v1
```

The same routes are also reachable at `https://api.chartcastr.com/v1` (the production server uses both hosts).

## Authentication

All requests require an API key passed in the `X-API-Key` header.

```bash theme={null}
curl https://public.api.chartcastr.com/v1/sources \
  -H "X-API-Key: sk_live_..."
```

Generate keys from **[Settings → API Keys](https://chartcastr.com/admin/settings/api-keys?create=true)** in your Chartcastr dashboard. Each key is scoped to a single account. Default expiry is 90 days.

<Warning>
  API keys are shown **once** at creation time. Store them securely — if you lose a key you must revoke and regenerate.
</Warning>

### Verify your key

There's no dedicated `/ping` endpoint — instead, call `GET /v1/sources` to confirm a key works. Every successful response includes a `meta.account` object, so this single call doubles as both an access check and your first useful query. `200` means the key resolved; `401` means it's missing, invalid, or expired.

<Accordion title="GET /v1/sources — verify key & resolve account" icon="key">
  Use this any time you want to confirm a key works before running a heavier integration flow. The response also tells you which account/email the key is bound to.

  **Request**

  ```bash theme={null}
  curl https://public.api.chartcastr.com/v1/sources \
    -H "X-API-Key: sk_live_..."
  ```

  **Success — 200**

  ```json theme={null}
  {
    "meta": {
      "account": {
        "id": "acc_2abc...",
        "email": "you@example.com"
      },
      "requestedAt": "2026-05-08T10:31:48.000Z"
    },
    "sources": [ /* ... */ ]
  }
  ```

  **Failure — 401**

  ```json theme={null}
  {
    "success": false,
    "error": "Invalid or expired API key"
  }
  ```

  <Tip>
    In CI/CD or onboarding flows, branch on the HTTP status: `200` → key works, `401` → prompt the user to regenerate, `429` → back off and retry.
  </Tip>
</Accordion>

#### Common failure modes

| Symptom                                   | Likely cause                                            |
| ----------------------------------------- | ------------------------------------------------------- |
| `401 Invalid or expired API key`          | Key revoked, expired, or never existed                  |
| `401 Authentication required`             | `X-API-Key` header missing entirely                     |
| `429 Too Many Requests`                   | More than 60 calls in the last minute on this key       |
| `200` but `meta.account.id` is unexpected | The key belongs to a different account than you thought |

## Response Shape

Every successful response includes a `meta` object so you can confirm which account the key resolved to:

```json theme={null}
{
  "meta": {
    "account": {
      "id": "acc_...",
      "email": "you@example.com"
    },
    "requestedAt": "2026-05-08T10:31:48.000Z"
  },
  "sources": [ ... ]
}
```

## Errors

| Status | Meaning                                             |
| ------ | --------------------------------------------------- |
| `401`  | Missing or invalid `X-API-Key`                      |
| `403`  | Key valid but lacks the required scope              |
| `404`  | Resource (source, pulse) not found for this account |
| `429`  | Rate limit exceeded                                 |
| `500`  | Server error — retry with backoff                   |

Error bodies follow the shape:

```json theme={null}
{
  "success": false,
  "error": "No pulse found for this source"
}
```

## Rate Limits

Public API endpoints are rate limited to **60 requests per minute** per API key. Each response includes the current window state in headers:

| Header                  | Description                                     |
| ----------------------- | ----------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests per window                     |
| `X-RateLimit-Remaining` | Requests left in the current window             |
| `X-RateLimit-Reset`     | Unix timestamp (seconds) when the window resets |

## OpenAPI Spec

The full machine-readable spec is served at:

```
GET https://public.api.chartcastr.com/v1/openapi.yaml
```

You can paste this directly into Postman, Insomnia, or any OpenAPI-aware tool to generate a typed client.

## Endpoints

<CardGroup cols={2}>
  <Card title="Sources" icon="database" href="/api/sources">
    List configured data sources.
  </Card>

  <Card title="Pulses" icon="chart-line" href="/api/pulses">
    Fetch the latest pulse for a source.
  </Card>
</CardGroup>
