API Documentation

Everything you need to integrate with transfer.injected.wtf — upload and download encrypted files with curl, wget, or any HTTP client.

One-Command Upload

Upload any file with a single curl command and get a shareable link back instantly.

Encrypted at Rest

XChaCha20-Poly1305 encryption on the server. No client-side setup, no keys to manage.

Auto-Expiring

Files are automatically deleted after the configured expiration period. 30-day maximum.

Overview

transfer.injected.wtf is an encrypted, ephemeral file sharing service. Every file uploaded is encrypted on the server with XChaCha20-Poly1305 before it touches disk. Downloads are decrypted on-the-fly and streamed over TLS.

There is no client-side encryption and no decryption key needed. URLs are public and work everywhere — browsers, curl, wget, scripts. The goal is protecting data at rest in case of a server-side data leak.

Quick Start

bash
# Upload a file curl --upload-file ./secret.pdf https://transfer.injected.wtf/secret.pdf # The response is a JSON object with the download URL # { # "id": "abc123def", # "filename": "secret.pdf", # "url": "https://transfer.injected.wtf/abc123def/secret.pdf", # "size": 1048576, # "expires": "2026-03-21T07:00:00.000Z" # } # Download it back curl https://transfer.injected.wtf/abc123def/secret.pdf -o secret.pdf
No setup required. There are no API keys, no accounts, and no authentication. Just upload and share.

CLI Upload

Upload files from the command line using PUT requests. The filename in the URL path determines the download filename.

PUT /:filename

Stream a file to the server via HTTP PUT. This is the simplest method and works with curl's --upload-file flag.

bash
# Basic upload curl --upload-file ./report.pdf https://transfer.injected.wtf/report.pdf # Set custom expiry (default: 14 days, max: 30) curl -H "X-Max-Days: 7" --upload-file ./report.pdf \ https://transfer.injected.wtf/report.pdf # Upload with progress bar curl --progress-bar --upload-file ./large-backup.tar.gz \ https://transfer.injected.wtf/large-backup.tar.gz

POST /api/upload

Alternatively, use a multipart form POST. This is what the web UI uses internally. Accepts a file field and an optional maxDays field.

bash
# Multipart upload curl -F "file=@./photo.jpg" -F "maxDays=7" \ https://transfer.injected.wtf/api/upload

Request Headers

Header Description Default
X-Filename Override the filename from the URL path Path segment
X-Max-Days Number of days before the file auto-deletes (1–30) 14
Content-Type MIME type of the file (auto-detected if not provided) application/octet-stream

Web Upload

The web interface provides a drag-and-drop upload experience with real-time progress tracking.

How It Works

The web uploader uses the POST /api/upload endpoint internally. Simply drag a file onto the upload card, set your desired expiry, and click Upload.

Features

Feature Details
Drag & drop Drop files anywhere on the upload card
Clipboard paste Paste files or screenshots directly with Ctrl+V
Progress bar Real-time XHR upload progress with percentage
Custom expiry Choose 1–30 days via the stepper control
Copy link One-click copy of the resulting download URL

Download

Every uploaded file gets a unique, shareable download URL that works in any browser or HTTP client.

URL Format

Download URLs follow this pattern:

url
https://transfer.injected.wtf/{id}/{filename}

The server decrypts the file on-the-fly and streams it directly to you over TLS. No special client or decryption key is needed.

curl Download

bash
# Download a file curl https://transfer.injected.wtf/abc123def/secret.pdf -o secret.pdf # Download with wget wget https://transfer.injected.wtf/abc123def/secret.pdf

File Info API

Get metadata about a file without downloading it:

bash
# Get file info (JSON) curl https://transfer.injected.wtf/api/download/abc123def/info

Raw Download API

Force a raw binary download (bypasses browser content negotiation):

bash
# Raw binary stream curl https://transfer.injected.wtf/api/download/abc123def/raw -o file.bin
Content-Length header. The server sends a proper Content-Length header so progress bars work correctly in curl, wget, and browsers.

Encryption

All files are encrypted server-side before being written to disk, protecting against data breaches and disk theft.

Algorithm

Property Value
Cipher XChaCha20-Poly1305
Key size 256-bit
Nonce size 192-bit (extended nonce)
Authentication Poly1305 MAC (authenticated encryption)
Key derivation Unique random key per file
No client-side encryption. The design is intentionally server-side only. This allows public URLs to work with curl, wget, and browsers without requiring a decryption key. The threat model protects against server-side data leaks, not in-transit interception (TLS handles that).

How It Works

1. You upload a file via PUT or POST.

2. The server generates a unique 256-bit key and 192-bit nonce.

3. The file is encrypted with XChaCha20-Poly1305 and written to disk.

4. The key and nonce are stored in a metadata database (not on disk with the file).

5. On download, the server reads the key from the database, decrypts the file in a stream, and sends it over TLS.

6. When the file expires, both the encrypted file and metadata are permanently deleted.

Limits

The following limits are enforced to keep the service running smoothly for everyone.

Service Limits

Limit Value Notes
Max file size 10 GB Per-upload limit. Larger files are rejected.
Max expiry 30 days Files are auto-deleted after expiry. Default is 14 days.
Min expiry 1 day Cannot be set lower than 24 hours.
Rate limit 10 req/min Per-IP upload rate limit. Downloads are not rate limited.
Rate limit exceeded? You will receive a 429 Too Many Requests response. Wait a minute and try again.

Response Format

All API responses are JSON. Here are the response shapes for each endpoint.

Upload Success (200)

json
{ "id": "abc123def", "filename": "secret.pdf", "url": "https://transfer.injected.wtf/abc123def/secret.pdf", "size": 1048576, "expires": "2026-03-21T07:00:00.000Z" }

File Info (200)

json
{ "id": "abc123def", "filename": "secret.pdf", "size": 1048576, "mime": "application/pdf", "expires": "2026-03-21T07:00:00.000Z", "created": "2026-03-07T07:00:00.000Z" }

Error Response (4xx / 5xx)

json
{ "error": "File not found", "code": "NOT_FOUND", "status": 404 }

HTTP Status Codes

Code Meaning
200 Success — upload complete or file info returned
400 Bad request — missing file, invalid parameters
404 File not found or expired
413 File too large (exceeds 10 GB limit)
429 Rate limit exceeded — wait and retry
500 Server error — unexpected failure