# COG downloads

> Whole-file downloads of Darly-hosted source COGs on paid plans — how /dl links work and how they're metered.

Some collections' source files are hosted on Darly's own storage (currently
the Mexico lidar COGs — agency-hosted collections like 3DEP and HRDEM have
direct public URLs instead; see [coverage](/docs/coverage)). On plans with
downloads enabled (Pro and up), you can download these files whole through
`/dl` links.

## Getting a download link

Fetch the **single-item** endpoint — Darly-hosted assets are rewritten to
`/dl` links:

```bash cURL
curl "https://api.darly.io/collections/mex-inegi-lidar-5m/items/{item_id}" \
  -H "X-API-Key: $DARLY_API_KEY"
```

```json Response (asset excerpt)
{
  "assets": {
    "dtm": {
      "href": "https://api.darly.io/dl/mex-inegi-lidar-5m/{item_id}/dtm",
      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
      "roles": ["data"]
    }
  }
}
```

Search and item-list responses omit Darly-hosted assets — always drill into
the item. The `/dl` link itself is stable and never expires.

## Downloading

`GET /dl/{collection}/{item}/{asset}` authenticates you, charges the file's
size to your monthly data-out quota, and answers `302` with a short-lived
signed URL. Any HTTP client that follows redirects just works:

```bash cURL
curl -L -o tile.tif \
  "https://api.darly.io/dl/mex-inegi-lidar-5m/{item_id}/dtm" \
  -H "X-API-Key: $DARLY_API_KEY"
```

```python Python
import os
import requests

resp = requests.get(
    "https://api.darly.io/dl/mex-inegi-lidar-5m/{item_id}/dtm",
    headers={"X-API-Key": os.environ["DARLY_API_KEY"]},
    allow_redirects=True,
)
resp.raise_for_status()
with open("tile.tif", "wb") as f:
    f.write(resp.content)
```

```javascript JavaScript
// fetch follows redirects by default
const resp = await fetch(
  "https://api.darly.io/dl/mex-inegi-lidar-5m/{item_id}/dtm",
  { headers: { "X-API-Key": process.env.DARLY_API_KEY } },
)
const buf = Buffer.from(await resp.arrayBuffer())
```

## Metering rules

- **Charged at full file size, once per download** — against the same
  monthly data-out quota as [raster extracts](/docs/raster).
- The signed URL in the redirect lives **5 minutes** — start the transfer
  promptly; re-hit the `/dl` link for a fresh one.
- **15-minute grace window**: repeat requests for the same asset within 15
  minutes redirect again without a second charge. This covers multi-open
  readers (GDAL/QGIS open files more than once) and HEAD-then-GET clients.
  After the window, a new request is a new charge.
- `HEAD` charges like `GET` (its redirect already exposes a live signed URL).
- Partial reads still pay the full file: `/dl` is for whole files. If you
  want a window, a mosaic, or a different projection, the
  [raster endpoint](/docs/raster) meters actual bytes instead.

## Errors

| Case | Response |
|---|---|
| No authentication | `401` `{"detail": "Authentication is required to download assets"}` |
| Plan without downloads (Free) | `403` `{"detail": "The current plan does not include downloads"}` |
| Monthly data-out quota would be exceeded | `429` `{"detail": "Monthly data-out quota exceeded"}` |
| Unknown collection/item/asset, or a non-Darly-hosted asset | `404` `{"detail": "Not found"}` |
