All API requests require authentication via either:
- Session Cookie - For browser-based clients
- API Key - For CLI and programmatic access (Bearer token in
Authorizationheader)
API keys are 256-bit cryptographically secure credentials prefixed with dks_.
Format: dks_<base64url-44-chars>
Storage: Keys are stored as SHA-256 hashes in the database. Only the plaintext key is shown once during creation.
Usage:
curl -H "Authorization: Bearer dks_your-key-here" https://api.example.com/api/public/sync/filesSessions are created via login endpoint and stored as secure HTTP-only cookies. Token expiry: 30 days Token algorithm: HS256 (HMAC with SHA-256)
Purpose: Request a file sync negotiation before upload
Request:
{
"path": "documents/report.pdf",
"chunking": "cdc",
"blockSize": 4096,
"newSize": 5242880,
"contentSha256": "sha256_hash_of_file",
"chunks": [
{
"strongHash": "chunk_sha256_hash",
"length": 4096,
"weakHash": 12345
}
],
"snapshotCurrentVersionId": "version-id-or-null"
}Response:
{
"negotiationId": "neg_123456",
"expiresAt": "2026-05-25T11:23:29Z",
"preSignedUrl": "https://s3.example.com/blocks?...",
"preSignedUrlExpiry": 3600
}Status Codes:
200 OK- Negotiation created successfully400 Bad Request- Invalid input (missing fields, invalid hashes, etc.)401 Unauthorized- Missing or invalid authentication429 Too Many Requests- Rate limit exceeded
Purpose: Upload file chunks using delta encoding
Request:
- Content-Type:
multipart/form-data - Fields:
negotiationId- from /negotiate responsemetadata- JSON with chunk operationsdelta- binary data (literal bytes)
Metadata Example:
{
"ops": [
{ "type": "literal", "length": 1024 },
{ "type": "copy", "offset": 2048, "length": 512 }
]
}Response:
{
"uploadId": "upload_789",
"received": 50331648,
"remaining": 0
}Status Codes:
200 OK- Upload received400 Bad Request- Invalid upload format401 Unauthorized- Invalid authentication or API key413 Payload Too Large- Exceeds 500MB limit429 Too Many Requests- Rate limit exceeded
Purpose: Finalize an upload and create file version
Request:
{
"negotiationId": "neg_123456",
"path": "documents/report.pdf"
}Response:
{
"fileId": "file_abc",
"versionId": "version_123",
"versionNo": 1,
"size": 5242880,
"contentSha256": "file_sha256_hash",
"createdAt": "2026-05-25T10:23:29Z"
}Status Codes:
201 Created- Version created successfully400 Bad Request- Invalid negotiation or path401 Unauthorized- Invalid authentication404 Not Found- Negotiation ID not found409 Conflict- File is being modified concurrently
Purpose: Download a file or specific version
Query Parameters:
fileId- File ID (required)version- Version number (optional, defaults to latest)Range- HTTP range header for resumable downloads
Response:
- Content-Type:
application/octet-stream - Body: Binary file data (streamed)
Status Codes:
200 OK- Full file206 Partial Content- Partial file (from Range header)400 Bad Request- Missing or invalid fileId401 Unauthorized- Invalid authentication404 Not Found- File or version not found
Purpose: List all user files with metadata
Query Parameters:
skip- Pagination offset (default: 0)take- Pagination limit (default: 20, max: 100)sort- Sort field:name,size,updated(default:name)
Response:
{
"files": [
{
"id": "file_123",
"path": "documents/report.pdf",
"versionCount": 3,
"totalSize": 5242880,
"currentVersionId": "version_latest",
"updatedAt": "2026-05-25T10:23:29Z"
}
],
"total": 45,
"skip": 0,
"take": 20
}Status Codes:
200 OK- Files listed401 Unauthorized- Invalid authentication
All error responses follow this format:
{
"error": "Error message",
"code": "ERROR_CODE",
"details": "Additional context if available"
}INVALID_INPUT- Request validation failedNOT_FOUND- Resource not foundUNAUTHORIZED- Missing or invalid authRATE_LIMITED- Too many requestsCONFLICT- Concurrent modificationSERVER_ERROR- Internal server error
API endpoints are rate-limited per user:
- Negotiation requests: 100 per minute
- Upload requests: 1000 per hour
- Download requests: Unlimited
- File listing: 1000 per hour
Rate limit headers:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1234567890
All responses include security headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: ...
The /negotiate endpoint returns pre-signed S3 URLs for direct block uploads:
- Expiry: 15 minutes
- Method: PUT
- Bucket:
deltasync-blocks - Key: Block content hash (SHA-256)
Example:
curl -X PUT \
--data-binary @block.dat \
--header "Content-Length: 4096" \
'https://s3.example.com/deltasync-blocks/sha256hash?X-Amz-Algorithm=...'- Produces variable-sized chunks based on content boundaries
- More efficient for textual changes
- Recommended for most use cases
- Produces fixed-size blocks (typically 4096 bytes)
- Simple and predictable
- Legacy mode for backwards compatibility
Files support multiple versions. All versions are retained by default.
- Version numbers are 1-indexed
- Versions are immutable once committed
- Download specific versions via
?version=Nparameter - Version retention can be configured per user
Uploaded chunks are streamed as binary blobs:
- No framing or length prefixes
- De-chunked on server using metadata ops
- Checksum validation not enforced (rely on TLS)