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

# Authentication

> API keys, the Bearer header, key types and scopes, and which broker a request acts as.

Every request carries an API key in the `Authorization` header:

```http theme={null}
Authorization: Bearer bl_live_...
```

There's no other credential, no OAuth flow and no request signing. Keep keys on your server; never put one in a browser, a mobile app or a URL.

## Keys and modes

A key's prefix tells you its mode:

| Prefix | Mode | Status |
| - | - | - |
| `bl_live_` | Live: real pricing, real quotes, real emails to your broker | Available by invitation |
| `bl_test_` | Test: real pricing, isolated data, no emails to anyone | Available once Bridgeline enables test mode for your agency. See [test and live mode](/concepts/test-and-live-mode) |

The rest of the key is 43 random characters and a 6-character checksum, so secret scanners (GitHub's included) can recognize a leaked key. We store only a SHA-256 hash: a lost key can't be recovered, so revoke it and create a new one.

## Getting a key

1. Bridgeline turns on API access for your agency. During the beta this is by invitation; ask your Bridgeline contact. Live keys and test keys are enabled separately: ask your Bridgeline contact to enable test mode if you want test keys.
2. An agency admin opens **API Keys** in the Bridgeline portal and creates a key: its mode (live or test), name, type, default broker, scopes and an optional expiry date.
3. The full key is shown once. Copy it into your secret manager.

The portal shows each key's last-used time. An integration can hold two active keys at once, so you can rotate without downtime: create the new key, deploy it, then revoke the old one.

## Key types

Every request acts as one of your agency's active brokers, so every quote has a named owner in Bridgeline, just as it does in the portal.

| | Agency key | Broker key |
| - | - | - |
| Acts as | Its default broker, or any active broker you name in `broker_email` | Only its default broker |
| Can read | Every quote in your agency | Only that broker's quotes |
| Typical use | An AMS or rater used by the whole agency | A tool one producer runs |

### Acting as a broker

Write requests that create something take an optional `broker_email` in the JSON body. Today that's `POST /v1/quotes`:

```json theme={null}
{
  "broker_email": "maria@lonestarrisk.example",
  "insured": { "...": "..." },
  "policies": [ "..." ]
}
```

* **Agency key:** any active broker at your agency. Leave it out and the request acts as the key's default broker. Set it from the logged-in user in your system, so each quote lands with the right producer.
* **Broker key:** leave it out, or send the key's own broker. Naming anyone else returns [`403 ACTING_BROKER_NOT_ALLOWED`](/errors/ACTING_BROKER_NOT_ALLOWED).
* An email that isn't an active broker at your agency returns [`403 BROKER_NOT_ACTIVE`](/errors/BROKER_NOT_ACTIVE). We give the same answer whether the person is inactive or works somewhere else.
* Reads, and requests with no body, always act as the key's default broker. There is no header for choosing a broker.

If the key's default broker is deactivated, requests that rely on the default fail with [`403 DEFAULT_BROKER_INACTIVE`](/errors/DEFAULT_BROKER_INACTIVE). We never quietly move a deal to someone else.

## Scopes

Give each key only the scopes it needs. A key without the scope an endpoint requires gets [`403 MISSING_SCOPE`](/errors/MISSING_SCOPE).

| Scope | Allows | Used by |
| - | - | - |
| `quotes:write` | Create quotes and replace their links; in test mode, act out your client's response | `POST /v1/quotes`, `POST /v1/quotes/{id}/hosted-link`, `POST /v1/test_helpers/quotes/{id}/interest` |
| `quotes:read` | Read quotes | `GET /v1/quotes/{id}` |
| (none) | Check the key, read reference data | `GET /v1/whoami`, `GET /v1/coverage-types` |

The portal also offers `applications:read`, `applications:write`, `agreements:write`, `loans:read` and `webhooks:manage`. They're reserved for endpoints on the [roadmap](/roadmap) and do nothing yet.

## When a request is refused

| Status | Code | Meaning |
| - | - | - |
| 401 | [`INVALID_API_KEY`](/errors/INVALID_API_KEY) | The key is missing, malformed or not recognized |
| 401 | [`KEY_REVOKED`](/errors/KEY_REVOKED), [`KEY_EXPIRED`](/errors/KEY_EXPIRED) | Create a new key |
| 403 | [`API_ACCESS_NOT_ENABLED`](/errors/API_ACCESS_NOT_ENABLED) | API access is off for your agency (a live key) |
| 403 | [`TEST_MODE_NOT_ENABLED`](/errors/TEST_MODE_NOT_ENABLED) | Test mode is off for your agency (a test key) |
| 403 | [`TEST_MODE_ONLY`](/errors/TEST_MODE_ONLY) | A live key called a test helper |
| 403 | [`MISSING_SCOPE`](/errors/MISSING_SCOPE) | The key lacks a scope this endpoint needs |

Turning off your agency's API access, or revoking a key, stops new API calls straight away. Links to interactive quotes you've already sent keep working; see [links outlive API access](/guides/hosted-quote-page#links-outlive-api-access).


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