# Filecast upload API v1

Read the public HTML documentation at https://fileca.st/docs.

Base URL: https://fileca.st/api/v1

Sign in and open [Settings](https://fileca.st/settings). Each account receives one
API token automatically, with no expiration. Use **Show** or **Copy token** to
retrieve it. **Regenerate** creates a replacement and immediately invalidates
the previous token; update any scripts that use it. Tokens are authenticated
using SHA-256 hashes and stored encrypted for retrieval by the signed-in owner.
The fixed `uploads:own` scope only grants access to your own uploads.
It cannot read host credentials, manage tokens or access administration.
Do not put tokens in URLs, frontend code or source control.

Send `Authorization: Bearer fc_...` on every API request. Cookies do not
authenticate v1. JSON requests use `Content-Type: application/json`.
API requests are limited to 60/minute per client IP; respect HTTP 429 and
Retry-After. Byte transfers use a separate, session-specific bearer token.

## Quick start

Download the standard-library Python 3 client from:
https://fileca.st/filecast-upload.py

```sh
read -rs FILECAST_TOKEN
export FILECAST_TOKEN
python3 filecast-upload.py ./example.zip --hosts vikingfile,gofile
# If interrupted, use the upload ID printed by the first command:
python3 filecast-upload.py ./example.zip --hosts vikingfile,gofile --resume UPLOAD_ID
unset FILECAST_TOKEN
```

The client validates chunk hashes before skipping received parts, uploads only
missing parts, completes the file and queues transfers. It prints the stable
Filecast share URL. Remote host transfers run asynchronously; check their status
through the API or share page. Configure required host accounts in the web UI.

## Endpoints

| Method | Path | Purpose |
|---|---|---|
| GET | /hosts | Host IDs, enabled flags, credential requirements and limits |
| POST | /uploads | Create a session with `{"name":"example.zip","size":12345}` |
| GET | /uploads/{id} | File metadata, state, expiry, checksum, shareUrl and jobs |
| GET | /uploads/{id}/parts | Resume: ordered receipts and refreshed upload capability |
| POST | /uploads/{id}/complete | Verify receipts with `{"parts":[{"partNumber":1,"etag":"..."}]}` |
| POST | /uploads/{id}/transfers | Queue one host using `{"host":"vikingfile"}` |
| DELETE | /uploads/{id} | Request deletion of temporary bytes after active jobs finish |

Create and resume responses contain `id`, `chunkSize`, `expiresAt` (Unix
milliseconds), `uploadUrl`, and `token`. The status endpoint uses ISO timestamps.
For each 1-based part, PUT its exact bytes to `uploadUrl?part=N`, with
`Content-Type: application/octet-stream` and `Authorization: Bearer <session token>`.
Use the returned uploadUrl verbatim: it may point to upload.fileca.st.
Never send the long-lived API token to the upload endpoint.

Each PUT returns `{partNumber, etag}`. The etag is the SHA-256 of that chunk.
Send all receipts, sorted by part number, to complete. Every chunk is exactly
8 MiB except the last. Maximum file size is **1 GiB (1,073,741,824 bytes)**.
Sessions expire **24 hours after creation**; resuming does not extend expiry.
Before resuming, verify the local filename, size and chunk hashes against the
server's record. Completed files include a full-file SHA-256 checksum.

Completion is idempotent. Retrying a transfer request returns an existing active
or successful job for that upload/host; a failed job can be retried while the
staged file remains available. Serialize transfer requests for the same host.
If session creation times out, its response may have been lost: creation is not
idempotent, and an unused session will expire automatically.

```sh
curl https://fileca.st/api/v1/hosts \
  -H "Authorization: Bearer $FILECAST_TOKEN"

curl https://fileca.st/api/v1/uploads \
  -H "Authorization: Bearer $FILECAST_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"name":"example.zip","size":12345}'
```

Errors use `{"error":"message"}` with HTTP 400 (invalid input), 401 (token),
404 (missing/not owned), 409 (state/paused host), 410 (expired/cancelled session),
429 (rate limit) or 503 (temporary capacity). Check HTTP status before using JSON.
Keep a session ID on failure; do not cancel it if you intend to resume.

Token regeneration immediately blocks subsequent v1 API calls using the old token. A previously
issued upload capability can still send bytes to that existing session until
its 24-hour expiry, but cannot complete or queue transfers through a revoked
API token. Cancel the session to stop accepting further parts. Already queued
host transfers finish independently. DELETE does not delete remote host files.

The web uploader retries individual chunks but does not resume after reloading
the page. The API/client supports interrupted client-to-Filecast transfers;
resuming an interrupted Filecast-to-host transfer is not supported universally.

## Reusing identical Buzzheavier files

For authenticated Buzzheavier transfers, Filecast checks earlier successful links owned by your account with the same filename and size. It reuses a link only when fresh host metadata also confirms the exact SHA-256 and file identity. No file bytes are sent to Buzzheavier in that case. The job in `GET /uploads/{id}` includes `reused: true`; other jobs report false. An unverified or different file is never silently substituted.

## Technical file metadata

`GET /api/v1/uploads/{id}` includes `metadataStatus`, `metadataCheckedAt` and
`metadata`. Extraction starts asynchronously after completion, independently of
file host transfers. Status is `pending`, `processing`, `ready`, `partial`,
`failed` or `unavailable`. Missing fields mean information was not recorded.

`metadata` contains `version: 1`, detected `mime`/`format`, `kind`, short
`summary` strings, technical `groups` (`name` and `rows` of `label`/`value`), and
`limited`. The same selected technical information appears on the public share
page and persists after staging cleanup. It excludes personal tags and contents.
Values come from source headers/metadata and are not a safety or full-file
validation result. A completed source released after transfer can remain staged
for up to ten minutes while this task finishes, within the original session TTL.
