Drops API

Manage drops and their submissions programmatically.

Drops are public file-reception links you share with anyone. The Drops API lets you create and configure drops, list incoming submissions, download files, and manage read/starred/archived state — all via Bearer token.

Endpoints

MethodPathScopeDescription
GET
/v1/dropsdrops:readList all your drops
POST
/v1/dropsdrops:writeCreate a new drop
GET
/v1/drops/:slugdrops:readGet a single drop by slug
PATCH
/v1/drops/:slugdrops:writeUpdate drop settings
DELETE
/v1/drops/:slugdrops:writeDelete a drop and all its submissions
GET
/v1/drops/:slug/submissionsdrops:readList submissions (newest first, max 100)
GET
/v1/drops/:slug/submissions/:iddrops:readGet a single submission
PATCH
/v1/drops/:slug/submissions/:iddrops:writeMark submission read / starred / archived
DELETE
/v1/drops/:slug/submissions/:iddrops:writeDelete a submission
GET
/v1/drops/:slug/submissions/:id/downloaddrops:readGet a 1-hour presigned download URL

Create a drop

POST /v1/drops — scope: drops:write

Request body:

{
  "name": "Client Uploads",
  "slug": "client-uploads",          // optional — auto-generated if omitted
  "description": "Send me your assets",
  "allowedKinds": "any",             // "any" | "image" | "video" | "audio" | "document"
  "maxFileSizeMB": 200,
  "requireSenderEmail": false,
  "requireMessage": false,
  "autoConvertTo": "mp4",            // optional — auto-converts incoming files
  "autoCompress": false,
  "webhookUrl": "https://your.app/hooks/drop",
  "expiresAt": "2026-12-31T23:59:59Z" // optional
}

Response 201 Created:

{
  "drop": {
    "slug": "client-uploads",
    "name": "Client Uploads",
    "isActive": true,
    "allowedKinds": "any",
    "maxFileSizeMB": 200,
    "submissionCount": 0,
    "totalBytes": 0,
    "createdAt": "2026-05-10T12:00:00Z"
  }
}

List submissions

GET /v1/drops/:slug/submissions — scope: drops:read

Returns up to 100 submissions, newest first.

{
  "submissions": [
    {
      "id": "sub_abc123",
      "dropId": "drop_xyz",
      "senderName": "Alice",
      "senderEmail": "[email protected]",
      "fileName": "promo.mp4",
      "fileSize": 52428800,
      "fileMime": "video/mp4",
      "fileKind": "video",
      "status": "ready",
      "processedFileName": "promo-converted.mp4",
      "isRead": false,
      "isStarred": false,
      "isArchived": false,
      "createdAt": "2026-05-10T14:30:00Z"
    }
  ]
}

Download a submitted file

GET /v1/drops/:slug/submissions/:id/download — scope: drops:read

Returns a presigned R2 URL valid for 1 hour. Add ?processed=true to get the auto-converted file instead of the original (only if the drop has autoConvertTo configured and processing completed).

{
  "url": "https://r2.utified.com/drops/client-uploads/1234-promo.mp4?X-Amz-Signature=…",
  "expiresIn": 3600,
  "file": "original"   // "original" | "processed"
}

Update a submission

PATCH /v1/drops/:slug/submissions/:id — scope: drops:write

Mark as read, starred, or archived. Only these three fields are accepted:

{
  "isRead": true,
  "isStarred": true,
  "isArchived": false
}

Update a drop

PATCH /v1/drops/:slug — scope: drops:write

Accepted fields:

  • name, description, emoji, accentColor
  • isActive — pause/resume the drop without deleting it
  • allowedKinds"any" | "image" | "video" | "audio" | "document"
  • maxFileSizeMB
  • requireSenderEmail, requireMessage
  • autoConvertTo, autoCompress
  • webhookUrl — called when a file arrives
  • expiresAt — ISO 8601 timestamp; set to null to remove expiry

Delete a drop

DELETE /v1/drops/:slug — scope: drops:write

Permanently deletes the drop and all its submissions (cascade). This cannot be undone.