# Authentication

> API keys, the three ways to send them, anonymous access, and how quotas attach to your account.

## What needs a key

| Surface | Anonymous | With API key |
|---|---|---|
| STAC catalog (`/collections`, `/search`, …) | ✓ 30 req/min per IP | Higher per-plan limits |
| Elevation API (`/v1/elevation/*`) | ✗ 401 | ✓ |
| COG downloads (`/dl/...`) | ✗ 401 | Paid plans only |
| `/v1/health` | ✓ | ✓ |

Keys are free: [sign up](/auth/sign-in), then create one under
[Dashboard → API keys](/dashboard/keys). The full key is displayed once at
creation.

## Sending the key

Two equivalent forms; both are HTTP headers:

```bash X-API-Key header
curl "https://api.darly.io/v1/elevation/point?lat=45.51&lon=-73.56" \
  -H "X-API-Key: $DARLY_API_KEY"
```

```bash Bearer token
curl "https://api.darly.io/v1/elevation/point?lat=45.51&lon=-73.56" \
  -H "Authorization: Bearer $DARLY_API_KEY"
```

Keys are **not** accepted in the URL. A request with `?api_key=…` is rejected
with `401` rather than served anonymously: URLs are recorded by proxies,
access logs, browser history, and `Referer` headers, so a key in a URL leaks
at every hop.

For tools that take only a URL, most still let you attach headers. GDAL-based
software (QGIS, rasterio, `/vsicurl`) reads them from an environment variable:

```bash GDAL / rasterio / QGIS
export GDAL_HTTP_HEADERS="X-API-Key: $DARLY_API_KEY"
gdalinfo /vsicurl/https://api.darly.io/dl/usa-usgs-3dep-1m-seamless/<item>/dtm
```

## Keys, users, and quotas

- **Quotas are per account, not per key.** All keys you create draw from the
  same monthly budgets and per-minute limits. Create as many keys as you want
  to separate environments or teammates' tools — revoking one never affects
  the others.
- Revoke keys anytime in [Dashboard → API keys](/dashboard/keys); revocation
  is immediate.
- Your plan's limits are listed in [rate limits & quotas](/docs/limits).

## Auth errors

| Case | Response |
|---|---|
| Elevation call without authentication | `401` `{"detail": "Authentication is required for the elevation API"}` |
| Download without authentication | `401` `{"detail": "Authentication is required to download assets"}` |
| Invalid or revoked key | Treated as anonymous: STAC keeps working at the anonymous limit; elevation calls get the `401`s above |
| Plan doesn't include the endpoint | `403` `{"detail": "The current plan does not include this endpoint"}` |
| Plan doesn't include downloads | `403` `{"detail": "The current plan does not include downloads"}` |

A silent fallback to anonymous access on a bad key can be surprising: if STAC
calls work but elevation calls return `401`, check the key value first.
