
# Authentication

Every API request must carry your API key so <span data-t="appName">Your AI Connector</span> knows it is you and which account to act on. You can send the key four different ways — all of them work on every endpoint that accepts API-key authentication, so pick whichever fits your setup.

API access is a paid feature. If your plan does not include it, requests are rejected with a `403` even when the key itself is valid — see [The paid-feature gate](#the-paid-feature-gate) below. To generate a key, see [API Access](../integrations/api-access.md).

> **HTTPS only.** All requests must use a secure connection. Plain HTTP requests are rejected before authentication even runs.

---

## The four methods at a glance

| Method | Carrier | When to use |
|---|---|---|
| Query parameter | `?apiKey=YOUR_API_KEY` | Quick tests and browser URLs |
| Header | `X-API-Key: YOUR_API_KEY` | Production integrations |
| Bearer header | `Authorization: Bearer YOUR_API_KEY` | Production integrations |
| Firebase ID token | `Authorization: Bearer <ID token>` | First-party app sessions only |

When more than one is present, the query parameter wins, then the `X-API-Key` header, then the bearer token. In practice you only ever send one.

---

## 1. Query parameter — `?apiKey=`

Add your key to the end of the web address. This is the simplest form and always works, which makes it ideal for quick tests, scripts, and any older tooling.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/contacts?apiKey=YOUR_API_KEY");
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/contacts",
    params={"apiKey": "YOUR_API_KEY"},
)
data = res.json()
```

> **Heads up:** Web addresses end up in browser history, server access logs, and proxy logs. For anything beyond a quick test, prefer one of the header methods below so your key is not written to disk in plain sight.

---

## 2. `X-API-Key` header

Send the key in a dedicated header. This keeps it out of the URL and is the recommended choice for production.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/contacts" \
  -H "X-API-Key: YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/contacts", {
  headers: {
    "X-API-Key": "YOUR_API_KEY",
  },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/contacts",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
data = res.json()
```

---

## 3. `Authorization: Bearer` header

You can also pass the key as a standard bearer token. This is handy when your HTTP client or framework already has built-in support for `Authorization` headers.

**cURL**

```bash
curl "https://api.youraiconnector.com/v1/contacts" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**JavaScript**

```javascript
const res = await fetch("https://api.youraiconnector.com/v1/contacts", {
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
  },
});
const data = await res.json();
```

**Python**

```python
import requests

res = requests.get(
    "https://api.youraiconnector.com/v1/contacts",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = res.json()
```

The API tells your API key apart from a login token automatically, so this method works exactly like `X-API-Key`.

---

## 4. Firebase ID token (first-party only)

If you are building a first-party app that signs users in through <span data-t="appName">Your AI Connector</span>'s own login, you can pass that signed-in user's Firebase ID token as a bearer token instead of an API key:

```
Authorization: Bearer <Firebase ID token>
```

The token is verified on every request and maps to the signed-in account. **This method is only for first-party app sessions** — you cannot mint these tokens from an external integration, and there is no way to obtain one without going through the normal app login. For server-to-server and third-party integrations, use an API key (methods 1–3).

---

## When to use which

- **Quick tests and one-off scripts** → query parameter (`?apiKey=`). Fastest to type, works in a browser.
- **Production integrations and server-to-server calls** → `X-API-Key` or `Authorization: Bearer YOUR_API_KEY`. Keeps the key out of URLs and logs.
- **First-party apps with a logged-in <span data-t="appName">Your AI Connector</span> user** → `Authorization: Bearer <Firebase ID token>`.

---

## Key scopes

Your account has one **main API key** — the one under **Settings → Integrations → API Key**. It has full access to everything the account can do.

You can also create extra **scoped keys**: named keys that only reach the parts of the API you choose, for example a read-only key limited to Analytics for a reporting dashboard. A scoped key is sent exactly like the main key (any of methods 1–3 above), but it is checked against its own permissions on every request:

- **Outside its allowed areas it is refused.** A write with a read-only key, or a call to a section the key was not given, comes back as `403` — `key_read_only` or `key_scope_denied` in the `error_code` field. The check is deliberately strict: anything that is not clearly inside the key's allowed areas is refused rather than let through, so if you see one of those `403`s, the key simply does not cover that endpoint.
- **It has its own rate-limit budget.** A scoped key is counted separately from your main key, so a busy dashboard on a scoped key cannot use up the allowance your other integrations depend on. You choose that per-minute budget when you create the key.
- **It cannot manage API keys.** Only the account owner — signed in, or using the main key — can list, create, edit, rotate or revoke keys. A scoped key can never mint itself a wider one.

See [API Keys](api-keys.md) for how to create, edit and revoke scoped keys.

---

## The paid-feature gate

API access is a paid feature. When your plan does not include it, a request with an otherwise-valid key is rejected with `403`:

```json
{
  "success": false,
  "error_code": 403,
  "error": "This action requires the \"api_access\" feature, which is not enabled for this account."
}
```

If you see this, check your plan or contact [<span data-t="supportEmail">hi@youraiconnector.com</span>](mailto:hi@youraiconnector.com). A missing or wrong key returns `401` instead:

```json
{
  "success": false,
  "error_code": 401,
  "error": "Invalid API key"
}
```

---

## Keeping your key safe

- **Treat the key like a password.** Your main key grants full access to your account. If you need to hand a key to a tool or a person who only needs part of it, create a scoped key instead — see [Key scopes](#key-scopes).
- **Keep it server-side.** Never embed it in browser JavaScript, a mobile app bundle, or any code an end user can read.
- **Store it in a secret manager** or server-side configuration, not in source control.
- **Rotate it if it leaks.** Generate a new key from the dashboard or call `POST https://api.youraiconnector.com/v1/api-keys/rotate` — this immediately invalidates the old one. See [API Keys](api-keys.md).
- **Always use HTTPS** so the key is encrypted in transit.

---

## Next steps

- [Getting Started](getting-started.md) — your first request and the resource guides.
- [Errors & Pagination](errors-and-pagination.md) — handle failures and page through results.
- [API Keys](api-keys.md) — rotate, revoke, and check usage on your key.
