# Filter Files

Returns a paginated collection of the tenant's non-image files (documents, spreadsheets, archives, …),
filtered and sorted using OData query options (`$filter`, `$orderby`, `$top`, `$skip`).
## Authentication
Requires a valid API key in the `X-API-KEY` header.
## Response (200 OK)
The page is wrapped in the house collection envelope — the files are under `value`, never at the
top level:

```json
{
  "value": [
    {
      "reference": "product-datasheet.pdf",
      "numLinks": 3,
      "status": "Ok",
      "modifiedOn": "2024-04-05T08:44:33Z",
      "fileType": "pdf",
      "createdOn": "2024-04-05T08:44:33Z",
      "tags": ["datasheets", "catalog"],
      "url": "https://cdn.example.com/product-datasheet.pdf",
      "sizeInBytes": 102400
    }
  ],
  "@count": 137,
  "@readLink": "https://api2.saleslayer.com/dam/files?$top=50",
  "@nextLink": "https://api2.saleslayer.com/dam/files?$top=50&$skip=50"
}
```
Notes on the payload:
- `status` tells you whether the file is usable yet — see the status values below.
- `url` and `sizeInBytes` come from the stored metadata and are empty / `0` until processing has
recorded them.
- `tags` is stored as a comma-separated string, so a tag that itself contains a comma comes back
split into several tags.
- `@count` is the total number of matches, ignoring `$top`/`$skip`.
- `@readLink` is the canonical URL of this collection — this request, echoed back.
- `@nextLink` is the URL of the next page and is omitted on the last page.

The `@`-prefixed hypermedia links (`@readLink`, `@nextLink`) are only emitted when hypermedia
enrichment is configured for the deployment; `@count` is always present. Where the links are
absent, page forward by incrementing `$skip` yourself until fewer than `$top` items come back.
## Supported fields
Only these fields can be used in `$filter` and `$orderby`:
`reference`, `numLinks`, `status`, `modifiedOn`, `fileType`, `createdOn`
Field names are case-insensitive. Every other field — including `tags`, `url` and
`sizeInBytes` — is **not** queryable: naming one in `$filter` or `$orderby` returns 400.
`$orderby` honours only the first sort expression.
`$select` and `$expand` are not supported and are ignored.
## Supported operators and functions
- Comparison: `eq`, `ne`, `gt`, `ge`, `lt`, `le`
- Logical: `and`, `or`, `not`
- Sets: `in`
- Functions: `contains`, `startswith`, `endswith`

## Dates
`createdOn` and `modifiedOn` are returned in UTC, as ISO 8601 with a `Z` suffix
(e.g. `2024-04-05T08:44:33Z`). Date values in `$filter` are compared as UTC instants: send them
in ISO 8601 with a `Z` suffix, e.g. `$filter=modifiedOn gt 2024-04-05T08:44:33Z`.
## Status field values
- `Vd` - Void (not yet started processing)
- `Up` - Updating (being uploaded/updated)
- `Ok` - Processed correctly (ready to use)
- `Re` - Reprocessing
- `Er` - Error (processing failed)
- `Dv` - Deleted/void

Results are not filtered by status, so files in any of these states can be returned. Filter on
`status` explicitly if you only want usable files.
## Examples

```
GET /files?$filter=fileType eq 'pdf'
GET /files?$filter=status eq 'Ok'
GET /files?$filter=fileType eq 'csv' and status eq 'Ok'
GET /files?$filter=status in ('Ok', 'Re')
GET /files?$filter=contains(reference, 'datasheet')
GET /files?$filter=startswith(reference, 'product-') and numLinks gt 0
GET /files?$orderby=createdOn desc
GET /files?$filter=fileType ne 'txt'&$orderby=numLinks desc&$skip=0&$top=50
```
## Error Responses
- **400 Bad Request**: Invalid `$filter` syntax, a field that is not queryable in `$filter` or
`$orderby`, a negative `$skip`, or a `$top` that is not between 1 and 100
- **401 Unauthorized**: Missing or invalid API key. Returned by the API gateway as
`{ "message": "Unauthorized", "request_id": "d8aafa5b8f3e400b60bea0123dd33317" }`
- **403 Forbidden**: The API key does not have read permissions for this operation. Same body
shape as the 401
- **500 Internal Server Error**: Technical error (e.g. database unavailable)

A 400 uses the shared validation envelope, keyed by the offending parameter:

```json
{
  "validationFailures": {
    "$orderby": [
      {
        "PropertyName": "$orderby",
        "ErrorMessage": "Ordering by 'tags' is not supported. Supported fields: reference, numlinks, status, modifiedon, filetype, createdon (Parameter 'propertyName')",
        "AttemptedValue": null
      }
    ]
  }
}
```

Endpoint: GET /files
Version: 2.0.0

## Description:

  - `Authentication` ()
    Requires a valid API key in the X-API-KEY header.

  - `Response (200 OK)` ()
    The page is wrapped in the house collection envelope — the files are under value, never at thetop level: {
  "value": [
    {
      "reference": "product-datasheet.pdf",
      "numLinks": 3,
      "status": "Ok",
      "modifiedOn": "2024-04-05T08:44:33Z",
      "fileType": "pdf",
      "createdOn": "2024-04-05T08:44:33Z",
      "tags": ["datasheets", "catalog"],
      "url": "https://cdn.example.com/product-datasheet.pdf",
      "sizeInBytes": 102400
    }
  ],
  "@count": 137,
  "@readLink": "https://api2.saleslayer.com/dam/files?$top=50",
  "@nextLink": "https://api2.saleslayer.com/dam/files?$top=50&$skip=50"
}
{
  "value": [
    {
      "reference": "product-datasheet.pdf",
      "numLinks": 3,
      "status": "Ok",
      "modifiedOn": "2024-04-05T08:44:33Z",
      "fileType": "pdf",
      "createdOn": "2024-04-05T08:44:33Z",
      "tags": ["datasheets", "catalog"],
      "url": "https://cdn.example.com/product-datasheet.pdf",
      "sizeInBytes": 102400
    }
  ],
  "@count": 137,
  "@readLink": "https://api2.saleslayer.com/dam/files?$top=50",
  "@nextLink": "https://api2.saleslayer.com/dam/files?$top=50&$skip=50"
} Notes on the payload: status tells you whether the file is usable yet — see the status values below.url and sizeInBytes come from the stored metadata and are empty / 0 until processing hasrecorded them.tags is stored as a comma-separated string, so a tag that itself contains a comma comes backsplit into several tags.@count is the total number of matches, ignoring $top/$skip.@readLink is the canonical URL of this collection — this request, echoed back.@nextLink is the URL of the next page and is omitted on the last page. The @-prefixed hypermedia links (@readLink, @nextLink) are only emitted when hypermediaenrichment is configured for the deployment; @count is always present. Where the links areabsent, page forward by incrementing $skip yourself until fewer than $top items come back.

  - `Supported fields` ()
    Only these fields can be used in $filter and $orderby: reference, numLinks, status, modifiedOn, fileType, createdOn Field names are case-insensitive. Every other field — including tags, url andsizeInBytes — is not queryable: naming one in $filter or $orderby returns 400.$orderby honours only the first sort expression. $select and $expand are not supported and are ignored.

  - `Supported operators and functions` ()
    Comparison: eq, ne, gt, ge, lt, leLogical: and, or, notSets: inFunctions: contains, startswith, endswith

  - `Dates` ()
    createdOn and modifiedOn are returned in UTC, as ISO 8601 with a Z suffix(e.g. 2024-04-05T08:44:33Z). Date values in $filter are compared as UTC instants: send themin ISO 8601 with a Z suffix, e.g. $filter=modifiedOn gt 2024-04-05T08:44:33Z.

  - `Status field values` ()
    Vd - Void (not yet started processing)Up - Updating (being uploaded/updated)Ok - Processed correctly (ready to use)Re - ReprocessingEr - Error (processing failed)Dv - Deleted/void Results are not filtered by status, so files in any of these states can be returned. Filter onstatus explicitly if you only want usable files.

  - `Examples` ()
    GET /files?$filter=fileType eq 'pdf'
GET /files?$filter=status eq 'Ok'
GET /files?$filter=fileType eq 'csv' and status eq 'Ok'
GET /files?$filter=status in ('Ok', 'Re')
GET /files?$filter=contains(reference, 'datasheet')
GET /files?$filter=startswith(reference, 'product-') and numLinks gt 0
GET /files?$orderby=createdOn desc
GET /files?$filter=fileType ne 'txt'&$orderby=numLinks desc&$skip=0&$top=50
GET /files?$filter=fileType eq 'pdf'
GET /files?$filter=status eq 'Ok'
GET /files?$filter=fileType eq 'csv' and status eq 'Ok'
GET /files?$filter=status in ('Ok', 'Re')
GET /files?$filter=contains(reference, 'datasheet')
GET /files?$filter=startswith(reference, 'product-') and numLinks gt 0
GET /files?$orderby=createdOn desc
GET /files?$filter=fileType ne 'txt'&$orderby=numLinks desc&$skip=0&$top=50

  - `Error Responses` ()
    400 Bad Request: Invalid $filter syntax, a field that is not queryable in $filter or$orderby, a negative $skip, or a $top that is not between 1 and 100401 Unauthorized: Missing or invalid API key. Returned by the API gateway as{ "message": "Unauthorized", "request_id": "d8aafa5b8f3e400b60bea0123dd33317" }403 Forbidden: The API key does not have read permissions for this operation. Same bodyshape as the 401500 Internal Server Error: Technical error (e.g. database unavailable) A 400 uses the shared validation envelope, keyed by the offending parameter: {
  "validationFailures": {
    "$orderby": [
      {
        "PropertyName": "$orderby",
        "ErrorMessage": "Ordering by 'tags' is not supported. Supported fields: reference, numlinks, status, modifiedon, filetype, createdon (Parameter 'propertyName')",
        "AttemptedValue": null
      }
    ]
  }
}
{
  "validationFailures": {
    "$orderby": [
      {
        "PropertyName": "$orderby",
        "ErrorMessage": "Ordering by 'tags' is not supported. Supported fields: reference, numlinks, status, modifiedon, filetype, createdon (Parameter 'propertyName')",
        "AttemptedValue": null
      }
    ]
  }
}

## Query parameters:

  - `$filter` (string)
    OData $filter expression — see the supported fields, operators and functions below

  - `$orderby` (string)
    OData $orderby expression — only the fields listed below are supported

  - `$top` (integer)
    Maximum number of records to return (default: 100, max: 100)

  - `$skip` (integer)
    Number of records to skip for pagination (default: 0)

## Header parameters:

  - `X-API-KEY` (string, required)
    Tenant's API key (required)

## Response 200:

  - `200` (unknown)
    OK

## Response 200 fields (application/json):

  - `value` (array)
    The files in this page, at most `$top` (default and maximum 100).

  - `value.reference` (string)
    The file's filename, unique per tenant. This is the public key used to address the file and the
value entities use to reference it.

  - `value.numLinks` (integer)
    Number of entities (products, variants, categories, …) currently using this file.

  - `value.status` (string)
    Processing status: `Vd` (void), `Up` (uploading/updating), `Ok` (ready to use),
`Re` (reprocessing), `Er` (processing failed) or `Dv` (deleted). Only `Ok`
guarantees the stored file is usable.

  - `value.modifiedOn` (string)
    When the file was last modified.

  - `value.fileType` (string)
    File extension of the file, without the dot (e.g. `pdf`, `csv`). Derived from the
filename, not from the served Content-Type.

  - `value.createdOn` (string)
    When the file was created. Null for files predating creation-date tracking.

  - `value.tags` (array)
    Tags assigned to the file. Stored as a comma-separated string, so a tag containing a comma is
read back as several tags. Not usable in `$filter` or `$orderby`.

  - `value.url` (string)
    URL of the stored file. Empty until processing has run.

  - `value.sizeInBytes` (integer)
    Size of the file in bytes; `0` until processing has recorded it. Not usable in
`$filter` or `$orderby`.

  - `@count` (integer)
    Total number of files matching the filter, ignoring `$top`/`$skip`.

  - `@readLink` (string)
    Canonical URL of this collection — this request, echoed back. Present only when hypermedia
enrichment is enabled.

  - `@nextLink` (string)
    URL of the next page, omitted on the last page. Present only when hypermedia enrichment is
enabled; otherwise page forward by incrementing `$skip` yourself.

## Response 400:

  - `400` (unknown)
    Bad Request

## Response 400 fields (application/json):

  - `validationFailures` (object)

## Response 401:

  - `401` (unknown)
    Unauthorized

## Response 401 fields (application/json):

  - `message` (string)
    Error description, e.g. `Unauthorized`.

  - `request_id` (string)
    Gateway request identifier, to quote when contacting support.

## Response 403:

  - `403` (unknown)
    Forbidden

## Response 403 fields (application/json):

  - `message` (string)

  - `request_id` (string)

## Response 500:

  - `500` (unknown)
    Internal Server Error

## Response 500 fields (application/json):

  - `error` (string)

  - `details` (any)

