> For the complete documentation index, see [llms.txt](https://docs.sparkloop.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sparkloop.app/api-v3.md).

# API v3

## API v3

SparkLoop's v3 API is organized around your **publications**: most resources are scoped to a publication (`/v3/publications/:publication_uuid/...`), while a few — your account, payouts, and webhooks — are scoped to the whole account.

{% hint style="info" %}
The v3 API returns richer, self-describing payloads. Related objects are referenced by UUID and can be inlined on demand with `expand`, and most performance figures are available inline via `expand=stats`.
{% endhint %}

{% hint style="info" %}
**Building with an LLM or AI agent?** A plain-text index of the entire v3 API — every endpoint with a one-line description and a direct link — is published at [api.sparkloop.app/llms.txt](https://api.sparkloop.app/llms.txt), following the [llms.txt convention](https://llmstxt.org). Point your tooling there for a compact map of the whole API surface.
{% endhint %}

{% hint style="info" %}
**This version of the API is available on request.** Contact the [SparkLoop support team](mailto:support@sparkloop.app) to have v3 access enabled for your account.
{% endhint %}

### Base URL

```
https://api.sparkloop.app/v3
```

### Authentication

Send your API key in the `x-api-key` header on every request. All requests act as the team that owns the key.

```bash
curl https://api.sparkloop.app/v3/account \
  -H "x-api-key: YOUR_API_KEY"
```

| Status | Body                                 | When                   |
| ------ | ------------------------------------ | ---------------------- |
| `401`  | `{ "error": "API key is missing!" }` | No `x-api-key` header. |
| `401`  | `{ "error": "Account not found!" }`  | Unknown API key.       |
| `401`  | `{ "error": "API key is invalid!" }` | Invalidated API key.   |

### Pagination

List endpoints are paginated and return a `meta` block alongside the results.

| Parameter  | In    | Type    | Description                                          |
| ---------- | ----- | ------- | ---------------------------------------------------- |
| `page`     | query | integer | Page number. Defaults to `1`.                        |
| `per_page` | query | integer | Results per page. Defaults to `50`, capped at `200`. |

The `meta` block, where `total_<resource>` is named after the listed resource (e.g. `total_publications`, `total_surveys`):

```json
{
  "meta": {
    "per_page": 50,
    "page": 1,
    "total_pages": 4,
    "total_<resource>": 187
  }
}
```

### Expanding objects

Related objects are returned as a UUID string by default. Pass `expand` with a comma-separated list of fields to inline the full object instead.

| Parameter | In    | Type   | Description                                                                    |
| --------- | ----- | ------ | ------------------------------------------------------------------------------ |
| `expand`  | query | string | Comma-separated fields to expand, e.g. `expand=recommended_publication,stats`. |

Each endpoint lists the fields it supports expanding.

### Stats & date range

Performance metrics are opt-in via `expand=stats`. When requested, they cover a date window you control:

| Parameter | In    | Type   | Description                                         |
| --------- | ----- | ------ | --------------------------------------------------- |
| `from`    | query | string | Start date (`YYYY-MM-DD`). Defaults to 30 days ago. |
| `to`      | query | string | End date (`YYYY-MM-DD`). Defaults to today.         |

`from`/`to` only narrow the `stats` window, so they require `expand=stats` — passing them without it returns `400`.

### Errors

Every error uses the same shape:

```json
{ "error": "Resource not found." }
```

| Status | Meaning                                                       |
| ------ | ------------------------------------------------------------- |
| `400`  | Bad request — an unsupported or malformed parameter.          |
| `401`  | Authentication failed — missing, unknown, or invalid API key. |
| `404`  | The resource doesn't exist, or isn't visible to your team.    |
| `422`  | The request was understood but couldn't be processed.         |
