TiniDrop API Reference

The TiniDrop REST API lets you upload files, manage projects, retrieve per-file analytics, and register webhooks — all programmatically. Available on Solo and Pro plans.

Base URL: https://tinidrop.com/apiJSON responsesHTTPS only

Authentication

All API requests must be authenticated using an API key. Generate one from your dashboard under the API Keys tab. API access requires Solo or Pro plan.

Pass your key as the x-api-key header on every request:

curl https://tinidrop.com/api/me \
  -H "x-api-key: td_YOUR_API_KEY"

Keep your API key secret. Anyone with your key can upload, delete, and manage files on your account. Rotate it immediately if compromised.

/me

GET
/api/me

Returns the authenticated user's profile, plan details, and current usage.

curl https://tinidrop.com/api/me \
  -H "x-api-key: td_YOUR_API_KEY"
{
  "id": "uuid",
  "email": "you@example.com",
  "plan": "pro",
  "plan_name": "Pro",
  "limits": {
    "max_file_size_bytes": 10737418240,
    "max_file_size_mb": 10240,
    "max_storage_bytes": 10737418240,
    "max_projects": 200,
    "max_visits_per_month": 500000,
    "expiry_days": null,
    "features": {
      "api_access": true,
      "analytics": true,
      "email_capture": true,
      "disable_download": true,
      "webhooks": true
    }
  },
  "usage": {
    "files": 12,
    "storage_bytes": 52428800,
    "storage_mb": 50,
    "visits_this_month": 3421
  }
}

/files

GET
/api/files

List all files for the authenticated user. Supports pagination and filtering.

Query Parameters

limitinteger

Max results per page. Default: 50. Max: 200.

offsetinteger

Pagination offset. Default: 0.

projectstring

Filter by project_id (UUID).

searchstring

Case-insensitive file name search.

curl "https://tinidrop.com/api/files?limit=10&search=report" \
  -H "x-api-key: td_YOUR_API_KEY"
{
  "files": [
    {
      "id": "uuid",
      "slug": "my-report-2026",
      "name": "Q1-report.pdf",
      "url": "https://tinidrop.com/s/my-report-2026",
      "size_bytes": 512000,
      "visits": 142,
      "created_at": "2026-01-15T10:30:00Z",
      "expires_at": null,
      "project_id": "uuid",
      "project_name": "Client Reports",
      "password_protected": false,
      "email_capture": false,
      "disable_download": false
    }
  ],
  "total": 1,
  "limit": 10,
  "offset": 0
}
POST
/api/upload

Upload a new file and receive a shareable link. Uses multipart/form-data.

Form Fields

fileFilerequired

The file to upload. See supported formats below.

customSlugstring

Vanity URL slug (Solo+ only). E.g. my-portfolio

passwordstring

Password-protect this file (Solo+ only).

projectIdstring

UUID of a project to attach this file to.

disableDownloadboolean

Prevent visitors from downloading the file (Solo+ only).

emailCaptureboolean

Require visitor email before access (Pro+ only).

feedbackboolean

Enable feedback widget on the viewer page (Starter+ only).

curl -X POST https://tinidrop.com/api/upload \
  -H "x-api-key: td_YOUR_API_KEY" \
  -F "file=@report.pdf" \
  -F "customSlug=q1-report-2026" \
  -F "disableDownload=true"
{
  "slug": "q1-report-2026",
  "url": "https://tinidrop.com/s/q1-report-2026",
  "original_name": "report.pdf",
  "size_bytes": 512000,
  "expires_at": null
}
GET
/api/files/{slug}

Get metadata for a single file.

curl https://tinidrop.com/api/files/q1-report-2026 \
  -H "x-api-key: td_YOUR_API_KEY"
PATCH
/api/files/{slug}

Update file settings post-upload. All fields are optional.

Body (JSON)

namestring

Rename the file's display name.

passwordstring

Set or change password. Pass empty string to remove.

disable_downloadboolean

Toggle download disable (Solo+ only).

email_captureboolean

Toggle email gate (Pro+ only).

feedbackboolean

Toggle feedback widget (Starter+ only).

expires_atISO-8601 | null

Set or clear expiry. Pass null to make permanent.

slugstring

Rename the URL slug (Solo+ only, must be unique).

curl -X PATCH https://tinidrop.com/api/files/q1-report-2026 \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"disable_download": true, "slug": "q1-final"}'
{
  "success": true,
  "slug": "q1-final",
  "url": "https://tinidrop.com/s/q1-final"
}
PUT
/api/upload

Replace an existing file's content while keeping the same URL. Pass the target slug as a form field.

fileFilerequired

New file content.

slugstringrequired

Slug of the file to replace.

curl -X PUT https://tinidrop.com/api/upload \
  -H "x-api-key: td_YOUR_API_KEY" \
  -F "file=@report-v2.pdf" \
  -F "slug=q1-final"
DELETE
/api/delete

Permanently delete a file and remove it from storage.

curl -X DELETE https://tinidrop.com/api/delete \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug": "q1-final"}'
{ "success": true }

Supported file formats

ZIPHTMLPDFDOCXPPTXXLSXTXTCSVMDJPGPNGGIFWEBPSVGTIFFAVIFBMPMP4WEBMMOVMP3OGGWAVJSONXML

/projects

GET
/api/projects

List all projects.

curl https://tinidrop.com/api/projects \
  -H "x-api-key: td_YOUR_API_KEY"
{
  "projects": [
    {
      "id": "uuid",
      "name": "Client Reports",
      "slug": "client-reports-xk2m1",
      "created_at": "2026-01-01T00:00:00Z"
    }
  ]
}
POST
/api/projects

Create a new project.

namestringrequired

Project display name.

curl -X POST https://tinidrop.com/api/projects \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Client Reports"}'
PATCH
/api/projects

Rename a project.

idstringrequired

Project UUID.

namestringrequired

New project name.

curl -X PATCH https://tinidrop.com/api/projects \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "uuid", "name": "Client Reports Q2"}'
POST
/api/move-to-project

Move a file into a project.

slugstringrequired

File slug to move.

projectIdstring

Target project UUID. Pass null to remove from project.

curl -X POST https://tinidrop.com/api/move-to-project \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug": "q1-final", "projectId": "uuid"}'
DELETE
/api/projects

Delete a project. Files are unlinked but not deleted.

idstringrequired

Project UUID.

curl -X DELETE https://tinidrop.com/api/projects \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": "uuid"}'

/analytics Unique feature

Per-file analytics via API. No other file hosting service exposes this. Use it to build dashboards, Zapier automations, Notion integrations, and more.

GET
/api/analytics/{slug}

Returns daily visit breakdown, referrer sources, and unique visitor counts.

daysinteger

Lookback window in days. Default: 30. Max: 365.

curl "https://tinidrop.com/api/analytics/q1-final?days=7" \
  -H "x-api-key: td_YOUR_API_KEY"
{
  "slug": "q1-final",
  "name": "report.pdf",
  "total_visits": 1842,
  "period_visits": 234,
  "unique_visitors": 198,
  "daily": [
    { "date": "2026-04-25", "visits": 45 },
    { "date": "2026-04-26", "visits": 31 }
  ],
  "referrers": [
    { "source": "direct", "visits": 120 },
    { "source": "twitter.com", "visits": 64 },
    { "source": "notion.so", "visits": 50 }
  ],
  "period_start": "2026-04-24T00:00:00.000Z",
  "period_end": "2026-05-01T00:00:00.000Z",
  "days": 7
}

/webhooks

Register HTTPS endpoints to receive real-time notifications for TiniDrop events. Each delivery is signed with X-TiniDrop-Signature (HMAC-SHA256).

Available Events

file.uploadedA new file was uploaded to your account.
file.deletedA file was deleted from your account.
file.visitedA visitor opened one of your shared file pages.
email.capturedA visitor submitted their email on an email-gated file.
*Subscribe to all events.
GET
/api/webhooks

List all webhook registrations.

curl https://tinidrop.com/api/webhooks \
  -H "x-api-key: td_YOUR_API_KEY"
{
  "webhooks": [
    {
      "id": "uuid",
      "url": "https://your-server.com/hooks/tinidrop",
      "events": ["file.uploaded", "email.captured"],
      "is_active": true,
      "created_at": "2026-01-01T00:00:00Z",
      "last_triggered_at": "2026-04-30T12:00:00Z",
      "failure_count": 0
    }
  ]
}
POST
/api/webhooks

Register a new webhook endpoint.

urlstringrequired

Public HTTPS URL that will receive POST requests.

eventsstring[]

Events to subscribe to. Default: ["*"] (all events).

curl -X POST https://tinidrop.com/api/webhooks \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-server.com/hooks", "events": ["email.captured"]}'
{
  "webhook": {
    "id": "uuid",
    "url": "https://your-server.com/hooks",
    "events": ["email.captured"],
    "secret": "whsec_abc123...",
    "is_active": true
  }
}

Verifying webhook signatures

// Node.js example
const crypto = require('crypto');

function verifySignature(secret, payload, sigHeader) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(sigHeader),
    Buffer.from(expected)
  );
}
PATCH
/api/webhooks/{id}

Update a webhook's URL, events, or active status.

urlstring

New endpoint URL.

eventsstring[]

Replace event subscriptions.

is_activeboolean

Pause (false) or resume (true) delivery.

curl -X PATCH https://tinidrop.com/api/webhooks/uuid \
  -H "x-api-key: td_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'
DELETE
/api/webhooks/{id}

Remove a webhook registration.

curl -X DELETE https://tinidrop.com/api/webhooks/uuid \
  -H "x-api-key: td_YOUR_API_KEY"

Errors

All errors return a JSON body with an error string and a standard HTTP status code.

400Bad RequestMissing required field or invalid value.
401UnauthorizedMissing or invalid x-api-key.
403ForbiddenPlan does not include this feature, or resource belongs to another user.
404Not FoundFile, project, or webhook not found.
409ConflictSlug already taken (on upload or rename).
413Payload Too LargeFile exceeds your plan limit.
429Too Many RequestsRate limit or per-account limit reached.
500Server ErrorInternal error — try again or contact support.

Rate Limits

API requests are rate-limited per API key:

  • Solo plan: 120 requests / minute, 5,000 uploads / day
  • Pro plan: 600 requests / minute, 25,000 uploads / day

When a limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header indicating when to retry.

© 2026 TiniDrop. Built for developers.