# Create File

Registers a new file from a publicly accessible URL, optionally tagging it. The file is fetched, checked against the supported formats and the size limit, and stored.
## Authentication
Requires a valid API key in the `X-API-KEY` header.
## Request Body

```json
{
  "url": "https://example.com/docs/product-datasheet.pdf",
  "tags": ["datasheets", "catalog", "summer-2024"]
}
```
### URL Field (Required)
The URL must meet the following requirements:
**Valid URL formats:**
- Must be a valid HTTP or HTTPS URL
- Must be absolute (e.g., `https://example.com/manual.pdf`)
- Relative URLs are NOT supported (e.g., `/docs/manual.pdf`)
- The filename is taken from the URL path and becomes the file's `reference`

**Examples of valid URLs:**

```
https://example.com/product-datasheet.pdf
https://cdn.example.com/docs/2024/manual.docx
http://assets.example.com/exports/catalog_123.csv
```
**Examples of invalid URLs:**

```
/docs/manual.pdf                       (relative URL)
example.com/manual.pdf                 (missing protocol)
ftp://server.com/manual.pdf            (FTP not supported)
https://example.com/installer.exe      (extension not accepted)
https://example.com/datasheet          (no extension to derive the file type from)
```
**URL validation rules:**
- Maximum length: 2048 characters
- The URL must be publicly accessible (no authentication supported)
- The host must resolve to a public address. URLs pointing at loopback, private ranges or the
cloud metadata endpoint are rejected
- The URL is probed with a `HEAD` request; anything other than a 2xx is rejected
- An address that never answers, or that refuses the connection, is rejected the same way — as an
address the caller has to correct, not as a technical error

### Tags Field (Optional)
Optional array of strings to categorize and organize your files.
**Rules:**
- Each tag cannot be empty or contain only whitespace
- Tags are case-sensitive
- No tag may contain a comma. A comma is the separator the set is stored with, so a tag carrying
one would be read back as two; it is rejected rather than accepted and mangled
- There is no explicit limit on the number of tags, but the whole comma-separated list must fit in
64 KB of storage

## Supported File Formats
The file type is taken from the URL's file extension and must be one of:
| Category | Extensions |
|  --- | --- |
| Documents | `pdf`, `doc`, `docx`, `txt`, `rtf`, `odt` |
| Spreadsheets | `xls`, `xlsx`, `csv`, `ods` |
| Presentations | `ppt`, `pptx`, `odp` |
| Archives | `zip`, `rar`, `7z`, `tar`, `gz`, `tgz` |
| Video and audio | `mp4`, `mov`, `webm`, `m4v`, `mpeg`, `mpg`, `avi`, `mp3`, `wav` |
| Images | `jpg`, `jpeg`, `png`, `gif`, `bmp`, `tif`, `tiff`, `psd`, `webp`, `avif`, `heic` |
| Markup and data | `svg`, `html`, `htm`, `xml`, `json` |
| Print production | `ai`, `eps`, `indd`, `idml`, `idms` |
| CAD, BIM and 3D | `dwg`, `dxf`, `step`, `stp`, `iges`, `igs`, `stl`, `sat`, `obj`, `mtl`, `fbx`, `3ds`, `max`, `skp`, `glb`, `gltf`, `usdz`, `dae`, `3dm`, `x3d`, `ifc`, `rfa`, `rvt`, `iam`, `ipt`, `idw` |
| Photometry and product data | `ldt`, `ies`, `uld`, `gll`, `gdtf`, `bc3`, `bom`, `sup` |
| Fonts | `otf`, `ttf`, `woff`, `woff2` |

The extension is matched case-insensitively and decides which format the file is filed as. The
`Content-Type` the URL serves is **not** validated, unlike `POST /images`: several of the accepted
formats have no registered media type and are commonly served as `application/octet-stream`, so a
media-type allow-list would reject valid uploads without excluding anything.
## File Size Limit
- **Maximum file size:** 250 MB (262,144,000 bytes)
- The transfer is cut off as soon as the limit is exceeded, so an oversized file is never stored

## Response
### Success Response (201 Created)
Returns the reference (filename) of the created file, wrapped in the house entity envelope. The
reference is the public, tenant-unique key; the numeric id is internal only and is not exposed:

```json
{
  "value": {
    "reference": "product-datasheet.pdf"
  },
  "@readLink": "https://api2.saleslayer.com/dam/files(product-datasheet.pdf)",
  "@editLink": "https://api2.saleslayer.com/dam/files(product-datasheet.pdf)"
}
```
## Error Responses
### 400 Bad Request
Validation failures are returned in the shared envelope. Service-level messages carry no field
context, so they are grouped under a generic `error` key:

```json
{
  "validationFailures": {
    "error": ["URL is required"]
  }
}
```
The messages you can receive, verbatim:
| Cause | Message |
|  --- | --- |
| Missing or empty URL | `URL is required` |
| URL over 2048 characters | `URL exceeds maximum length of 2048 characters` |
| Not an absolute URL | `URL is not valid` |
| Scheme other than HTTP/HTTPS | `URL must use HTTP or HTTPS protocol` |
| No extension in the URL path | `Could not determine file type from URL. Please ensure the URL contains a filename with an extension.` |
| Unsupported extension | `File extension 'exe' is not allowed. Allowed extensions: 3dm, 3ds, 7z, ai, avi, ...` — the whole accepted set, alphabetically |
| Host is not publicly routable | `URL host 'localhost' is not allowed.` |
| URL not reachable (non-2xx `HEAD`) | `URL is not accessible. HTTP status: 404 Not Found` |
| URL did not answer in time | `URL is not accessible. The address did not respond in time.` |
| Connection refused, DNS or TLS failure | `URL is not accessible. The address 'cdn.example.com' could not be reached.` |
| Empty file | `The uploaded file is empty` |
| Stored copy missing | `The uploaded file could not be found in storage.` |
| File too large | `File size (300.00 MB) exceeds maximum allowed size of 250 MB` |
| Content is a different file type | `The address serves a PNG image, but the file name 'product-datasheet.pdf' announces a 'pdf' file.` |
| Content matches no known file type | `The address does not serve a 'pdf' file: its content matches no known file type.` |
| Empty or whitespace-only tag | `Tags cannot contain empty values` |
| Tag containing a comma | `Tags cannot contain commas` |

### 401 Unauthorized
Missing or invalid API key in the `X-API-KEY` header. Emitted by the API gateway:

```json
{
  "message": "Unauthorized",
  "request_id": "d8aafa5b8f3e400b60bea0123dd33317"
}
```
### 403 Forbidden
The API key does not have write permissions for this operation. Same body shape as the 401.
### 409 Conflict
Two distinct causes, both using the conflict envelope:
**A file with the same filename (`reference`) already exists for this tenant:**

```json
{
  "error": "A file with the filename 'product-datasheet.pdf' already exists"
}
```
**The tenant has reached its file-library quota:**

```json
{
  "error": "File library limit reached. Current: 500, Maximum: 500"
}
```
Deleted files do not count towards the quota. Delete unused files to free
capacity, or contact Sales Layer to raise the limit. The file and image libraries have separate
quotas, so files never consume image capacity or vice versa.
## Complete Example
**Request:**

```http
POST /files HTTP/1.1
Host: api2.saleslayer.com
X-API-KEY: your-api-key-here
Content-Type: application/json
            
{
  "url": "https://cdn.example.com/docs/2024/product-datasheet.pdf",
  "tags": ["datasheets", "catalog"]
}
```
**Success Response:**

```http
HTTP/1.1 201 Created
Content-Type: application/json
Location: https://api2.saleslayer.com/dam/files(product-datasheet.pdf)
            
{
  "value": {
    "reference": "product-datasheet.pdf"
  }
}
```
**Result:**

```json
{
  "value": {
    "reference": "product-datasheet.pdf",
    "status": "Ok",
    "fileType": "pdf",
    "sizeInBytes": 524288,
    "numLinks": 0,
    "tags": ["datasheets", "catalog"],
    "url": "https://cdn.example.com/CMP2009/files/product-datasheet.pdf",
    "createdOn": "2024-04-02T10:30:00",
    "modifiedOn": "2024-04-02T10:30:00"
  }
}
```

Endpoint: POST /files
Version: 2.0.0

## Header parameters:

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

## Request fields (application/json):

  - `url` (string)
    Publicly accessible HTTP or HTTPS URL of the file to import. Required. Must be absolute and end
in a supported extension (pdf, doc, docx, txt, xls, xlsx, csv, rtf, ppt, pptx, zip, rar, tar,
mpeg, mpg, avi, mov, tif, tiff, ai, eps, psd, x3d, sup, ldt, ies, dwg, obj, webp); the file's
`reference` is the filename taken from the URL path. Maximum 2048 characters.

  - `tags` (array)
    Optional tags to associate with the file, e.g. `["datasheets", "catalog", "2024"]`. Tags are
case-sensitive and cannot be empty or whitespace. Avoid commas inside a tag — tags are stored as a
comma-separated string and would be read back split.

## Response 201 fields (application/json):

  - `value` (object)
    The reference of a newly created file. Retrieve the full file with
`GET /files({reference})`. Unlike an image, a file is usable as soon as it is created — nothing
processes it afterwards — so it starts, and stays, in status `Ok`.

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

  - `@readLink` (string)
    Canonical URL of the created file, the same resource the `Location` header names.
Present only when hypermedia enrichment is enabled.

  - `@editLink` (string)
    URL to modify the created file, identical to `@readLink`. Present only when hypermedia
enrichment is enabled.

## 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 fields (application/json):

  - `message` (string)

  - `request_id` (string)

## Response 409 fields (application/json):

  - `error` (string)

## Response 500 fields (application/json):

  - `error` (string)

  - `details` (any)

