TEASEDocs
ProductsClubHow-to

Upload new content to the vault

Add a new photo or video to the OnlyFans vault directly from the panel.

Who this is for: a workspace owner or team member with upload access (the media_upload grant).

Uploads are byte-less: the backend only ever brokers an address and a completion signal. Your browser sends the actual file straight to the address OnlyFans issues. Check first whether uploads are live — vault_write is gated by two independent switches, and either being off means an honest {"enabled": false}, not a broken button.

curl "https://app.tease.link/api/admin/vault/upload/enabled" \
  -H "Authorization: Bearer $TEASE_API_KEY"
{ "enabled": true, "shadow": false, "photo_max_mb": 50, "video_max_gb": 4 }

Start the upload

Send the file's name, size, and content type — never the bytes themselves.

curl -X POST "https://app.tease.link/api/admin/vault/upload" \
  -H "Authorization: Bearer $TEASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "beach.mp4", "size": 104857600, "content_type": "video/mp4", "export_type": "message"}'
FieldTypeDescription
namestringFile name, up to 255 chars.
sizeintegerDeclared size in bytes — checked against the ceiling before an address is issued.
content_typestringOne of image/jpeg, image/png, image/webp, image/heic, video/mp4, video/quicktime, video/webm. Anything else is a 415.
export_typestringmessage (default — headed for a chat/PPV) or post (headed for the wall).
fan_idstringOptional; only meaningful for a message upload tied to one fan.

A photo over 50 MB or a video over 4 GB is rejected with a 413 before anything is requested from OnlyFans. The response is {"status": "pending", "upload_id": "...", "nonce": "..."} — an upload_id to poll, never a finished upload.

Poll until an address is ready

curl "https://app.tease.link/api/admin/vault/upload/{upload_id}" \
  -H "Authorization: Bearer $TEASE_API_KEY"

States: queuedreadyfinishingdone, or failed / shadow. Once ready, the response carries put — the target(s) your browser should PUT the file's bytes to directly (one part for a small file, several for a large multipart upload).

Complete the upload

After every part has landed on the put target(s), tell the engine to close the upload and mint a media_id:

curl -X POST "https://app.tease.link/api/admin/vault/upload/{upload_id}/complete" \
  -H "Authorization: Bearer $TEASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"parts": [{"part": 1, "e_tag": "\"d41d8...\""}]}'

Parts must be numbered 1..N in order with a real ETag from the PUT response — OnlyFans' CompleteMultipartUpload requires it, and an out-of-order or missing ETag is rejected before it ever reaches the vendor. On success the file appears in All content immediately — you don't have to wait for the next scan.

If something goes wrong

  • Cancel: POST /vault/upload/{upload_id}/abort closes the row and asks the engine to clean up any partial multipart write in the bucket.
  • No resume. If the tab closes or the connection drops mid-transfer, the upload fails with "start the upload again" — there's no docking back into a partial upload.
  • Two-hour window. Once an address is ready, you have two hours to finish sending bytes before the upload is marked failed on its own.

What's next

See the recent uploads and how they ended with GET /vault/uploads, or read async engine write gotchas for what {"enabled": false, "staged": true} means.

On this page