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

AI enrichment

Every file admitted to the library is analyzed. That analysis is what separates the library from a folder with a search box: it is why you can ask for photos that look like this one, photos good enough to print, or photos of a person whose name nobody typed in.

This page covers what analysis produces, how to re-run and customize it, and the three searches that depend on it.

What analysis writes

Analysis runs after finalize and lands in the file's file_metadata.analysis. Reading a file once it is ready gets you all of it:

Code
{ "file_id": "8a1b6e5c-…", "file_status": "ready", "file_metadata": { "faceCount": 3, "analysis": { "title": "Product demo at trade show", "description": "Specialist demonstrating a device to two visitors", "retrieval_description": "A product specialist demonstrates a handheld device to two visitors at a branded booth on a trade show floor, company logo on the back wall…", "environment": { "setting": { "item": "Trade show floor", "confidence": 96 }, "venue_type": { "item": "Conference center", "confidence": 93 }, "weather": { "item": "Not applicable (indoors)", "confidence": 99 }, "background_quality": { "item": "Clean and Professional", "confidence": 88 } }, "people": { "individuals": [ { "description": "Product specialist in a branded polo", "estimated_age": 34, "gender": "Female", "role": "Employee", "mood_emotion": "Engaged" } ], "group_size": { "item": "Small Group (2-3 people)", "confidence": 90 } }, "marketing_suitability": { "channel_suitability": [{ "item": "Website", "confidence": 92 }], "target_audience": { "item": "B2B", "confidence": 87 }, "marketing_appeal": { "item": "High", "confidence": 84 } }, "photo_quality": { "focus_sharpness": 5, "exposure": 4, "overall_score": 4.3 }, "tags": ["trade show", "product demo"], "flags": [], "mediaTags": { "campaign": ["product launch"] }, "nudges": [ { "title": "Remove background clutter", "user_prompt": "Remove the distracting signage behind the booth while keeping the subjects intact…" } ] } } }

The fields that matter most:

title, descriptionShort and human-facing. Written for a caption rather than for search.
retrieval_descriptionThe long form, written to be searched. This is what the embedding is built from.
environmentWhere the shot was taken (setting, venue type, background quality), each with a confidence percentage.
people.individualsOne entry per clearly visible person, with estimated age, gender, role and mood. Blurry and background people are deliberately omitted.
marketing_suitabilityWhich channels the shot suits, the audience it reads to, and its overall appeal.
photo_qualityFourteen scores from 1 to 5: exposure, sharpness, framing, storytelling and the rest, plus an overall_score that may carry one decimal.
tags, flags, mediaTagsControlled vocabulary. See below.
nudgesSuggested edits, each with a ready-to-send prompt.

Almost everything here is filterable. See the analysis filters.

Your controlled vocabulary

tags, flags and mediaTags are not free text. The model may use only values from your knowledge bases: the Media Tags and Flags sets, plus the ones your product uses. Invented values are rejected rather than stored.

The consequence is worth knowing: editing a knowledge base changes how every future upload is described. If the analysis is not using your terminology, correct the vocabulary rather than the prompt.

Re-run analysis

Re-run analysis when the vocabulary changed, a schema changed, or the file arrived before either existed:

TerminalCode
# one file curl -X POST https://api.genuineai.app/api/v1/files/<file-id>/reanalyze \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" # many curl -X POST https://api.genuineai.app/api/v1/files/actions/reanalyze \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -H "Content-Type: application/json" \ -d '{"file_ids": ["8a1b6e5c-…", "3f2a9c1e-…"]}'

Re-analysis runs a model on every file you name. It consumes credits and counts against the expensive rate-limit tier. Re-analyzing a whole library is expensive, so filter to the files that need it and check GET /me for your remaining credits first.

Analysis is asynchronous, exactly like the first pass. The file returns to pending and reaches ready again when it finishes.

To correct analysis by hand rather than re-running it, PUT /files/{id}/analysis merges a partial analysis object into what is already there. Use it to fix one incorrect field without paying to redo the rest.

Custom analysis schemas

The standard analysis answers a general set of questions. A schema adds your own: fields the platform has no way to infer, such as a product SKU or a shot type. Schemas live at /media-analysis-schemas and require the module-custom-analysis entitlement.

Test one before committing to it:

TerminalCode
curl -X POST https://api.genuineai.app/api/v1/files/<file-id>/analyze-preview \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -H "Content-Type: application/json" \ -d '{"form_id": "3f2a9c1e-…"}'

This is a dry run: it shows what the schema would produce and writes nothing. Iterate on the schema against a handful of representative files, then re-analyze in bulk once the schema is right.

Schema output is filterable through custom:

Code
GET /media-files?repo_type=media&custom={"shot_type":["hero"]}

Core fields (photo_quality, tags, flags and the rest listed above) are never redefined by a schema, so a schema can only add fields.

Documents

Documents get text extraction rather than a visual analysis. The platform extracts a markdown rendition of the file, which is what search indexes and what agents retrieve against when the file backs a knowledge base. The platform maintains the rendition, and re-running analysis re-extracts it.

Search by meaning

Analysis produces embeddings from retrieval_description, and three searches run on them.

Text to image

Describe what you want rather than what it is called:

Matching rows carry a similarity score and come back ordered by it. similarityThreshold moves the cutoff: raise it for precision, lower it for recall. It combines with every other filter, so "photos similar to this, from this album, rated 4 or better" is a single request.

Similar images

Code
GET /files/{id}/similar?limit=12

Compares stored embeddings against one seed file. It returns up to 24 results, 6 by default, and only files above a fixed similarity floor.

An empty array is a normal answer. It means one of three things: the seed's analysis has not finished, the seed is a generated image (which never gets an embedding), or nothing in the library is close enough. Do not treat it as an error.

Find this face

This takes two calls. First, post an image to get the face's embedding. The request is multipart/form-data rather than JSON, and the field is image:

Then pass it to the library as face_embedding:

Code
GET /media-files?repo_type=media&face_embedding=[0.021,-0.118,…]&face_threshold=0.9

Matching rows carry face_similarity. A lower face_threshold is stricter, because the value is a distance rather than a score.

Two constraints apply: the image must contain a detectable face or the first call returns 400, and the upload is capped at 10 MB and images only. Blurry unassigned faces are skipped during matching, so a face search will not surface photos where the person is an unrecognizable smudge in the background.

To find someone you have already named, face_person is cheaper and exact. See people and faces.

One-shot AI helpers

Four endpoints run a model and answer immediately, with no thread and no agent. All of them consume credits and count against the expensive tier.

POST /assist/photo-selectorPicks the best photos for a stated purpose. Takes a query, optional criteria and a minQuality floor. It reads photo_quality, so it will not hand back a technically poor shot.
POST /assist/captions-generatorSocial captions for a photo, by platform. Takes an image_file_id or a description.
POST /assist/magic-writeWrites or rewrites text from a brief, with optional tone and platform.
POST /assist/canvas-assistantDesign-surface assistance.

Use photo-selector when your integration needs "a good photo of X" rather than a list to page through: it does the query, the quality filter and the ranking in one call.

Next steps

  • People and faces turns detected faces into named people.
  • Organizing and finding assets lists the full filter vocabulary.
  • Agents and conversations covers knowledge bases, and asking questions in a thread.
Last modified on October 8, 2026
Publishing assetsPeople and faces
On this page
  • What analysis writes
    • Your controlled vocabulary
  • Re-run analysis
  • Custom analysis schemas
  • Documents
  • Search by meaning
    • Text to image
    • Similar images
    • Find this face
  • One-shot AI helpers
  • Next steps
JSON
curl -G "https://api.genuineai.app/api/v1/media-files" \ --data-urlencode "repo_type=media" \ --data-urlencode "embedding_search=candid moment between two colleagues" \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>"
curl -X POST https://api.genuineai.app/api/v1/files/face-search \ -H "X-Api-Key: gai_…" -H "X-Tenant-Id: <workspace-id>" \ -F "image=@face.jpg"