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

# Download a purchased file

> Open the file for a single-title download link. The token is the credential, so no login is needed.

## Request

```http theme={null}
GET /downloads/9f2c1b7e4a6d8035c1e2f4a7b9d0c3e5a8b1d4f6c7e90123
```

No `Authorization` or `x-shop-id` header is needed: the token identifies both the buyer's access and the store.

## Path parameters

| Parameter | Type | Description |
| - | - | - |
| `token` | string | The download token (32 to 128 hex characters) from the buyer's purchase email or a library row's `downloadUrl`. |

<Note>
  This is the link in the buyer's email for a title bought on its own (bought outright). The all-access pass uses [one token for the whole pass](/api-reference/endpoint/downloads/download-all-access) instead.
</Note>

## Responses

| Status | `code` | Meaning |
| - | - | - |
| `200` | | The file, as a PDF stamped for the buyer (see below). |
| `302` | | Any other format, or a PDF over 30 MB: a redirect to a short-lived link (5 minutes) to the file. Follow it immediately. |
| `403` | `read_only` | The access is a 30-day pass or the all-access pass. Those are read online and cannot be downloaded. The body carries `libraryUrl`. |
| `403` | `revoked` | The seller removed this access. |
| `403` | `store_unavailable` | The store is switched off or suspended. |
| `404` | `not_found` | The token is not valid, or the title is no longer available. |
| `404` | `file_unavailable` | The file is missing from storage. |
| `410` | `expired` | The pass has ended. The body carries `renewUrl`, the store's `/library`. |
| `429` | `download_limit` | Five downloads of this title today. `Retry-After` counts the seconds to the next UTC midnight. |
| `502` | `file_service_error` | The file service could not prepare the file. The attempt is not counted against the daily limit. |

Errors are JSON unless the request prefers `text/html` (a browser opening an emailed link), in which case a small page in the store's colour explains what happened and links back to the store. Error and file responses are never cached.

```json theme={null}
{
    "status": 429,
    "success": false,
    "message": "You have reached today's download limit for this title. Please try again tomorrow.",
    "code": "download_limit",
    "retryAfter": 41200,
    "data": {}
}
```

## Limits and protection

* **5 downloads per day**, per title and per access, counted by UTC day.
* **PDFs up to 30 MB are stamped** on every page with a footer reading `Licensed to <email> | <store name> | <short id>`, so a leaked copy can be traced. Larger PDFs and other formats are delivered unstamped.
* A `HEAD` request answers `204` and does not use a download, so mail scanners and link previews are safe.
* The link is the credential: it needs no login, and Salesive keeps it out of its own logs. Do not share it.


## OpenAPI

````yaml api-reference/openapi.json GET /downloads/{token}
openapi: 3.1.0
info:
  title: Salesive Store API
  description: >-
    REST interface for querying products, categories, and merchandising banners
    exposed by Salesive storefronts.
  version: 1.0.0
servers:
  - description: Production
    url: https://store.salesive.com/api/v1
security:
  - BearerAuth: []
    ShopIdHeader: []
paths:
  /downloads/{token}:
    get:
      summary: Download a purchased file
      description: >-
        Opens the file for a single-title access link. The token in the path is
        the credential, so the link works from an email without a login. Each
        title can be downloaded five times per UTC day per access. `HEAD`
        requests answer `204` and never use up a download, so mail scanners are
        safe. Errors come back as JSON by default, and as a small branded HTML
        page when the request prefers `text/html` (a browser).
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
            pattern: ^[0-9a-f]{32,128}$
          description: >-
            The download token from the buyer's email or the `downloadUrl` of a
            library row.
      responses:
        '200':
          description: >-
            A PDF up to 30 MB, stamped on every page with the buyer's email, the
            store name and a short access id. Sent as an attachment with
            `Cache-Control: no-store`.
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '302':
          description: >-
            Any other format, or a PDF over 30 MB: a redirect to a short-lived
            (5 minutes) link to the file. Follow it right away.
        '403':
          description: >-
            The store is unavailable (`store_unavailable`) or the seller revoked
            this access (`revoked`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                  code:
                    type: string
                    description: Machine-readable reason.
                example:
                  status: 403
                  success: false
                  message: >-
                    Access to this title was removed by the store. Contact the
                    store if you think this is a mistake.
                  code: revoked
                  data: {}
        '404':
          description: >-
            The token is not valid or the title is no longer available
            (`not_found`), or the file is missing (`file_unavailable`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                  code:
                    type: string
                    description: Machine-readable reason.
                example:
                  status: 404
                  success: false
                  message: >-
                    This download link is not valid. Check that you copied the
                    whole link, or open your library from the store.
                  code: not_found
                  data: {}
        '410':
          description: >-
            A pass that has ended (`expired`). `renewUrl` points at the store's
            library.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                  code:
                    type: string
                    description: Machine-readable reason.
                example:
                  status: 410
                  success: false
                  message: >-
                    Your access to this title has ended. Renew it from the store
                    to download again.
                  code: expired
                  data: {}
        '429':
          description: >-
            Five downloads of this title today (`download_limit`). The
            `Retry-After` header counts the seconds to the next UTC midnight.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                  code:
                    type: string
                    description: Machine-readable reason.
                example:
                  status: 429
                  success: false
                  message: >-
                    You have reached today's download limit for this title.
                    Please try again tomorrow.
                  code: download_limit
                  data: {}
        '502':
          description: >-
            The file service could not prepare the file (`file_service_error`).
            The attempt does not count against the daily limit.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                  code:
                    type: string
                    description: Machine-readable reason.
                example:
                  status: 502
                  success: false
                  message: >-
                    We could not prepare your file. Please try again in a
                    moment.
                  code: file_service_error
                  data: {}
      security: []
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT issued by the Salesive Store API for authenticated shoppers.
    ShopIdHeader:
      type: apiKey
      in: header
      name: x-shop-id
      description: >-
        Optional storefront identifier sent as a header to scope responses to a
        specific shop. Try It requests remember this value once provided.

````

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