GenuineAIGenuineAI
For usersFor developers
  • Overview
  • Guides
  • How-to
  • API reference
Documentation
  • Quickstart
  • Authentication
  • Errors
  • Rate limits
  • API reference
Platform
  • Platform overview
  • Solutions
  • Pricing
  • Sign in
Company
  • Status
  • Trust Center
  • Contact
  • Terms of Service
  • Privacy Policy

© 2026 GenuineAI Ventures LLC

support@genuinehq.com
Media library
Uploading filesOrganizing and finding assetsDelivering assetsPublishing assets
AI
AI enrichmentPeople and facesAgents and conversations
Knowledge
Knowledge basesHow agents use knowledge
Automation
Autonomous AIExternal dataExtensions
Creating and deploying
Generating contentDeployed AI
Operations
Usage and credits
How-to

Organizing and finding assets

A library is only as useful as what you can retrieve from it. This page covers the querying half of the media library: the filters, the two endpoints that accept them, and how to save a query rather than rebuild it.

Two listing endpoints

They are not interchangeable, and picking the wrong one is a common early mistake:

EndpointFor
GET /filesAny repository. repo_type is required: files are always scoped to one, never listed across the workspace. Plain column filters: name, type, size, status, dates.
GET /media-filesThe media library (repo_type=media) or generated media (repo_type=generated). The full filter vocabulary below, each file's album membership, and semantic and face search.

For asset-management work, use GET /media-files. It returns album membership alongside each file rather than listing one album; that is af_album, one filter among many.

Repository parameters

repo_type names what kind of thing owns the files, and repo_id names which one:

repo_typerepo_idLists
media—The shared media library, what people uploaded. A library takes no id.
generated—What the platform produced: AI images and infographics, wherever they were made.
dsknowledge base idThe documents a knowledge base indexes.
threadconversation idWhat was attached to a conversation, and what was generated in it.
designdesign idA design's assets and rendered previews.
promptprompt idThe references attached to a saved prompt.

A file can sit in more than one repository at once, and either containment is readable: an image generated inside a conversation carries both generated and its thread, so it is returned by both listings.

Reading a repository means reading the object that owns it, so that object's access rules apply on top of each file's. Several repositories have their own collection, which is the more direct way to ask: GET /knowledge-bases/{id}/files, GET /threads/{id}/files, GET /designs/{id}/files.

Both endpoints answer with the standard collection envelope:

Code
{ "data": [ … ], "has_more": true, "next_cursor": "eyJzIjoi…" }

Each row in the media library adds file_albums: every album the file belongs to, resolved, so you do not need a second call to render membership:

Code
{ "file_id": "8a1b6e5c-…", "file_name": "harbor-sunset.jpg", "file_status": "ready", "file_albums": [ { "album_id": "3f2a9c1e-…", "album_name": "Summer campaign", "af_created": "2026-07-02T14:11:03Z" } ] }

The filter vocabulary

Filters combine with AND. Where a filter takes a list, the values inside it combine with OR, so tags=harbor&tags=sunset means "either tag", and adding orientation=Landscape narrows that to landscape files.

Core filters

Filter
searchFree text over the file name and, for generated images, the prompt that made them.
af_albumFiles in one album.
favorite=trueThe calling user's favorites. Favorites are per person, not per workspace.
fileTypeImage, Video, Audio or Document. Repeatable.
file_created, photoTakenDateTime ranges. photoTakenDate is when the photo was taken; file_created is when it arrived. They differ for anything imported from an archive.
file_state_itemFiles sitting at one state of your review workflow.
aiGeneratedWhether the platform generated the image.
excludeWorkflow=trueHides intermediate files produced by workflow runs.

Tags

Two systems, deliberately kept separate:

  • tags: what the AI identified. Free-form labels from analysis. Filter with tags=harbor&tags=boat.

  • mediaTags: what your organization defined. Structured groups you define, passed as a JSON object mapping group to values:

    Code
    GET /media-files?repo_type=media&mediaTags={"campaign":["summer-2026"],"usage":["print"]}

Write media tags with PUT /files/{id}/media-tags for one file, or POST /files/actions/set-media-tags for many. The bulk form merges by default and removes when you pass remove: true, and it reports what it actually changed:

Code
{ "successCount": 412, "totalRequested": 420 }

The difference is files you cannot write to. Compare the two numbers rather than treating a 200 as confirmation that all of them were updated.

Analysis filters

These read the AI's structured output, so they match only files that reached ready. See AI enrichment for what produces them.

Filter
flagsAnything the analysis flagged for attention. Repeatable.
photoRatingOverall quality score, 1 to 5, as a range: photoRating[0]=4&photoRating[1]=5.
peopleCountNumber of people in the shot, as a range.
gender, role, ageAttributes of the people in the shot. age is a range.
orientationPortrait or Landscape, computed from EXIF dimensions.
dpiPixel density range, the filter for whether a file is good enough to print.
customFields from your own analysis schemas, as {"field":["value"]}.

Faces

Filter
has_faces=trueAny photo containing a countable face.
face_personPhotos containing one named person.
face_embeddingPhotos containing a face resembling one you supply. See people and faces.

Meaning

embedding_search searches by what an image is of rather than what it is called, and works on files whose analysis has produced embeddings:

Code
GET /media-files?repo_type=media&embedding_search=boats%20at%20golden%20hour

Matching rows carry a similarity score, and results are ordered by it. similarityThreshold tightens or loosens the cutoff. AI enrichment covers this in full.

Ranges

Range filters take two values, either repeated (age=25&age=40) or as {"min":25,"max":40}. Both ends are inclusive and both are required; there is no open-ended form.

Albums

Manual albums are explicit lists. Create one, then add and remove files:

Adding is idempotent and reports the result:

Code
{ "added": 18, "skipped": 2, "missing": 0 }

skipped counts files already in the album, and missing counts files that do not exist or are not visible to you. Re-sending the same list is safe.

You can also skip this step entirely: album_ids on the upload request files a file at the moment it is created.

Smart albums are a saved filter rather than a list. Their contents are whatever currently matches, so files join and leave automatically:

TerminalCode
curl -X POST https://api.genuineai.app/api/v1/albums/smart \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -H "Content-Type: application/json" \ -d '{ "album_name": "Print-ready harbor shots", "query_search": { "tags": ["harbor"], "dpi": {"min": 300, "max": 1200}, "photoRating": {"min": 4, "max": 5} } }'

query_search is the same filter object you would have sent as query parameters. PATCH /albums/{id}/smart changes it later, and reading a smart album returns the filter as album_query_search so you can show people what it selects on.

Albums nest through album_parent, and GET /albums?album_parent=<id> walks one level.

A smart album is how you save a filter. There is no separate saved-search resource on this surface: to keep a query, save it as a smart album and read it back as one.

Bulk actions

Three bulk endpoints take a file_ids array and apply one change:

POST /files/actions/set-media-tagsAdd or remove media tags.
POST /files/actions/transitionMove files to a target_state_id in the media status flow.
POST /files/actions/reanalyzeRe-run AI analysis. Consumes credits.

Each skips files you cannot write to rather than failing the batch, and each reports counts. Most housekeeping integrations combine a filtered list with one of these actions: query for what is wrong, then hand the ids to the action.

Sorting and paging

sort=-file_created is newest first, and sort=file_name is A to Z. The media library adds a deterministic tiebreaker of its own, so equal sort values do not reshuffle between pages and infinite scroll does not show duplicates.

Page with cursor rather than offset (see pagination). Media libraries are exactly the case cursors exist for: a deep offset gets slower the further in you go.

Next steps

  • AI enrichment explains what fills in the analysis filters above.
  • People and faces covers the face filters, and naming who is in a photo.
  • Delivering assets is how you get the files you found back out.
Last modified on October 8, 2026
Uploading filesDelivering assets
On this page
  • Two listing endpoints
    • Repository parameters
  • The filter vocabulary
    • Core filters
    • Tags
    • Analysis filters
    • Faces
    • Meaning
    • Ranges
  • Albums
  • Bulk actions
  • Sorting and paging
  • Next steps
JSON
JSON
JSON
curl -X POST https://api.genuineai.app/api/v1/albums \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -H "Content-Type: application/json" \ -d '{"album_name": "Summer campaign"}' curl -X POST https://api.genuineai.app/api/v1/albums/<album-id>/files \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -H "Content-Type: application/json" \ -d '{"file_ids": ["8a1b6e5c-…", "3f2a9c1e-…"]}'
JSON