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

# Overview

> Authentication, errors and rate limits.

Use the Demand API to quote and buy sample.

## Typical flow

**1. Get the taxonomy**

Load audiences and filter values with [Get taxonomy](https://docs.emporiaresearch.com/demand-api/get-taxonomy.md).

**2. Get a quote**

Call [Create a preview](https://docs.emporiaresearch.com/demand-api/create-preview.md) to get the feasible N, CPI and a preview `id`.

**3. Create a project**

Call [Create a project](https://docs.emporiaresearch.com/demand-api/create-project.md) with the preview `id`. The response includes your redirect URLs.

**4. Upload your screener**

Add it with [Upload an attachment](https://docs.emporiaresearch.com/demand-api/upload-attachment.md).

**5. Launch it**

Set the status to `ACTIVE` with [Update project status](https://docs.emporiaresearch.com/demand-api/update-project-status.md).

**6. Track respondents**

Use [Get a project](https://docs.emporiaresearch.com/demand-api/get-project.md) and [List respondents](https://docs.emporiaresearch.com/demand-api/list-respondents.md).

## Authentication

Send your API key as a bearer token in the `Authorization` header of every request.

```http theme={null}
Authorization: Bearer <api_key>
```

Requests with a missing or invalid key return `403 UNAUTHORIZED`.

## Request IDs

Send `X-Request-Id` with a request to trace it, and we echo it back. If you don't send one, we generate one. It also appears as `requestId` in error bodies.

## Errors

Errors return a `code`, a `message`, the `requestId` and, for validation errors, the `field` that failed.

```json theme={null}
{
  "error": {
    "code": "INVALID_FILTER_VALUE",
    "message": "Unknown employee range 'FIFTY_TO_FIVE_HUNDRED'.",
    "field": "filters.employeeRanges[0]",
    "requestId": "7c1e4b9a-2f3d-4e8a-9b6c-1d5f8a2e4c7b"
  }
}
```

General errors, which any endpoint can return:

| Status | Code | When |
| - | - | - |
| 400 | `INVALID_REQUEST` | Malformed JSON or an unknown field. |
| 403 | `UNAUTHORIZED` | Missing or invalid API key. |
| 429 | `RATE_LIMITED` | Over the [rate limit](#rate-limits). |
| 500 | `INTERNAL_ERROR` | Server error. |

Endpoint pages list their own codes.

## Rate limits

Limits apply per API key.

| Scope | Limit |
| - | - |
| `POST /v1/preview` | 30 requests per minute |
| Everything else | 120 requests per minute |

Every response includes:

```http theme={null}
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1761580800
```

`X-RateLimit-Reset` is a Unix timestamp. Over the limit, you get `429 RATE_LIMITED` with a `Retry-After` header in seconds.

## Support

For questions about the API, email [engineering@emporiaapp.com](mailto:engineering@emporiaapp.com).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.