[Docs](https://linkinseconds.com/docs)Developers

# Upload a file with the API

Turn any file into a public link in three HTTP calls: create the upload, PUT the bytes, complete it. With curl, Node and Python.

An upload is three calls. The file itself never passes through our API servers: you send it straight to storage with a short-lived signed URL, which is why the API handles files as large as your plan allows.

1POST /uploads

Name, type and size → signed URL

2PUT signed URL

Raw file bytes → storage

3POST /uploads/complete

Checked, scanned → public link

## Full example

Set `LIS_API_KEY` to your key (see [Authentication](https://linkinseconds.com/docs/api/authentication)), then:

```
FILE=report.pdf; TYPE=application/pdf
SIZE=$(wc -c < "$FILE" | tr -d ' ')

# 1. Start the upload
START=$(curl -s -X POST https://linkinseconds.com/api/v1/uploads \
  -H "Authorization: Bearer $LIS_API_KEY" -H "Content-Type: application/json" \
  -d "{\"name\":\"$FILE\",\"type\":\"$TYPE\",\"size\":$SIZE}")
URL=$(echo "$START" | jq -r .signedUrl)
UPLOAD_PATH=$(echo "$START" | jq -r .path)

# 2. Send the bytes straight to storage
curl -s -X PUT -H "Content-Type: $TYPE" --data-binary @"$FILE" "$URL"

# 3. Publish
curl -s -X POST https://linkinseconds.com/api/v1/uploads/complete \
  -H "Authorization: Bearer $LIS_API_KEY" -H "Content-Type: application/json" \
  -d "{\"path\":\"$UPLOAD_PATH\",\"name\":\"$FILE\",\"type\":\"$TYPE\"}"
```

## 1. Start the upload

POST`/api/v1/uploads`API key required

Checks your key, plan, the hourly limit and the file name and size, then returns a signed upload URL.

JSON body

`name`stringrequired

File name with its extension, e.g. `report.pdf`. The extension must be an allowed type.

`type`stringrequired

MIME type, e.g. `application/pdf`. Send the same value as `Content-Type` on the PUT.

`size`integerrequired

Exact size in bytes. The signed URL only accepts this many bytes.

`slug`string

Custom link name. Send it again on complete. See [Link settings](https://linkinseconds.com/docs/link-settings).

`idempotencyKey`uuid

Makes retries safe. Reuse the same value on complete. If a lost response is retried, you get the existing link back instead of a duplicate.

200 OK

```
{
  "path": "6f1c…/a1b2c3d4.pdf",
  "signedUrl": "https://…"
}
```

If the `idempotencyKey` already produced a link, the response is `{ "existing": { "slug", "title", "url" } }` and you can skip the next two steps.

## 2. Send the file

PUT`{signedUrl}`No auth

PUT the raw bytes (not form data) with the same `Content-Type` you declared. The URL is valid for 10 minutes and can not be reused for another file. No API key is needed on this call.

## 3. Publish it

POST`/api/v1/uploads/complete`API key required

We read the real size and first bytes from storage, check the file really is what its name says, run the safety scan and create the link. If anything fails, the uploaded bytes are deleted.

JSON body

`path`stringrequired

The path returned by step 1.

`name`stringrequired

Same file name as step 1.

`type`stringrequired

Same MIME type as step 1.

`linkName`string

Title shown on the link page. Defaults to the file name.

`slug`string

Custom link name, same as step 1.

`allowDownload`boolean

Set `false` for a view-only link. Default `true`.

`idempotencyKey`uuid

Same value as step 1.

200 OK

```
{
  "slug": "report-x7",
  "title": "report",
  "url": "https://lisview.com/report-x7"
}
```

### When a file is held for review

If the safety scan flags a file, the response includes `"review": true`. The link exists but is not public until a person clears it. Videos can return `"processing": true` while they are being scanned. Tell your users the link will start working shortly.

Retries

Network blips happen, especially on big files. Always send an `idempotencyKey`: retrying step 1 or step 3 with the same key never creates a second link or uses a second free slot.

## What you can upload

- Any type listed in [Supported file types](https://linkinseconds.com/docs/file-types): PDFs, images, video, audio, documents, HTML, ZIP and more. Executables and scripts are always refused.

- Up to your plan's per-file size and total storage. See [Plans and limits](https://linkinseconds.com/docs/plans-and-limits).

- **Albums and static websites** are created from the website, not the API, for now.

[PreviousAuthentication](https://linkinseconds.com/docs/api/authentication)[Next List links](https://linkinseconds.com/docs/api/links)

Last updated 4 October 2026. Something unclear or missing? [Tell us](https://linkinseconds.com/contact).

Source: https://linkinseconds.com/docs/api/uploads
