Access your encrypted files programmatically using our REST API. All file content remains encrypted - you'll need your encryption key to decrypt files after downloading.
All API requests require your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Returns all files associated with your API key.
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://geohavnvault.com/api/files
{
"success": true,
"upload": {
"id": "abc123",
"status": "paid",
"expiresAt": "2025-03-05T00:00:00Z",
"fileCount": 2
},
"files": [
{
"id": "file123",
"name": "encrypted-filename.pdf",
"size": 1048576,
"uploadDate": "2025-09-05T10:00:00Z",
"encryptedUrl": "https://geohavnvault.com/api/download/file123"
}
]
}
Returns metadata for a specific file without downloading it.
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://geohavnvault.com/api/files/file123
Downloads the encrypted file content. The file remains encrypted - you'll need to decrypt it using your encryption key.
# Using Authorization header
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://geohavnvault.com/api/download/file123 \
-o encrypted-file.bin
# Using query parameter
curl "https://geohavnvault.com/api/download/file123?key=YOUR_API_KEY" \
-o encrypted-file.bin
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="encrypted-filename.pdf"
X-File-Encrypted: true
After downloading files via the API, you'll need to decrypt them using your encryption key. Files are encrypted using AES-256-GCM with the IV prepended to the encrypted data.
import { createDecipheriv, createHash } from 'crypto';
import { readFile, writeFile } from 'fs/promises';
async function decryptFile(
encryptedPath: string,
decryptedPath: string,
encryptionKey: string
) {
// Read encrypted file
const encryptedData = await readFile(encryptedPath);
// Extract IV (first 16 bytes) and encrypted content
const iv = encryptedData.slice(0, 16);
const authTag = encryptedData.slice(16, 32);
const encrypted = encryptedData.slice(32);
// Derive key from string (must match frontend logic)
const key = createHash('sha256')
.update(encryptionKey)
.digest();
// Create decipher
const decipher = createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
// Decrypt
const decrypted = Buffer.concat([
decipher.update(encrypted),
decipher.final()
]);
// Write decrypted file
await writeFile(decryptedPath, decrypted);
}
// Usage
await decryptFile(
'downloaded-file.bin',
'decrypted-file.pdf',
'your-encryption-key-here'
);
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import hashlib
def decrypt_file(encrypted_path, decrypted_path, encryption_key):
# Read encrypted file
with open(encrypted_path, 'rb') as f:
encrypted_data = f.read()
# Extract IV (first 16 bytes) and auth tag
iv = encrypted_data[:16]
auth_tag = encrypted_data[16:32]
ciphertext = encrypted_data[32:]
# Derive key from string (must match frontend logic)
key = hashlib.sha256(encryption_key.encode()).digest()
# Create cipher
cipher = Cipher(
algorithms.AES(key),
modes.GCM(iv, auth_tag),
backend=default_backend()
)
decryptor = cipher.decryptor()
# Decrypt
decrypted = decryptor.update(ciphertext) + decryptor.finalize()
# Write decrypted file
with open(decrypted_path, 'wb') as f:
f.write(decrypted)
# Usage
decrypt_file(
'downloaded-file.bin',
'decrypted-file.pdf',
'your-encryption-key-here'
)
Endpoint | Rate Limit |
---|---|
/api/files | 20 requests per minute |
/api/download/* | 30 requests per minute |
Rate limits return a 429 status code with a Retry-After header indicating when you can retry.
All errors return JSON with an error message:
{
"error": "Error message",
"details": "Additional information if available"
}