---
url: https://docs.dataflair.ai/marketplace/ad-server-api/authentication.md
description: >-
  The API key you issue to DataFlair, what DataFlair stores about your
  connection, and how the two systems first connect and verify.
---

# Authentication and connection

How DataFlair proves who it is to your API, and how the two systems first shake hands.

## The credential you issue to DataFlair

Authentication is a **single bearer token**. It is a static API key that you generate on your platform and give to DataFlair. There is no OAuth flow, no token endpoint and no login. DataFlair stores the key encrypted and sends it on every request:

```http
Authorization: Bearer sk_live_9f2c…    (opaque, issued by you)
```

Requirements for the key:

* **You issue it.** You generate the key on your own platform and give it to DataFlair. DataFlair does not generate it, and does not ask a person to type a password into your platform.
* **Revocable.** You can revoke and reissue it without downtime, so a leaked key can be rotated.
* **Least privilege.** Scope it to read, create-draft and report only. It must not be able to activate inventory or move money.
* **One key per publisher.** One key authenticates one account. DataFlair holds it encrypted and keeps it out of URLs, log lines and API responses.
* **HTTPS only.** DataFlair refuses a base URL that does not start with `https://`. Its Revive integration enforces the same rule.
* Treat the key like a password. Hash it at rest on your side and do not log it in plaintext.

## What DataFlair stores

For each connected publisher, DataFlair keeps a small connection record.

| Field | Who supplies it | Notes |
| --- | --- | --- |
| `base_url` | You | For example `https://ads.example.com/api/v1`. `https://` is enforced. |
| `api_key` | You | The bearer token. Encrypted at rest and not shown back to a user. |
| `account_name` | Your `/health` response | Display only. |
| `timezone`, `currency` | Your `/health` response | Used to read flight dates and to validate the pricing currency. |
| `capabilities` | The verify probe | `inventory_read`, `forecast`, `reporting` and `draft_booking`, each `confirmed` or `not_verified`. |
| `status`, `last_error` | The verify probe | `connected` or `error`, and the last failure reason. |

## The connect-and-verify handshake

When an operator connects your platform, DataFlair runs a short read-only probe. It creates nothing.

1. DataFlair calls [`GET /health`](/marketplace/ad-server-api/operations/health) to confirm the credential works, that it reached the right account, and that it can read your account context.
2. If that succeeds, DataFlair calls [`GET /inventory?limit=1`](/marketplace/ad-server-api/operations/inventory) once.

### The capability checklist

DataFlair confirms a capability only by using it. It does not assume. One cheap probe, `GET /inventory?limit=1`, is enough to move `inventory_read` from `not_verified` to `confirmed`. Reporting and draft booking can be confirmed only by real use. A freshly connected account that shows "not verified" next to them is normal until the first real report and the first real draft happen.

`inventory_read` differs from the other three. You cannot turn it off. It is either implemented or it is not, so there is nothing to declare for it in the `capabilities` object of `/health`. That object carries only `forecast`, `reporting` and `draft_booking`. Implementing `GET /inventory` is part of the required contract, like the rest. DataFlair confirms `inventory_read` the first time a real `GET /inventory` call succeeds.

## Failure behavior

Return a clear HTTP status and a JSON `{ code, message }` body (see [Conventions](/marketplace/ad-server-api/conventions#error-model)). DataFlair shows the `message` to the operator on the connection card. The operator fixes the problem and retries in place.

* `401`: bad or missing credential.
* `403`: the credential authenticated but lacks a required scope.
* `5xx` or unreachable: DataFlair reports "could not reach your platform" and the operator retries.
