Files API
Create shareable encrypted file bundles via the REST API.
Overview
The Files API lets you create an end-to-end encrypted file bundle from a set of files. Each bundle is assigned a short, shareable ID and a preview URL. The server never sees plaintext data — encryption and decryption happen entirely on the client side.
File bundles automatically expire after 24 hours and are no longer accessible after that.
All file content is end-to-end encrypted using AES-256-GCM. The server only stores the encrypted blob and cannot read the content. Viewers must enter the correct passphrase to decrypt.
Quick Start
Encrypt your file data
Encrypt the { files } JSON using the encryption function with your chosen passphrase:
const plaintext = JSON.stringify({
files: [
{
title: "src/auth.ts",
content: "export function login(token: string) {\n const user = validate(token);\n return user;\n}",
},
{
title: "README.md",
content: "# My Project\n\nA secure file sharing service.",
},
],
});
const encrypted = await encryptFiles(plaintext, "my-secret-passphrase");Send the encrypted payload
curl -X POST https://diff4.com/api/files \
-H "Content-Type: application/json" \
-d '{
"encrypted_data": {
"ciphertext": "...",
"iv": "...",
"salt": "..."
}
}'Get your preview URL
{
"success": true,
"data": {
"id": "B7KM2P",
"preview_url": "https://diff4.com/f/B7KM2P"
}
}Share the link and passphrase
Open preview_url in any browser. The viewer will prompt for the passphrase to decrypt and render the file bundle. The page displays a two-panel layout — file list on the left, selected file's content on the right. If the viewer previously entered the passphrase (shared with diff previews), it will be remembered automatically.
Endpoint
POST /api/filesRequest Body
Send a JSON object with the following field:
| Field | Type | Required | Description |
|---|---|---|---|
encrypted_data | object | Yes | Encrypted payload (ciphertext, iv, salt) |
Encrypted Data Object
| Field | Type | Description |
|---|---|---|
ciphertext | string | Base64-encoded AES-256-GCM ciphertext |
iv | string | Base64-encoded 12-byte initialization vector |
salt | string | Base64-encoded 16-byte PBKDF2 salt |
Responses
{
"success": true,
"data": {
"id": "B7KM2P",
"preview_url": "https://diff4.com/f/B7KM2P"
}
}| Field | Type | Description |
|---|---|---|
id | string | 6-character ID for the file bundle |
preview_url | string | Full URL to view the file bundle |
Returned when required fields are missing or invalid.
{
"success": false,
"error": "ciphertext must be a string, iv must be a string"
}{
"success": false,
"error": "Internal server error"
}Notes
- The plaintext (before encryption) must be valid JSON with a
filesarray. - Each file entry has
title(string, required) andcontent(string, required). - The server cannot decrypt the content. If the passphrase is lost, the files are unrecoverable.
- No authentication is required to create or view file bundles, but the passphrase is needed to decrypt.
- Passphrase storage is shared with the Diff API — entering a passphrase for one will be remembered for the other.