# Confirm a sample and get its download link

> POST /v1/sample-downloads. Sent by the confirmation page when the person presses its button, with the token from the emailed link; the token is the credential, so no key or session is needed.

Source: https://emailmovers.com/mydatahub/docs/reference/rest/create-sample-download

`POST /v1/sample-downloads`

Sent by the confirmation page when the person presses its button, with the token from the emailed link; the token is the credential, so no key or session is needed. The first press confirms the address and chooses up to 10 records (verified named emails with an Article 14 notice, none at the person's own domain, at most 2 a company), read afresh against every suppression. Each press until the download gives a new single-use link for 5 minutes; after it, the answer says the sample was already downloaded. An unknown or expired token gets 404.

| Property | Value |
| --- | --- |
| Endpoint | `POST https://mydatahub.emailmovers.com/v1/sample-downloads` |
| Operation id | `createSampleDownload` |
| Cost | Free (0 credits) |
| Access | No account, key or token needed. |
| Tag | Samples |

> **Not yet live.** MyDataHub v2 is built and tested locally and is not yet live. The v2 hosts open at launch, date to confirm. This page describes the contract the API is tested against.

## Request

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `MyDataHub-Version` | header | string | no | The dated API version, pinned per key when left out. Non-breaking changes ship as new dates; the path major changes only for breaking changes, with a 12 month deprecation window. |

### Body

| Member | Type | Required | Description |
| --- | --- | --- | --- |
| `token` | string | yes | The token from the emailed link (the last part of /samples/confirm/{token}). Only a press of the confirmation page's button sends it, so a link scanner that opens the page uses nothing up. |

## Example request

```bash
curl -X POST "https://mydatahub.emailmovers.com/v1/sample-downloads" \
  -H "Content-Type: application/json" \
  --data '{
  "token": "q3V8xN2fK7mR1tY6pL0sD4hJ9wZ5cB8eA2gU7iO3nQ1"
}'
```

## Responses

### 200: The sample's link, or why there is none.

Headers: `RateLimit`, `RateLimit-Policy`.

| Member | Type | Always present | Description |
| --- | --- | --- | --- |
| `status` | enum: `ready`, `empty`, `downloaded` | yes | ready: download_url serves the sample once; empty: no record of the audience can be sent as a sample now, and nothing is supplied; downloaded: the sample was already served, and is never served twice. |
| `records` | integer (0 to 10) | yes | Records in the sample: up to 10, fewer when fewer are left. |
| `download_url` | string or null | yes | A relative link on this host to the CSV, whose first lines are the licence. It works once, for 5 minutes, from the address that asked for it. Null unless ready. |
| `expires_at` | string (date-time) or null | yes | When download_url stops working. Null unless ready. |

#### Example response

```json
{
  "status": "ready",
  "records": 10,
  "download_url": "/files/samples/sdl_Xr4mP8qT2vN6kJ1wL9sF3hD7bG5cZ0yA8eU2iO6nQ4t",
  "expires_at": "2026-10-11T10:20:00Z"
}
```

## Errors

Every error is a problem object with a `code` and a `next_step`. Every response carries the `RateLimit` and `RateLimit-Policy` headers; see [Rate limits](https://emailmovers.com/mydatahub/docs/rate-limits.md).

| Status | Problem codes | When |
| --- | --- | --- |
| 400 | [`invalid-request`](https://emailmovers.com/mydatahub/docs/errors/invalid-request.md), [`idempotency-key-required`](https://emailmovers.com/mydatahub/docs/errors/idempotency-key-required.md), [`unsupported-version`](https://emailmovers.com/mydatahub/docs/errors/unsupported-version.md) | The request could not be read, or an Idempotency-Key is missing. |
| 404 | [`not-found`](https://emailmovers.com/mydatahub/docs/errors/not-found.md) | No such object for this organisation. |
| 422 | [`validation-failed`](https://emailmovers.com/mydatahub/docs/errors/validation-failed.md), [`quote-required`](https://emailmovers.com/mydatahub/docs/errors/quote-required.md), [`dataset-unavailable`](https://emailmovers.com/mydatahub/docs/errors/dataset-unavailable.md) | The request is not valid. errors lists every problem with a JSON pointer and did_you_mean. |
| 429 | [`rate-limited`](https://emailmovers.com/mydatahub/docs/errors/rate-limited.md) | Too many requests. Wait for Retry-After. |
| Any other failure | [`internal-error`](https://emailmovers.com/mydatahub/docs/errors/internal-error.md), [`service-unavailable`](https://emailmovers.com/mydatahub/docs/errors/service-unavailable.md), [`tps-screen-expired`](https://emailmovers.com/mydatahub/docs/errors/tps-screen-expired.md) | Something failed on our side (500 internal-error) or the service is briefly unavailable (503 service-unavailable, with Retry-After). Nothing was charged; retry with the same Idempotency-Key. A count, sample, quote or order with telephone in play is also refused with 503 tps-screen-expired, with no Retry-After, while the dataset version's TPS and CTPS screen is more than 28 days old. |
