Assets API

The Assets API allows you to upload and manage images used across YouThumbAI. Assets are the foundation for face profiles and custom templates.

Asset Types

TypeDescriptionStored in DB
faceFace reference images for personsYes
templateStyle reference templatesYes
bucketTemporary file upload (no DB entry)No
The bucket type uploads files to temporary storage without creating a database entry. Useful for transient images needed during generation workflows.

List Assets

Lists your owned or organization-shared stored images, including unpublished uploads.
GET /api/assets

Query Parameters

ParameterTypeRequiredDefaultDescription
typestringNo-Filter by type: face, template, bucket
pagenumberNo1Page number
limitnumberNo20Items per page (max 100)
bash
# List all assets
curl https://youthumb.ai/api/assets \
  -H "x-api-key: your_api_key"

# List only face assets
curl "https://youthumb.ai/api/assets?type=face" \
  -H "x-api-key: your_api_key"

# Paginated
curl "https://youthumb.ai/api/assets?page=2&limit=10" \
  -H "x-api-key: your_api_key"

List Response

json
{
  "success": true,
  "data": {
    "assets": [
      {
        "id": "asset-uuid",
        "type": "face",
        "url": "https://...",
        "name": "photo.jpg",
        "description": "Front face photo",
        "mimeType": "image/jpeg",
        "size": 245000,
        "width": 1920,
        "height": 1080,
        "createdAt": "2024-01-15T10:30:00.000Z"
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 20
    }
  }
}

Upload Asset

Upload an image. Supports two modes: multipart/form-data and JSON (base64).
POST /api/assets

Mode 1: Multipart (FormData)

FieldTypeRequiredDescription
fileFileYesImage file (MIME must start with image/)
typestringYesface, template, or bucket
descriptionstringNoDescription
bash
curl -X POST https://youthumb.ai/api/assets \
  -H "x-api-key: your_api_key" \
  -F "file=@face-photo.jpg" \
  -F "type=face" \
  -F "description=Front face photo"

Mode 2: Base64 (JSON)

FieldTypeRequiredDefaultDescription
base64stringYes-Base64-encoded image (with or without data: prefix)
typestringYes-face, template, or bucket
filenamestringNoauto-generatedFilename
mimeTypestringNoimage/jpegimage/jpeg, image/png, image/webp, image/gif
descriptionstringNo-Description (max 500 chars)
bash
curl -X POST https://youthumb.ai/api/assets \
  -H "x-api-key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "base64": "data:image/jpeg;base64,/9j/4AAQ...",
    "type": "face",
    "filename": "my-face.jpg",
    "mimeType": "image/jpeg",
    "description": "Front face photo"
  }'

Upload Response

json
{
  "success": true,
  "data": {
    "id": "new-asset-uuid",
    "type": "face",
    "url": "https://...",
    "name": "my-face.jpg",
    "description": "Front face photo",
    "mimeType": "image/jpeg",
    "size": 245000,
    "width": 1920,
    "height": 1080,
    "createdAt": "2024-01-15T10:30:00.000Z"
  }
}
For bucket uploads, the response will have an empty id and null for width/height, since the file is stored temporarily without a database record.

Get Asset

Retrieve a specific asset by ID.
GET /api/assets/{id}
ParameterTypeDescription
idstring (UUID)Asset ID
bash
curl https://youthumb.ai/api/assets/asset-uuid \
  -H "x-api-key: your_api_key"

Get Response

json
{
  "success": true,
  "data": {
    "id": "asset-uuid",
    "type": "face",
    "url": "https://...",
    "name": "photo.jpg",
    "description": "Front face photo",
    "mimeType": "image/jpeg",
    "size": 245000,
    "width": 1920,
    "height": 1080,
    "createdAt": "2024-01-15T10:30:00.000Z"
  }
}

Delete Asset

Delete an asset by ID.
DELETE /api/assets/{id}
ParameterTypeDescription
idstring (UUID)Asset ID
bash
curl -X DELETE https://youthumb.ai/api/assets/asset-uuid \
  -H "x-api-key: your_api_key"

Delete Response

json
{
  "success": true,
  "data": {
    "message": "Asset deleted"
  }
}

Complete Example: JavaScript

javascript
const API = 'https://youthumb.ai/api';
const headers = {
  'x-api-key': process.env.YOUTHUMB_API_KEY,
  'Content-Type': 'application/json',
};

// Upload a face image (base64)
async function uploadFaceImage(base64Data, filename) {
  const response = await fetch(`${API}/assets`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      base64: base64Data,
      type: 'face',
      filename,
      mimeType: 'image/jpeg',
    }),
  });
  return response.json();
}

// List all face assets
async function listFaceAssets() {
  const response = await fetch(`${API}/assets?type=face`, { headers });
  return response.json();
}

// Upload face then create person
async function setupPerson(name, faceImages) {
  // 1. Upload all face images
  const uploadResults = await Promise.all(
    faceImages.map((img) => uploadFaceImage(img.base64, img.filename))
  );

  const imageIds = uploadResults.map((r) => r.data.id);

  // 2. Create person with uploaded images
  const person = await fetch(`${API}/persons`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ name, imageIds }),
  });

  return person.json();
}
Assets are the prerequisite for the Persons API. Upload face images as assets first, then pass their IDs when creating or updating a person.

Resources: persons, uploads and catalog

All resource operations use the connected identity. Stored assets must belong to the selected organization and be owned by you or shared with it. Imports stay unpublished and are still discoverable. Unknown or inaccessible IDs return 404; permission refusals return 403; invalid inputs return 400. MCP errors use isError: true. Management operations consume no credits.
RESTMCPInput / effect
PATCH /api/persons/:idupdate_personname? (1–100), description? (max 500); null clears description; at least one field
DELETE /api/persons/:iddelete_personDeletes profile and photo associations; stored images remain
DELETE /api/persons/:id/images/:imageIdremove_person_imageDetaches only this existing association, without deleting the asset
PUT /api/persons/:id/defaultset_default_personIdempotent organization default; existing owner permissions apply
GET /api/assets/:idget_assetAuthorized stored asset UUID
GET /api/templates/:idget_templatePublished catalog template or your own private template
MCP mutations require mcp:assets and active Images and persons access. Reads require mcp:read and active Read access. Tool arguments use personId, imageId, assetId or templateId instead of URL path parameters. Person reads/updates return the profile with images and imageCount; delete returns {"deleted":true}. Existing create/add-photo calls also validate every referenced image before writing.

Asset discovery

GET /api/assets / list_assets accepts type (face, template, bucket), search, isPublished, page (default 1), limit (default 20, max 100). Without type, stored face and template images are listed. Search matches name/description, and visibility/publication filters apply before pagination and count. Stored results include isPublished, ownerScope: "organization"; pagination returns page, limit, total, totalPages, hasMore. type=bucket lists the caller's personal temporary folder across organizations. Results include ownerScope: "user", id: "", stable fileKey, url and isFavorite. Use contentImages: [{"url": "RETURNED_URL"}] for generation; get_asset and userImageId require a persisted asset UUID, never a bucket file key. favorite=true selects starred files, favorite=false excludes them; omission includes both. search matches file names. Bucket-only sortBy=name|createdAt and sortOrder=asc|desc default to createdAt descending. Unknown or invalid dates remain createdAt: null and sort last in either direction; ties use fileKey ascending. These three bucket filters are rejected for other asset types; isPublished is invalid for bucket files. The service enumerates matching storage files in batches of 100, deduplicates by path and excludes non-images/placeholders before favorite filtering, sorting and public pagination. total is the filtered image count, totalPages = ceil(total / limit) and hasMore signals another page. Empty results have totals of 0; an out-of-range page is empty. Orphan favorites do not create assets. Every request enumerates the matching folder, so large folders cost more storage requests; concurrent changes are not an atomic snapshot. Any provider page failure fails the request rather than returning partial success. Temporary files cannot be deleted through /api/assets/:id. Example: GET /api/assets?type=bucket&search=logo&favorite=true&sortBy=createdAt&sortOrder=desc&page=1&limit=20 or MCP list_assets({"type":"bucket","search":"logo","favorite":true,"sortBy":"createdAt","sortOrder":"desc","page":1,"limit":20}).

Three reference namespaces

GET /api/templates / list_templates searches catalog title, description and tags with search. scope=public (default) lists published catalog templates; scope=mine lists only templates you created, published or private. isPublished=false requires scope=mine. Existing category, isFeatured, page, limit filters remain. Responses contain templates and pagination (page, limit, total, totalPages). A catalog UUID goes in templateId. An uploaded personal reference is found through list_assets(type="template"): use its URL as styleReferenceUrl, or its UUID as a content userImageId / prompt-assistance assetId. A temporary file uses its URL. Never interchange catalog IDs, asset IDs and file keys.
bash
curl "$BASE/api/assets?type=template&search=studio&page=1&limit=20" -H "x-api-key: $YOUTHUMB_API_KEY"
curl "$BASE/api/templates?scope=mine&isPublished=false&search=studio" -H "x-api-key: $YOUTHUMB_API_KEY"
curl -X PATCH "$BASE/api/persons/$PERSON_ID" -H "x-api-key: $YOUTHUMB_API_KEY" -H "Content-Type: application/json" -d '{"description":null}'