Skip to main content
All endpoints on this page require authentication via Authorization: Bearer <token>.

Avatar

Get avatar

GET /api/avatar
Returns the user’s avatar image. If the avatar is an external URL (e.g., from an OAuth provider), the response is a 302 redirect. Otherwise, the image binary is returned directly.

Response 200

Binary image data with appropriate Content-Type header (image/jpeg, image/png, image/webp, or image/gif).

Response 302

Redirect to external avatar URL (OAuth avatars).

Response 404

{
  "message": "Avatar not found"
}

Upload avatar

POST /api/avatar
Uploads a new avatar image. The old avatar is automatically deleted.
Send the file as multipart/form-data with the field name avatar.
ConstraintValue
Max file size2 MB
Allowed formatsJPEG, PNG, WebP, GIF

Response 200

{
  "avatar": "cuid_abc123/avatar_1717596600.png",
  "message": "Avatar uploaded successfully"
}

Response 400

{
  "message": "File too large. Maximum size is 2MB"
}

Delete avatar

DELETE /api/avatar
Removes the user’s avatar.

Response 200

{
  "message": "Avatar deleted successfully"
}

Custom domain

Custom domains are only available on the enterprise tier for the DROP service.

Get custom domain

GET /api/user/custom-domain
Returns the current custom domain configuration.

Response 200

{
  "customDomain": "files.example.com",
  "customDomainVerified": true,
  "hasCustomDomain": true
}

Response 403

{
  "message": "Enterprise plan required for custom domains"
}

Set custom domain

POST /api/user/custom-domain
Connects a custom domain to the user’s DROP service. The domain starts as unverified - DNS configuration is required.
domain
string
required
The custom domain to connect (e.g., files.example.com).

Response 200

{
  "success": true,
  "domain": "files.example.com",
  "message": "Domain connected successfully. Please configure your DNS settings."
}

Response 409

{
  "message": "Domain is already in use"
}

Delete custom domain

DELETE /api/user/custom-domain
Disconnects the custom domain.

Response 200

{
  "success": true,
  "message": "Custom domain disconnected successfully"
}

Services

List services

GET /api/services
Returns the user’s service entitlements. Optionally filter by service.
service
string
Filter by service identifier. Currently supported: DROP.

Response 200

{
  "entitlements": [
    {
      "id": "ent_abc123",
      "userId": "cuid_abc123",
      "service": "DROP",
      "tier": "pro",
      "isPremium": true,
      "connected": true,
      "customStorageLimit": null,
      "customApiKeyLimit": null,
      "metadata": {},
      "createdAt": "2026-01-15T10:30:00.000Z",
      "updatedAt": "2026-06-05T14:30:00.000Z"
    }
  ]
}

Update service

POST /api/services
Creates or updates a service entitlement for the current user.
service
string
required
Service identifier (e.g., DROP).
tier
string
Service tier (e.g., free, pro-lite, pro, enterprise).
isPremium
boolean
Whether the user has premium access.
accessFlags
object
Custom access flags for the service.
metadata
object
Arbitrary metadata for the service entitlement.
customStorageLimit
number
Custom storage limit override in bytes.
customApiKeyLimit
number
Custom API key limit override.

Response 200

{
  "entitlement": {
    "id": "ent_abc123",
    "service": "DROP",
    "tier": "pro",
    "isPremium": true,
    ...
  }
}

Subscription

Get subscription

GET /api/subscription
Returns the user’s current Polar subscription details for the DROP service. Prices are converted to PLN.

Response 200

{
  "id": "sub_polar_123",
  "status": "active",
  "currentPeriodStart": 1717200000,
  "currentPeriodEnd": 1719792000,
  "cancelAtPeriodEnd": false,
  "plan": "pro",
  "billingCycle": "monthly",
  "price": {
    "amount": 39.96,
    "currency": "pln",
    "interval": "month"
  },
  "product": {
    "name": "Premium"
  }
}

Response 404

{
  "message": "No active subscription"
}