Upload one part (image / audio)
API reference

Upload one part (image / audio)

Uploads one part of an image or audio session: the raw bytes as the request body (`Content-Type: application/octet-stream`).

View as MarkdownUpdated Oct 31, 2026
PUT/api/external/v1/media/uploads/{id}/parts/{partNumber}also served at /api/external/media/uploads/{id}/parts/{partNumber}New

Uploads one part of an image or audio session: the raw bytes as the request body (Content-Type: application/octet-stream).

Every part except the last is exactly partSize (3 MB); the last one is the remainder. Send parts in any order and in parallel. Repeating a part replaces it, so retry a failed part freely.

Authentication

Send the creator's API key as a bearer token: Authorization: Bearer dpfn_…. See Authentication & API keys.

For a creator you manage or onboarded

PUT /api/external/v1/creators/{creatorId}/media/uploads/{id}/parts/{partNumber} — an agency's own key for a creator or AI persona it manages (needs canManageVault), or your app owner's own key for an account your app onboarded. The X-Dropfans-Account header still works but is deprecated. See Acting for a creator.

Path parameters

NameTypeRequiredDescription
idstringRequiredThe upload id from POST /api/external/v1/media/uploads.
partNumberintegerRequired1-based part number, up to totalParts.
Min: 1

Responses

200Part stored.
NameTypeDescription
idstringUpload id.
partNumberintegerThe part you sent.
sizeBytesintegerBytes received.
receivedPartsinteger[]Parts received so far.
missingPartsinteger[]Parts still missing — empty means you can complete.
Example response
{
  "id": "mu_3f9c1a7be0d24c55a1e8b6f2",
  "partNumber": 1,
  "sizeBytes": 3145728,
  "receivedParts": [
    1
  ],
  "missingParts": [
    2,
    3
  ]
}

Errors

StatusBodyWhen
400{"error":"Part number must be 1–3","code":"invalid_part_number"}Part number out of range.
400{"error":"Part 3 must be exactly 1612811 bytes (got 1000)","code":"part_size_mismatch","expectedBytes":1612811}The part is not exactly the size it must have.
400{"error":"Video sessions upload with tus — send the bytes to the tus endpoint","code":"parts_not_used"}A video session.
401{"error":"Unauthorized","code":"unauthorized"}Missing or invalid API key.
404{"error":"Upload not found","code":"upload_not_found"}Unknown id, or an upload of another account.
409{"error":"This upload is completed and takes no more parts","code":"upload_not_accepting_parts","status":"completed"}The session is completed, failed or being completed.
410{"error":"This upload session has expired — start a new one","code":"upload_expired"}Past `expiresAt`.
413{"error":"Parts are at most 3145728 bytes","code":"part_too_large","partSize":3145728}The part is bigger than `partSize`.
400{"error":"X-Dropfans-Account must be an account id (from GET /api/external/agency/creators), not a username.","code":"invalid_account_header"}`X-Dropfans-Account` is not an account id.
400{"error":"X-Dropfans-Account names a different account than the path — send one or the other.","code":"account_mismatch"}Called under /v1/creators/{creatorId}/ with an `X-Dropfans-Account` naming another account.
403{"error":"This key cannot act for that account.","code":"account_not_managed"}The creator in the path (or `X-Dropfans-Account`) is one this key cannot act for: no ACCEPTED management by your agency and not an account your app onboarded (or it no longer holds a key bound to your app), a key minted for one creator, or someone is suspended, banned or deleted. An unknown id gets the same answer.
403{"error":"The agency does not have permission for this on that account.","code":"permission_denied","permission":"canManageVault"}For a managed creator: the agency lacks `canManageVault` on that account.
403{"error":"This app does not have the vault API category enabled. Contact support to enable it.","code":"api_category_disabled","category":"vault"}Your app has the Vault [API category](/developers/concepts/api-categories) switched off.

Rate limiting

Every response carries the X-RateLimit-Tier header and, on limited tiers, the per-minute and per-day trios — read X-RateLimit-Remaining and X-RateLimit-Reset instead of hardcoding limits. Details in Rate limits.

Code samples

curl -X PUT "https://www.dropfans.io/api/external/v1/media/uploads/$VAULT_ITEM_ID/parts/$VAULT_ITEM_ID" \
  -H "Authorization: Bearer $DROPFANS_API_KEY"

Questions? [email protected]