Skip to main content
POST
/
v1
/
buckets
/
{bucket_identifier}
/
uploads
Create Upload
curl --request POST \
  --url https://api.mixpeek.com/v1/buckets/{bucket_identifier}/uploads \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --header 'X-Namespace: <x-namespace>' \
  --data '{
  "blob_property": "video",
  "content_type": "video/mp4",
  "create_object_on_confirm": true,
  "description": "Simple video upload with auto object creation",
  "file_hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "file_size_bytes": 52428800,
  "filename": "product_demo.mp4",
  "object_metadata": {
    "category": "tutorials",
    "title": "Product Demo Video"
  }
}'
{
  "blob_property": "video",
  "blob_type": "VIDEO",
  "bucket_id": "bkt_prod_videos",
  "content_type": "video/mp4",
  "create_object_on_confirm": true,
  "created_at": "2024-01-15T10:30:00Z",
  "description": "New upload ready for S3 upload",
  "expires_at": "2024-01-15T11:30:00Z",
  "file_size_bytes": 52428800,
  "filename": "product_demo.mp4",
  "is_duplicate": false,
  "object_metadata": {
    "category": "tutorials"
  },
  "presigned_url": "https://s3.amazonaws.com/bucket/key?X-Amz-Signature=...",
  "presigned_url_expiration": 3600,
  "s3_key": "int_xyz/ns_abc/api_buckets_uploads_create/upl_abc123xyz789/product_demo.mp4",
  "skip_duplicates": true,
  "status": "PENDING",
  "upload_id": "upl_abc123xyz789"
}

Authorizations

Authorization
string
header
required

Bearer token authentication using your API key. Format: 'Bearer your_api_key'. To get an API key, create an account at mixpeek.com/start and generate a key in your account settings.

Headers

Authorization
string
required

REQUIRED: Bearer token authentication using your API key. Format: 'Bearer sk_xxxxxxxxxxxxx'. You can create API keys in the Mixpeek dashboard under Organization Settings.

Examples:

"Bearer sk_live_abc123def456"

"Bearer sk_test_xyz789"

X-Namespace
string
required

REQUIRED: Namespace identifier for scoping this request. All resources (collections, buckets, taxonomies, etc.) are scoped to a namespace. You can provide either the namespace name or namespace ID. Format: ns_xxxxxxxxxxxxx (ID) or a custom name like 'my-namespace'

Examples:

"ns_abc123def456"

"production"

"my-namespace"

Path Parameters

bucket_identifier
string
required

The unique identifier of the bucket

Body

application/json

Request to generate a presigned URL for direct S3 upload.

⚠️ ⚠️ ⚠️ THIS IS THE PRESIGNED URL SYSTEM ⚠️ ⚠️ ⚠️

This endpoint (POST /buckets/{id}/uploads) is the COMPLETE presigned URL system. It handles:

  • ✅ Presigned URL generation (S3 PUT URLs)
  • ✅ Upload tracking and status management
  • ✅ Validation (quotas, file size, content type, schema)
  • ✅ Duplicate detection
  • ✅ Auto object creation on confirmation
  • ✅ Returns upload_id for later reference

DO NOT CREATE A NEW PRESIGNED UPLOAD ENDPOINT! If you need presigned URLs, use this existing system.

If you think you need a new endpoint:

  1. Check if this system already does it (it probably does)
  2. Extend this system instead of creating redundancy
  3. See api/buckets/uploads/services.py for implementation

Integration Points:

  • Object creation: Use upload_id in CreateBlobRequest.upload_id field
  • See: shared/buckets/objects/blobs/models.py::CreateBlobRequest
  • See: api/buckets/objects/canonicalization.py::resolve_upload_reference()

Workflow:

  1. Call this endpoint to get a presigned URL (all validation happens here)
  2. Upload your file directly to S3 using the presigned URL
  3. Call POST /uploads/{upload_id}/confirm to verify upload
  4. Either: a) Automatic object creation (if create_object_on_confirm=true) b) Manual object creation referencing upload_id later

Use Cases: - Upload a video with automatic object creation on confirmation - Upload multiple files, then combine into one object later - Upload in parallel, create object when all complete - Reuse same upload across multiple objects - Track upload progress and status

Requirements: - filename: REQUIRED, will be validated (no path traversal) - content_type: REQUIRED, must be valid MIME type - bucket_id: Comes from URL path parameter, not request body - All other fields: OPTIONAL with sensible defaults

Note: The bucket_id comes from the URL path (/v1/buckets/{bucket_id}/uploads), not from the request body. The bucket is validated before generating presigned URL.

filename
string
required

Name of the file to upload. REQUIRED. Must be a valid filename without path traversal characters (../, ). The filename is used to derive the blob_property if not explicitly provided. Examples: 'product_video.mp4', 'thumbnail.jpg', 'transcript.txt'

Required string length: 1 - 255
Examples:

"product_video.mp4"

"thumbnail.jpg"

"document.pdf"

content_type
string
required

MIME type of the file. REQUIRED. Must be a valid MIME type (e.g., 'video/mp4', 'image/jpeg', 'application/pdf'). The presigned URL will enforce this content type during upload. Used to validate compatibility with bucket schema if create_object_on_confirm=true.

Examples:

"video/mp4"

"image/jpeg"

"image/png"

"application/pdf"

"text/plain"

file_size_bytes
integer | null

Expected file size in bytes. OPTIONAL but RECOMMENDED. If provided, will be validated against: 1. Tier-based file size limits (100MB free, 5GB pro, 50GB enterprise) 2. Storage quota availability 3. Actual uploaded file size during confirmation. If not provided, quota checking is skipped until confirmation.

Required range: x >= 1
Examples:

10485760

104857600

presigned_url_expiration
integer
default:3600

How long the presigned URL is valid, in seconds. OPTIONAL, defaults to 3600 (1 hour). Valid range: 60 seconds (1 minute) to 86400 seconds (24 hours). After expiration, the URL cannot be used and you must request a new one. Recommendation: Use shorter expiration (300-900 seconds) for security-sensitive files, longer expiration (3600-7200 seconds) for large files that take time to upload.

Required range: 60 <= x <= 86400
Examples:

3600

7200

900

metadata
object

Custom metadata for tracking purposes. OPTIONAL. Stored with the upload record for filtering and analytics. Does NOT affect the created bucket object (use object_metadata for that). Common uses: campaign tracking, user identification, upload source.

Examples:
{
"campaign": "summer_2024",
"source": "mobile_app",
"user_id": "user_123"
}
{
"department": "marketing",
"priority": "high"
}
create_object_on_confirm
boolean
default:false

Whether to automatically create a bucket object when upload is confirmed. OPTIONAL, defaults to false. If true: - Bucket MUST have a schema defined - blob_property must exist in bucket schema - content_type must match schema field type - Validation happens BEFORE generating presigned URL. If false: - Upload is confirmed but no object is created - You can manually create the object later using the S3 URL.

object_metadata
object | null

Metadata to attach to the created bucket object. OPTIONAL. Only used if create_object_on_confirm=true. This metadata will be: 1. Validated against bucket schema (if keys match schema fields) 2. Attached to the bucket object 3. Passed to downstream documents in connected collections. Example: {'priority': 'high', 'category': 'products', 'tags': ['featured']}

Examples:
{
"category": "products",
"priority": "high"
}
{
"campaign": "q4_2024",
"status": "draft",
"tags": ["review", "featured"]
}
blob_property
string | null

Property name for the blob in the bucket object. OPTIONAL. Defaults to filename without extension (e.g., 'product_video.mp4' → 'product_video'). If create_object_on_confirm=true: - Must exist in bucket schema - Must be alphanumeric with underscores only - Will be validated BEFORE generating presigned URL. Common values: 'video', 'image', 'thumbnail', 'transcript', 'content'.

Examples:

"video"

"thumbnail"

"transcript"

"content"

blob_type
string | null

Type of blob. OPTIONAL. Defaults to type derived from content_type (e.g., 'video/mp4' → 'VIDEO'). Must be a valid BucketSchemaFieldType if provided. Valid values: IMAGE, VIDEO, AUDIO, TEXT, PDF, DOCUMENT, etc. If create_object_on_confirm=true, will be validated against bucket schema field type.

Examples:

"VIDEO"

"IMAGE"

"AUDIO"

"TEXT"

"PDF"

file_hash
string | null

SHA256 hash of the file content for duplicate detection. OPTIONAL. If provided: - System checks for existing confirmed uploads with same hash - If duplicate found and skip_duplicates=true, returns existing upload - Hash will be validated against actual S3 ETag during confirmation. If not provided: - Hash is calculated from S3 ETag after upload - Duplicate detection only happens during confirmation. Use case: Pre-calculate hash client-side to avoid uploading duplicates. Format: 64-character hexadecimal string (SHA256).

Required string length: 64
Examples:

"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"

skip_duplicates
boolean
default:true

Skip upload if a file with the same hash already exists. OPTIONAL, defaults to TRUE. If true (default): - If file_hash provided: System checks MongoDB for existing completed upload with same hash - If duplicate found: Returns existing upload details WITHOUT generating new presigned URL - If file_hash NOT provided: Duplicate check happens during confirmation using S3 ETag - Saves bandwidth, storage, and upload time by reusing existing files. If false: - Always generates new presigned URL even if file already uploaded - Creates separate upload record for same file content - Useful when you need distinct upload tracking for identical files. Recommendation: Keep default (true) unless you specifically need multiple upload records for same file.

Response

Successful Response

Response containing presigned URL and upload tracking information.

This response includes everything needed to:

  1. Upload your file to S3 using the presigned_url
  2. Track the upload status using upload_id
  3. Confirm the upload using the confirmation endpoint

The presigned_url is time-limited and specific to this upload. After uploading to S3, call POST /v1/buckets/{bucket_id}/uploads/{upload_id}/confirm.

upload_id
string
required

Unique identifier for this upload. Auto-generated.

Use this ID to: - Check status: GET /v1/uploads/{upload_id} - Confirm upload: POST /v1/uploads/{upload_id}/confirm - Cancel upload: DELETE /v1/uploads/{upload_id} - Reference in object creation: POST /v1/buckets/{bucket_id}/objects with 'upload_id' in blobs

⚠️ ADVANCED: Reference upload_id in object creation to: - Combine multiple uploads into one object - Upload files in parallel, create object later - Reuse same upload across multiple objects

Example: POST /v1/buckets/{id}/objects { 'blobs': [{'property': 'video', 'type': 'VIDEO', 'upload_id': 'upl_abc123'}] }

Format: 'upl_' followed by 12 random characters.

Examples:

"upl_a1b2c3d4e5f6"

"upl_x9y8z7w6v5u4"

bucket_id
string
required

Target bucket ID where object will be created

Examples:

"bkt_abc123"

filename
string
required

Name of the file to upload

Examples:

"product_video.mp4"

content_type
string
required

MIME type enforced by the presigned URL

Examples:

"video/mp4"

presigned_url_expiration
integer
required

How long the presigned URL is valid, in seconds

Examples:

3600

s3_key
string
required

Full S3 object key where the file will be stored. Format: {internal_id}/{namespace_id}/api_buckets_uploads_create/{upload_id}/{filename}. Used internally for verification and object creation.

Examples:

"int_xyz/ns_abc/api_buckets_uploads_create/upl_123/video.mp4"

status
enum<string>
required

Current upload status. After creation, always PENDING. Possible statuses: PENDING → IN_PROGRESS → PROCESSING → COMPLETED/FAILED/CANCELED

Available options:
PENDING,
IN_PROGRESS,
PROCESSING,
COMPLETED,
FAILED,
CANCELED,
UNKNOWN,
SKIPPED,
DRAFT,
ACTIVE,
ARCHIVED,
SUSPENDED
create_object_on_confirm
boolean
required

Whether bucket object will be auto-created on confirmation

created_at
string<date-time>
required

When this upload record was created (ISO 8601 format)

Examples:

"2024-01-15T10:30:00Z"

expires_at
string<date-time>
required

When the presigned URL expires (ISO 8601 format). After this time: - The presigned URL cannot be used - Upload status will be marked as FAILED if not completed - The upload record will be auto-deleted 30 days later (MongoDB TTL)

Examples:

"2024-01-15T11:30:00Z"

file_size_bytes
integer | null

Expected file size in bytes if provided in request. Will be validated during confirmation.

Examples:

10485760

presigned_url
string<uri> | null

Time-limited HTTPS URL for uploading directly to S3. Use HTTP PUT with the file content to upload: curl -X PUT '{presigned_url}' -H 'Content-Type: {content_type}' --upload-file {filename} The URL includes authentication and expires after presigned_url_expiration seconds. After successful upload, S3 returns an ETag header - save this for confirmation. NOTE: This will be null if is_duplicate=true (duplicate found, no upload needed).

Required string length: 1 - 2083
metadata
object

Custom metadata for tracking

object_metadata
object | null

Metadata for the bucket object (if create_object_on_confirm=true)

blob_property
string | null

Property name for the blob in bucket object

blob_type
string | null

Type of blob (IMAGE, VIDEO, etc.)

file_hash
string | null

SHA256 hash of the file content. Set during confirmation from S3 metadata or provided in request. Used for duplicate detection.

Examples:

"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

skip_duplicates
boolean
default:true

Whether duplicate detection was enabled for this upload

is_duplicate
boolean
default:false

Whether this upload was identified as a duplicate of an existing file. If true: - duplicate_of_upload_id contains the original upload - presigned_url will be null (no upload needed) - You can use the original upload's S3 object. This saves bandwidth and storage costs.

duplicate_of_upload_id
string | null

If skip_duplicates=true and duplicate found, this is the original upload_id. The response will reference the existing upload instead of creating a new one.

Examples:

"upl_original123"

message
string | null

Human-readable message about the upload. Provided when is_duplicate=true or other special conditions. Example: 'File already exists with the same content hash. No upload needed - returning existing upload.'

completed_at
string<date-time> | null

When the upload was completed and verified (ISO 8601 format)

Examples:

"2024-01-15T10:35:00Z"

verified_at
string<date-time> | null

When S3 object existence was verified (ISO 8601 format)

Examples:

"2024-01-15T10:35:00Z"

etag
string | null

S3 ETag from the uploaded object (set during confirmation)

Examples:

"d41d8cd98f00b204e9800998ecf8427e"

object_id
string | null

Created bucket object ID (if create_object_on_confirm was true)

Examples:

"obj_a1b2c3d4e5f6"

task_id
string | null

Celery task ID for async confirmation (if processed asynchronously)

Examples:

"task_abc123"