Skip to navigation

Sharing an Encrypted File

View as Markdown

Overview

Files are encrypted on your side before they are uploaded. Konfidant stores only the ciphertext and never receives the content, the file name or the key. See Zero-Knowledge Encryption for the model and the KNF1 format.

With an official SDK, sharing a file is one call:

import { readFile } from 'node:fs/promises';
const { shareUrl } = await client.shareFile(await readFile('./report.pdf'), {
filename: 'report.pdf',
contentType: 'application/pdf',
ttlHours: 72,
});

The SDKs also expose the individual steps (createFileUpload, uploadCiphertext and completeFileUpload, or their equivalents in each language) if you need to control the upload yourself.

The file flow step by step

Without an SDK, you must encrypt the file as KNF1 yourself and then make three requests.

1. Create an upload

Compute the exact size of the KNF1 ciphertext and request an upload slot. ttl_hours is optional and defaults to your plan’s maximum.

curl --request POST 'https://www.konfidant.app/api/v1/files' \
--header 'Authorization: Bearer kf_live_...' \
--header 'Content-Type: application/json' \
--data '{"ciphertext_size": 1048720, "ttl_hours": 48}'
{
"upload_url": "https://<account>.r2.cloudflarestorage.com/encrypted-eu/3f9a...?X-Amz-Algorithm=...",
"file_key": "3f9a0c5e7b1d2a4f6e8c0b9d7a5f3e1c2b4d6f8a0e9c7b5d3f1a2c4e6b8d0f9a",
"upload_headers": { "Content-Type": "application/octet-stream" },
"upload_expires_in": 3600
}

The request is rejected with 400 if the size exceeds your plan’s file size limit, and with 403 if your monthly upload quota or API share allowance is used up.

2. Upload the ciphertext

PUT the KNF1 bytes to upload_url with exactly the headers in upload_headers, within upload_expires_in seconds. The body must be exactly ciphertext_size bytes; storage rejects any other size. Do not send your API key to this URL.

curl --request PUT 'THE_UPLOAD_URL' \
--header 'Content-Type: application/octet-stream' \
--upload-file report.pdf.knf1

3. Complete the share

curl --request POST 'https://www.konfidant.app/api/v1/files/3f9a0c5e.../complete' \
--header 'Authorization: Bearer kf_live_...'
{
"download_url": "https://download.konfidant.app/#t=hvs.CAESIABCDEFG...",
"file_id": "681da863-a551-4b0e-8f3c-6d2e9a1b7c40",
"expires_at": "2026-10-05T12:00:00.000Z",
"verified_burn": true
}

The response is immediate: there is no server-side encryption step to wait for and no status endpoint to poll. Completion succeeds exactly once per upload. file_id is null unless your organization has verified burn enabled.

StatuserrorMeaning
404not_foundUnknown file_key, or the upload was already completed
409upload_incompleteThe ciphertext is not in storage yet. Retry after the PUT has finished
410expiredThe upload was not completed within 2 hours. Start again from step 1
422invalid_ciphertextThe uploaded object does not match ciphertext_size or is not KNF1. It has been deleted

Append the key to the fragment and send the result to the recipient:

share_link = download_url + "&k=" + base64url(key) # unpadded, 43 characters

The recipient can open the link once, until expires_at. The ciphertext is deleted as soon as it has been delivered.