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

# Aggregates API Overview

Programmatically provision and manage sub-tenants (aggregates) under your aggregator store. Each aggregate is a fully independent store with its own domain, catalog, and configuration.

---

## Prerequisites

Your store must have the **store aggregation** feature enabled. Contact support to enable aggregation capabilities for your account.

:::warning Aggregated Tenants
Only top-level aggregator stores can use this API. Sub-tenants cannot provision other tenants.
:::

---

## Authentication

| Header           | Example         | Description                                                          |
| ---------------- | --------------- | -------------------------------------------------------------------- |
| **X-User-Token** | `api-abc123...` | API token generated in your dashboard. **Header-only for security.** |

All requests **must** be performed over HTTPS.

```bash
curl -X GET "https://yourstore.publica.la/api/v3/aggregates" \
  -H "X-User-Token: api-abc123..." \
  -H "Accept: application/json"
```

---

## API Endpoints

| Operation       | Method | Endpoint                  | Description                    |
| --------------- | ------ | ------------------------- | ------------------------------ |
| List aggregates | `GET`  | `/api/v3/aggregates`      | List all sub-tenants           |
| Get aggregate   | `GET`  | `/api/v3/aggregates/{id}` | Retrieve a specific aggregate  |
| Create          | `POST` | `/api/v3/aggregates`      | Provision a new sub-tenant     |
| Update          | `PUT`  | `/api/v3/aggregates/{id}` | Update aggregate configuration |

:::info No Delete
Aggregates cannot be deleted via the API. Contact support for tenant deactivation.
:::

---

## What Gets Inherited

When you create an aggregate, the following are automatically inherited from the aggregator:

- **Fees**: transaction and sales fee structure
- **Currencies**: main and secondary currency configuration

The aggregate gets its own independent content catalog, user base, and store configuration. Branding (colors, icons, emails) is set during creation or via update.

---

## Aggregator vs Sub-Tenant API Usage

The Aggregates API (`/api/v3/aggregates`) is used by the **aggregator** to provision and configure sub-tenants (name, domain, branding, support email).

To interact with a sub-tenant's data (content, orders, users), use the sub-tenant's own API endpoints with the `api_key` obtained during creation or via `?include=api_key` on the [list](./aggregates-v3-list.md) and [get](./aggregates-v3-get.md) endpoints.

---

## Cursor Pagination

```json
{
  "data": [...],
  "links": {
    "next": "https://yourstore.publica.la/api/v3/aggregates?cursor=eyJjcmVhdGVkX2F0...",
    "prev": null
  },
  "meta": {
    "has_more": true
  }
}
```

### Pagination Workflow

1. Make initial request without `cursor`
2. Store `links.next` token
3. Use `cursor=<token>` for next page
4. Continue until `meta.has_more` is `false`

:::tip Best Practice
Always use `meta.has_more` to detect the end of results, not by counting items.
:::

---

## Common Response Format

### Single Aggregate

```json
{
  "data": {
    "id": 42,
    "slug": "my-bookstore",
    "name": "My Bookstore",
    "final_domain": "mybookstore.publica.la",
    "lang": "en",
    "timezone": "America/New_York",
    "support_email": "support@mybookstore.com",
    "primary_color": "#336699",
    "secondary_color": "#FF6600",
    "reader_accent_color": "#0066CC",
    "reader_flashcards_enabled": true,
    "logo_url": "https://assets.publica.la/my-bookstore/logo/logo.png",
    "icon_url": "https://assets.publica.la/my-bookstore/icons/icon.png",
    "disable_selling": false,
    "landing_enabled": true,
    "storefront_redirect": {
      "enabled": false,
      "url": null
    },
    "created_at": "2026-03-24T15:30:00+00:00"
  }
}
```

### With `?include=api_key`

The `api_key` is always included in the create response. For existing aggregates, request it explicitly with `?include=api_key`:

```json
{
  "data": {
    "id": 42,
    "slug": "my-bookstore",
    "name": "My Bookstore",
    "final_domain": "mybookstore.publica.la",
    "lang": "en",
    "timezone": "America/New_York",
    "api_key": "a1b2c3d4e5f6...",
    "support_email": "support@mybookstore.com",
    "primary_color": "#336699",
    "secondary_color": null,
    "reader_accent_color": null,
    "reader_flashcards_enabled": false,
    "logo_url": null,
    "icon_url": null,
    "disable_selling": false,
    "landing_enabled": false,
    "storefront_redirect": {
      "enabled": false,
      "url": null
    },
    "created_at": "2026-03-24T15:30:00+00:00"
  }
}
```

:::tip API Key
Use the `api_key` in the `X-User-Token` header to make API requests directly to the sub-tenant's endpoints (content, orders, etc.).
:::

---

## Error Handling

### Authorization Errors (403)

```json
{
  "message": "Tenant does not have aggregation capabilities."
}
```

```json
{
  "message": "Aggregated tenants cannot provision tenants."
}
```

### Validation Errors (422)

```json
{
  "message": "The given data was invalid.",
  "errors": {
    "name": ["The name field is required."],
    "final_domain": ["The final domain has already been taken."]
  }
}
```

### Authentication Errors (401)

```json
{
  "message": "Unauthenticated."
}
```

### Not Found (404)

```json
{
  "message": "Not found."
}
```

---

## Quick Start Examples

### List Your Aggregates

```bash
curl -X GET "https://yourstore.publica.la/api/v3/aggregates?per_page=10" \
  -H "X-User-Token: your-api-token" \
  -H "Accept: application/json"
```

### Create a New Aggregate

```bash
curl -X POST "https://yourstore.publica.la/api/v3/aggregates" \
  -H "X-User-Token: your-api-token" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Bookstore",
    "lang": "en",
    "timezone": "America/New_York",
    "support_email": "support@mybookstore.com"
  }'
```

---

## Rate Limiting

Two limits apply: a per-token burst of **60 requests/minute** and a **daily read quota** of 2,000 reads/token plus 5,000/store (`GET`/`HEAD` only; writes are separate). Exceeding either returns `429 Too Many Requests` with a `Retry-After` header.

Cache responses and avoid re-fetching the same aggregate by ID on every cycle. See the [API Overview](../../rest-api/overview.md#rate-limiting-and-flood-protection) for full details.

---

## Next Steps

- **[Create Aggregate](./aggregates-v3-create.md)** - Provision a new sub-tenant
- **[List Aggregates](./aggregates-v3-list.md)** - Query your aggregates
- **[Get Aggregate](./aggregates-v3-get.md)** - Retrieve aggregate details
- **[Update Aggregate](./aggregates-v3-update.md)** - Modify aggregate configuration

---

## See Also

- [API Authentication](../../rest-api/overview.md)
- [Content API](../content/content-v3-overview.md) - Manage content catalog
- [Orders API](../orders/orders-v3-overview.md) - Manage customer purchases
