Skip to content

Media Library

Standalone media endpoints for bulk upload, moderation-first workflows, and n:m product linking.

Media items live in a creator's library independently of products. Products reference one or more media rows through the product_media pivot.


List media library

GET /api/media

Returns paginated media owned by the authenticated creator.

Authentication: Required

Query Parameters

ParameterTypeDescription
pageintegerPage number (default: 1)
limitintegerItems per page (default: 20, max: 100)
statusstringFilter by moderation status: pending, approved, rejected
folder_idintegerFilter by content folder
unlinkedbooleanWhen true, only media not linked to any product

Response (200)

json
{
  "success": true,
  "errors_message": null,
  "data": {
    "data": [
      {
        "id": 101,
        "type": "image",
        "title": "Beach photo",
        "description": null,
        "status": "pending",
        "preview": "https://...",
        "preview_blurred": "https://...",
        "source": "https://...",
        "folder_id": null,
        "folder": null,
        "product_ids": [],
        "is_linked": false,
        "created_at": "2026-06-10T10:00:00+00:00",
        "updated_at": "2026-06-10T10:00:00+00:00"
      }
    ],
    "current_page": 1,
    "last_page": 1,
    "per_page": 20,
    "total": 1
  }
}

Create media from upload session

POST /api/media

Creates a library media item from a finalized upload session without creating a product.

Authentication: Required

Request Body

json
{
  "upload_session_id": "01knyp9pd50ey9xrpgp1nv0jn0",
  "title": "Optional title",
  "description": "Optional description",
  "folder_id": 12
}

Response (201)

Returns a MediaLibraryResource object. Moderation runs on the media row (status: pending until approved).


Bulk upload sessions

POST /api/media/bulk

Starts multiple upload sessions with shared defaults. Use the returned session IDs with the normal upload session flow, then call POST /api/media per file after finalization.

Authentication: Required

Request Body

json
{
  "files": [
    {
      "file_name": "pic_01.jpg",
      "file_size_bytes": 2048000,
      "mime_type": "image/jpeg"
    },
    {
      "file_name": "pic_02.jpg",
      "file_size_bytes": 1800000,
      "mime_type": "image/jpeg"
    }
  ],
  "defaults": {
    "is_adult_content": true,
    "is_downloadable": false,
    "is_verif_age": false,
    "folder_id": 12
  }
}

Response (201)

json
{
  "success": true,
  "errors_message": null,
  "data": [
    { "upload_session_id": "01abc..." },
    { "upload_session_id": "01def..." }
  ]
}

Update media

PATCH /api/media/{media_id}

Edit title, description, or folder assignment on a library item.

Authentication: Required (owner only)

Request Body

json
{
  "title": "Updated title",
  "description": "Updated description",
  "folder_id": 12
}

Delete media

DELETE /api/media/{media_id}

Deletes a library item. Fails with 403 when the media is still linked to one or more products.


POST /api/products/{product_id}/media

Attach existing library media to a product (n:m).

Request Body

json
{
  "media_ids": [101, 102, 103]
}

DELETE /api/products/{product_id}/media/{media_id}

Removes the pivot link only. The media row remains in the library.


Create product from media library

POST /api/products

Accepts media_ids[] instead of uploading a new file:

json
{
  "media_ids": [101, 102, 103],
  "price": 1500,
  "title": "Summer Bundle",
  "is_adult_content": true,
  "is_downloadable": false
}

The legacy upload_session_id flow on POST /api/products remains supported as a compatibility shim.


Account upload defaults

PATCH /api/user/{user_id}

Store creator-level defaults used to pre-fill bulk uploads and product creation:

json
{
  "upload_defaults": {
    "is_adult_content": true,
    "is_downloadable": false,
    "is_verif_age": false,
    "default_price": 500,
    "folder_id": 12
  }
}

default_price is in cents (500 = $5.00). Returned on GET /api/user as upload_defaults.


Moderation

Moderation status is tracked on media rows (veriff_status), not on products. API status values map as:

API statusBackend states
pendingUnchecked
approvedChecked, Manual Approval
rejectedManual Removal, AI Removal

Purchasability still evaluates linked media on each product.

Fangate backend developer documentation