# File Drop Integration Contract Version: `filedrop.v1` The File Drop service is backend/API-first. UI code is only an integration example. Host systems discover an active dropbox, encrypt locally to the advertised recipient key, then commit ciphertext and the E2EE envelope to the intake endpoint. ## Discovery `GET /api/dropbox/current` Response: ```json { "contractVersion": "filedrop.v1", "dropboxId": "default", "fingerprint": "recipient-key-fingerprint", "key": { "fingerprint": "recipient-key-fingerprint", "publicKey": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }, "source": "configured", "status": "active" }, "label": "Interling secure intake", "publicKey": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }, "source": "configured", "status": "active", "recipientKeys": [ { "fingerprint": "recipient-key-fingerprint", "publicKey": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }, "source": "configured", "status": "active" }, { "fingerprint": "master-recovery-fingerprint", "publicKey": { "kty": "EC", "crv": "P-256", "x": "...", "y": "..." }, "source": "configured", "status": "active" } ] } ``` Integrations must show or otherwise pin the recipient `fingerprint` where key authenticity matters. The `key.status` value is one of `active`, `rotating`, or `revoked`. Upload UIs must not accept new files for revoked keys. ## Upload Commit `POST /api/uploads/intake` Content type: `multipart/form-data` Fields: - `ciphertext`: encrypted file bytes. - `envelope`: JSON E2EE envelope from `@addideas/sefidrop/e2ee`. - `contactName`: sender name. - `contactEmail`: sender email. - `dropboxId`: discovery response id. - `routingLabel`: operational routing label. - `serviceType`: optional operational service type. - `languagePair`: optional operational language pair. - `requestedDeadline`: optional operational date. - `projectPublicId`: optional existing order id for project-specific drop links. The original filename, note, MIME type, and other sensitive sender metadata stay in the encrypted E2EE metadata envelope. New integrations should encrypt to every active `recipientKeys[]` entry and submit an envelope with `recipients[]`. The legacy `recipient` field remains required and mirrors the first recipient wrap for older consumers. Response: ```json { "id": "upload-id", "orderId": "INTAKE-20260710-XXXXXXXX", "storageKey": "upload-id.enc", "status": "ciphertext_received" } ``` ## Event Each accepted upload emits a `filedrop.upload.received` event. Interling records that event in `project_events`, links the ciphertext row to an order, and exposes it in the portal timeline. The event payload is intentionally host-neutral: ```json { "contractVersion": "filedrop.v1", "eventType": "filedrop.upload.received", "occurredAt": "2026-07-10T17:32:07.000Z", "sender": { "contactEmail": "client@example.com" }, "routing": { "dropboxId": "default", "serviceType": "translation", "languagePair": "DE -> EN" }, "storage": { "driver": "local", "key": "upload-id.enc", "manifestKey": "upload-id.json" }, "upload": { "id": "upload-id", "ciphertextByteLength": 12345, "ciphertextSha256": "base64url-sha256", "recipientKeyFingerprint": "recipient-key-fingerprint", "recipientKeyFingerprints": ["recipient-key-fingerprint", "master-recovery-fingerprint"] } } ``` ## Webhook Signature Future standalone deployments can deliver the same event via webhook instead of direct DB integration. Signed webhook deliveries use these headers: - `x-filedrop-webhook-id`: stable id for idempotency. - `x-filedrop-timestamp`: Unix timestamp in seconds. - `x-filedrop-signature`: HMAC-SHA256 signature, formatted as `v1=`. The signature input is: ```txt . ``` Receivers should reject old timestamps and verify the signature with a shared webhook secret. ## Storage Boundary The package exposes a `FileDropStorage` interface. The current Interling host uses the local filesystem adapter; a standalone service can provide S3-compatible storage without changing the upload commit contract.