> For the complete documentation index, see [llms.txt](https://docs.aiclicks.io/llms.txt).
> Use it to discover all available pages before exploring further.

# Overview

Envelope, headers, caching, dates, and error semantics for the AIclicks API.

The AIclicks API is read-only and JSON over HTTPS. All endpoints are `GET`, mounted under `/api/v1/`, and share the conventions below.

## Base URL

```typescript
https://api.aiclicks.io
```

All paths in the reference are appended to this base.

## Authentication

Every request must include an API key as a Bearer token:

```typescript
Authorization: Bearer ak_live_<your-key>
```

Mint keys in the dashboard under **Settings → Developers**. Each key inherits:

- The team it was created on (team key), or **all your teams** (master key). Data is scoped accordingly.
- The `allowed_domains` allowlist of the user who created it.
- The team's `developer_access` flag — keys on disabled teams return `403`.

Validate a key at any time with ``.

## Response envelope

Every successful response shares the same envelope:

```jsonc
{
  "data": { /* endpoint payload */ },
  "generated_at": "2026-06-17T10:00:11.218Z"
  // plus echoed query params (e.g. "domain_id", "days") for traceability
}
```

| Field             | Type   | Description                                                            |
| ----------------- | ------ | ---------------------------------------------------------------------- |
| `data`            | object | Endpoint-specific payload. List endpoints nest under `data.items`.     |
| `generated_at`    | string | ISO-8601 timestamp when the server produced (or cached) this response. |
| `<echoed params>` | varies | Each endpoint echoes the meaningful query params it received.          |

List endpoints (`/domains`, `/prompts`, `/fanout-queries`) use this shape under `data`:

```jsonc
{
  "data": {
    "items": [ /* ... */ ],
    "total": 87,
    "page": 2,
    "size": 25,
    "total_pages": 4
  },
  "generated_at": "..."
}
```

Time-series endpoints return a flat `items` array under `data` with no pagination — one row per day in the requested window.

## Response headers

| Header                  | Purpose                                                                                                |
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
| `X-Cache`               | `HIT`, `MISS`, or `BYPASS`. See [Caching](#caching).                                                   |
| `X-Request-Id`          | Unique id for this request. Echoes the value you sent if you set one. Include this in support tickets. |
| `X-RateLimit-Limit`     | Max requests per minute for this key.                                                                  |
| `X-RateLimit-Remaining` | Requests remaining in the current minute.                                                              |
| `X-RateLimit-Reset`     | Unix epoch seconds when the rate-limit window resets.                                                  |
| `Retry-After`           | Only on `429`. Seconds to wait before retrying.                                                        |

## Pagination

The list endpoints accept:

| Param  | Type    | Default | Max   | Notes                  |
| ------ | ------- | ------- | ----- | ---------------------- |
| `page` | integer | `1`     | —     | 1-indexed page number. |
| `size` | integer | `25`    | `100` | Items per page.        |

Iterate until `page > total_pages`. No cursor-based pagination today.

Time-series endpoints do not paginate — they return all days in the requested window.

## Date filtering

Time-series endpoints accept a `days=N` query parameter:

- Range: 1–365. Default: `30`.
- Honoured exactly: `days=95` returns the last 95 days. Values are not snapped to buckets.
- The window is `[today − N days, today]` in UTC.

Changed 14 September 2026.  used to be rounded up to the next bucket. Every time-series endpoint now honours the value you send. Only clients that relied on the old bucketing see a different window; no request that was valid before has become invalid.

## Caching

Most endpoints are cached server-side for **1 hour** per `(endpoint, domain, query params)`. The `X-Cache` header tells you which path served the response:

- `MISS` — fresh computation. Cached for the next caller.
- `HIT` — served from cache. `generated_at` reflects when the cached entry was produced.
- `BYPASS` — endpoint is not cached (e.g. `/validate`).

A `HIT`'s `generated_at` may be up to one hour old. There is no cache-bust mechanism — invalidation is TTL-based.

## Errors

All errors return JSON with a `detail` field:

```jsonc
{ "detail": "Domain not found" }
```

| Status                | Meaning                                                                                     |
| --------------------- | ------------------------------------------------------------------------------------------- |
| `400`                 | Malformed request — wrong query parameter type, value out of range, missing `domain_id`.    |
| `401`                 | Missing, malformed, or revoked API key.                                                     |
| `403`                 | Valid key but no permission — wrong team, domain not in scope, `developer_access` disabled. |
| `404`                 | Domain or resource id not found, or path doesn't exist.                                     |
| `405`                 | Wrong HTTP method on a valid path.                                                          |
| `429`                 | Rate limit exceeded. See [Rate Limits](/rate-limits).                                       |
| `500`                 | Internal server error. Include the response `X-Request-Id` when reporting.                  |
| `502` / `503` / `504` | Upstream issue. Safe to retry with exponential backoff.                                     |

## Idempotency

All endpoints are `GET` and therefore idempotent. Retries are always safe.

## Tracing & support

To correlate requests with our logs, send your own `X-Request-Id` header:

```bash
curl https://api.aiclicks.io/api/v1/domains \
  -H "Authorization: Bearer $AICLICKS_API_KEY" \
  -H "X-Request-Id: $(uuidgen)"
```

When contacting [support@aiclicks.io](mailto:support@aiclicks.io), include:

1. The full request URL.
2. The `X-Request-Id` from the response (or the one you sent).
3. The time of the request, with timezone.

## Versioning

All endpoints are mounted under `/api/v1/`. The contract is **additive** — we may add fields without warning, but won't remove or rename fields without a deprecation window. When `/api/v2/` ships, `/api/v1/` will run in parallel for at least 6 months. Sunset dates will be announced by email and via `Deprecation` / `Sunset` response headers (RFC 8594).
