# Get loyalty points export download link

Get a temporary download URL for a completed export.

- Endpoint: `GET https://api.returning.ai/v1/loyalty-exports/{exportId}/download`
- Section: Gamification / Loyalty points
- Authentication: `Authorization: Bearer <API_KEY>` (Community API key)
- Permission: `customerSuccess` (Shown in the dashboard as Customer Success.)
- Retries: Safe to repeat while the file remains available; links do not extend file retention.
- Guide: hand-written
- Verified: live, 2026-10-12
- Last updated: 12 Oct 2026
- Web page: https://docs.returning.ai/api-reference/gamification-loyalty-points/get-loyalty-points-export-download-link

## When to use this

- Download a completed CSV or JSON report into your reporting system.
- Replace an expired download link while the file remains available.

**Instead:** Use [Get loyalty points export status](https://docs.returning.ai/api-reference/gamification-loyalty-points/get-loyalty-points-export-status.md) while the job is queued or processing.

## Authentication

- Header: `Authorization: Bearer <API_KEY>`
- Permission: `customerSuccess`

Use a Community API key with `customerSuccess`, shown as Customer Success in the dashboard. Keep the key on your backend and send `Authorization: Bearer <API_KEY>`. The key selects the community; do not send a community ID. Personal API keys are not supported.

All three calls use `https://api.returning.ai` and return `Cache-Control: no-store`. They accept no query parameters. A valid community key with the required permission can read that community's export jobs, including jobs created by another key in the same community.

Successful responses contain `meta`, `message` and `data`. Read job state from `data.status`. An HTTP `200` means the status request succeeded, even when the job is `failed`. Errors put their machine-readable code in `meta.code`; do not branch on `message`.

## Behaviour

Download the returned URL without forwarding your API key:

```bash
curl --fail --output points.csv '<TEMPORARY_DOWNLOAD_URL>'
```

The URL is sensitive: anyone holding it may download the file while it remains valid. Do not put it in logs, support tickets or client-side source. The response contains only `filename`, `url` and `url_expires_at`; no checksum or file size is returned here.

Links are generated with an expiry of at most five minutes, bounded by the file's availability. Files have an API availability window of 24 hours after completion. Request a new link if the old one expires while the file remains available. Repeated link requests do not extend the file's availability.

CSV filenames use the export creation time in Unix milliseconds: `points-<timestamp>.csv`. JSON downloads use `points.json`.

An unfinished, failed or cancelled job returns `409 EXPORT_NOT_READY`. Check status; wait only for queued or processing jobs. An expired file returns `410 EXPORT_EXPIRED`.

## Request

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `exportId` | `string` | Yes | Export ID returned by Create loyalty points export. (24 hex characters) |

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | Yes | Community API key with Customer Success permission. The key selects the community. (Bearer <API_KEY>) |

### Example request

```bash
curl --request GET \
  --url https://api.returning.ai/v1/loyalty-exports/66f000000000000000000701/download \
  --header 'Authorization: Bearer <API_KEY>'
```

## Response

Download the file with a plain HTTPS GET. Check [Create loyalty points export](https://docs.returning.ai/api-reference/gamification-loyalty-points/create-loyalty-points-export.md) for CSV columns, JSON fields and daily-load guidance.

### Verify and store the file

Compare the downloaded byte length with `file_size_bytes` from the completed status. For CSV, parse it with a CSV library and count data records, excluding the header; fields can be quoted, so counting newline characters is not a reliable row count. For JSON, count objects in the array. Compare that count with `total_rows`.

Store the file only after the transfer and parsing checks succeed. Keep customer data private and apply your own retention policy. The API's 24-hour availability is a download window, not a retention policy for files you have saved yourself.

### Two different expiry times

| What expires | Window | Recovery |
| --- | --- | --- |
| A download URL | At most five minutes, shown by `url_expires_at` | Request another link for the same completed export. |
| The export file | 24 hours after completion | Create a deliberately new export. Replaying the original create does not extend availability. |

A file-host HTTP 403 may mean the temporary URL expired or was copied incompletely. Get a fresh link and copy it exactly. If a fresh link also fails, stop retrying it repeatedly and contact support with the export ID and API request ID. Do not send support the API key, signed URL or raw customer file.

The file host's errors are not the API's JSON error envelope. Use the status and download-link endpoints to distinguish an unfinished job, an expired artifact and a temporary download failure.

### Response fields

| Field | Type | Presence | Description |
| --- | --- | --- | --- |
| `meta` | `object` | always | Request result and support reference. |
| `meta.status` | `string` | always | Result of the request. (success) |
| `meta.statusCode` | `integer` | always | HTTP status of the request. |
| `meta.requestId` | `string` | always | Support reference for this request. |
| `message` | `string` | always | Human-readable summary. Do not branch on it. |
| `data` | `object` | always | Temporary download details. |
| `data.filename` | `string` | always | Suggested filename for saving the download. |
| `data.url` | `string` | always | Sensitive temporary HTTPS URL. Download without forwarding the API key. |
| `data.url_expires_at` | `string` | always | UTC link expiry, at most five minutes after generation and bounded by file availability. |

### Example response (200)

```json
{
  "meta": {
    "status": "success",
    "statusCode": 200,
    "requestId": "example-request"
  },
  "message": "Loyalty export download success.",
  "data": {
    "filename": "points-1788397200000.csv",
    "url": "https://download.example.com/temporary-file",
    "url_expires_at": "2026-09-03T01:07:00.000Z"
  }
}
```

## Errors

### Fix the request

| Status | Code | What to do |
| --- | --- | --- |
| 400 | `VALIDATION_ERROR` | Remove unsupported query parameters and correct the request fields. |
| 401 | `AUTHENTICATION_REQUIRED` | Send a valid Community API key in Authorization: Bearer <API_KEY>. |
| 403 | `API_KEY_PERMISSION_DENIED` | Use a Community API key with Customer Success permission. |
| 403 | `COMMUNITY_ACCESS_DENIED` | Use a Community API key, not a personal API key. |
| 400 | - | Invalid request or unsupported query parameters. |
| 401 | - | Missing or invalid API key. |
| 403 | - | A Community API key with the required permission is needed. |
| 410 | - | The export artifact has expired. |

### Fix the data

| Status | Code | What to do |
| --- | --- | --- |
| 404 | `COMMUNITY_NOT_FOUND` | Contact support about the community selected by your API key. |
| 404 | `EXPORT_NOT_FOUND` | Check the export ID and the community selected by your API key. |
| 410 | `EXPORT_EXPIRED` | Create a new export with a new idempotency key if you still need the file. |
| 404 | - | The export was not found. |
| 409 | - | The export is not ready. |

### Retry with backoff

| Status | Code | What to do |
| --- | --- | --- |
| 503 | `EXPORTS_UNAVAILABLE` | Retry with backoff. For create, preserve the original body and idempotency key. |
| 500 | `AUTHENTICATION_FAILED` | Retry with backoff; contact support if authentication checks keep failing. |
| 409 | `EXPORT_NOT_READY` | Read status. Wait only for queued or processing jobs; do not keep polling failed or cancelled jobs. |
| 503 | `EXPORT_ARTIFACT_UNAVAILABLE` | Retry with backoff; contact support if the file remains unavailable. |
| 503 | `EXPORT_STORAGE_UNAVAILABLE` | Retry with backoff; contact support if the file remains unavailable. |
| 503 | `EXPORT_SIGNING_UNAVAILABLE` | Retry with backoff; contact support if no download link becomes available. |
| 503 | - | Exports disabled or unavailable. Retry creation with the same idempotency key. |

**Retries:** Request another link when it expires while the file remains available. Do not forward your API key to the returned URL. For `409 EXPORT_NOT_READY`, read status and wait only for queued or processing jobs. For `410 EXPORT_EXPIRED`, deliberately create a new report. Retry 5xx errors with backoff.

## Next step

- [Create loyalty points export](https://docs.returning.ai/api-reference/gamification-loyalty-points/create-loyalty-points-export.md): `POST /v1/loyalty-exports`. Read the file format and daily-load guidance, or request another report.
- [Get loyalty points export status](https://docs.returning.ai/api-reference/gamification-loyalty-points/get-loyalty-points-export-status.md): `GET /v1/loyalty-exports/{exportId}`. Check state when the file is not ready.
