> ## Documentation Index
> Fetch the complete documentation index at: https://docs.convertly.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Library metadata and search

> Tags, taxonomy, AI auto-tagging, faceted library search, and contributor tagging in Convertly HDAM.

Convertly HDAM stores **library metadata** on each file: tags, description, dedicated alt text and captions, rights information, and workspace-defined custom metadata. Metadata powers dashboard search, public faceted search APIs, and CDN delivery identifiers (file id and slug).

## Metadata fields

| Field         | Purpose                          | Limits                                                                   |
| ------------- | -------------------------------- | ------------------------------------------------------------------------ |
| `tags`        | Searchable asset labels          | Up to 50 tags, 80 characters each                                        |
| `description` | Long-form asset description      | Up to 5,000 characters                                                   |
| `cdnSlug`     | Readable CDN delivery identifier | Unique per workspace; see [URL structure](/docs/image-cdn/url-structure) |

## Custom metadata, rights, and alt text

**Custom metadata** in Convertly is the **Custom metadata** section of the asset Metadata tab. Define reusable workspace fields such as campaign ID, photographer, product SKU, approval status, or publishing date, choose a field type, and then assign values independently on each asset.

Supported field types are `text`, `long_text`, `number`, `date`, `boolean`, `url`, `single_select`, and `multi_select`. Values are validated against their workspace field definition. Dedicated alt text, captions, and rights fields are kept separate from custom fields so accessibility and licensing information retain consistent semantics across integrations.

Retrieve the full asset record with a `files:read` API key:

```bash theme={"system"}
curl "https://convertly.sh/api/files/$FILE_ID/asset-details" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY"
```

The response contains:

* `governance`: alt-text treatment, alt text, caption, rights, and custom field values
* `fields`: the workspace custom-metadata definitions needed to interpret `customFields`
* `usage`: 30-day and tracked-lifetime origin requests and generated bytes
* `collections`: available collections and whether this asset belongs to each one
* `relationships`: source, derivative, variant, companion, and related-asset links

Update values with a `files:write` key:

```bash theme={"system"}
curl -X PATCH "https://convertly.sh/api/files/$FILE_ID/asset-details" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "altTextMode": "informative",
    "altText": "Blue product bottle on a stone plinth",
    "caption": "Spring campaign hero",
    "rights": {
      "copyrightNotice": "© Example Studio",
      "creator": "Example Studio",
      "creditLine": "Photo: Example Studio",
      "licenseUrl": "https://example.com/license",
      "usageTerms": "Digital channels only",
      "expiresAt": "2027-01-31",
      "territory": "Worldwide"
    },
    "customFields": {
      "86ddb637-cbd6-49cd-8503-a2bb672289ab": "SPRING-27"
    }
  }'
```

Create a reusable custom field through the same endpoint:

```bash theme={"system"}
curl -X POST "https://convertly.sh/api/files/$FILE_ID/asset-details" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create_field",
    "label": "Campaign ID",
    "fieldType": "text",
    "required": false,
    "options": []
  }'
```

## Asset usage and relationships API

Asset usage is returned by `GET /api/files/{id}/asset-details`. Convertly stores daily aggregates rather than visitor-level request logs. Per-asset figures count requests that reached Convertly processing and generated response bytes; browser and edge-cache hits are not attributed to an individual asset.

Create a relationship after finding the target with `GET /api/files/search?q=...`:

```bash theme={"system"}
curl -X POST "https://convertly.sh/api/files/$FILE_ID/asset-details" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "add_relationship",
    "targetFileId": "b3239c44-f1a1-4df2-bf45-e72bad94ea8b",
    "relationType": "derivative"
  }'
```

Remove it by sending `{"action":"remove_relationship","relationshipId":"..."}`. Relationship targets are checked against the same workspace; cross-workspace links are rejected by both the API and database policy.

Update metadata with `PATCH /api/files/{id}` or the SDK:

```ts theme={"system"}
await convertly.storage.files.update(fileId, {
  description: "Golden-hour editorial portrait",
  tags: ["sunset", "editorial", "vertical"],
});
```

Tags submitted through the API are normalized against your workspace **taxonomy** when present (synonyms resolve to canonical labels).

## AI auto-tagging (SDK one-liner)

Generate searchable tags with Forma AI and persist them on the file in one call:

```ts theme={"system"}
const result = await convertly.ai.tagFile(fileId, {
  maxTags: 8,
  merge: true,
  locale: "en",
});

console.log(result.tags, result.addedTags, result.summary);
```

REST equivalent:

```bash theme={"system"}
curl -X POST "https://convertly.sh/api/files/{id}/ai-tags" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "maxTags": 8, "merge": true, "locale": "en" }'
```

| Option    | Default | Description                                    |
| --------- | ------- | ---------------------------------------------- |
| `maxTags` | `8`     | Maximum tags returned from the model (1–20).   |
| `merge`   | `true`  | Merge with existing tags instead of replacing. |
| `locale`  | `en`    | Taxonomy locale used when canonicalizing tags. |
| `prompt`  | —       | Optional override for the tagging instruction. |

Auto-tagging is available for **images up to 25 MB** and consumes [Forma AI quota](/docs/ai-tools). Supported image tags are embedded back into the file when the format allows.

<Note>
  `POST /api/files/{id}/auto-tags` remains available for dashboard compatibility. Prefer **`/ai-tags`** for new integrations.
</Note>

## Faceted library search

Search the main workspace library with combined text query, tag filters, orientation, mime type, and optional facet counts — for example **sunset + vertical + editorial**:

```ts theme={"system"}
const { files, facets, applied } = await convertly.storage.files.search({
  q: "sunset",
  tags: ["editorial", "vertical"],
  tagMode: "all",
  orientation: "vertical",
  facets: ["tags", "orientation"],
  locale: "en",
  limit: 24,
});
```

REST:

```bash theme={"system"}
curl "https://convertly.sh/api/files/search?q=sunset&tags=editorial,vertical&tagMode=all&orientation=vertical&facets=tags,orientation&locale=en" \
  -H "Authorization: Bearer $CONVERTLY_API_KEY"
```

| Query param   | Description                                                        |
| ------------- | ------------------------------------------------------------------ |
| `q`           | Free-text search across filename, slug, description, and tags.     |
| `tags`        | Comma-separated tag list.                                          |
| `tagMode`     | `any` (default) or `all` — require every tag vs match any.         |
| `orientation` | `vertical`, `horizontal`, or `square` (derived from width/height). |
| `folderId`    | Restrict to a folder; use `null` for root only.                    |
| `mimePrefix`  | e.g. `image/` or `video/mp4`.                                      |
| `facets`      | Comma-separated: `tags`, `orientation`, `mimeType`.                |
| `locale`      | Taxonomy locale for synonym resolution and facet labels.           |

Faceted search applies to the **main workspace library** (not WordPress isolated buckets). Isolated site tokens should use `GET /api/files` with `q` for scoped listing.

## Taxonomy, synonyms, and locales

Define a controlled vocabulary per workspace and locale. Synonyms map contributor input (`"portrait"`) to canonical slugs (`portrait-orientation`) used in search filters.

```ts theme={"system"}
const { terms } = await convertly.library.taxonomy.list({ locale: "en" });

await convertly.library.taxonomy.create({
  slug: "editorial",
  label: "Editorial",
  groupName: "Style",
  synonyms: ["magazine", "editorial-style"],
  locale: "en",
});
```

| Method   | Endpoint                                |
| -------- | --------------------------------------- |
| `GET`    | `/api/library/taxonomy/terms?locale=en` |
| `POST`   | `/api/library/taxonomy/terms`           |
| `PATCH`  | `/api/library/taxonomy/terms/{id}`      |
| `DELETE` | `/api/library/taxonomy/terms/{id}`      |

Each term is scoped to a workspace and locale. Duplicate slugs per locale return `409`. AI auto-tagging and manual tag updates canonicalize against the active locale taxonomy when available.

## Contributor tag UI (dashboard)

Contributors do **not** need a separate tagging product — the dashboard already exposes metadata editing in the **Assets lightbox**:

1. Open any file in **Assets** and expand the info sidebar.
2. Edit **Tags** inline (type and press Enter, or remove with the chip control).
3. Use **Auto tags** on images to run the same AI pipeline as `convertly.ai.tagFile`, then review and save.

The lightbox uses the same `PATCH /api/files/{id}` metadata path as the API. Taxonomy canonicalization applies on save when terms exist for the workspace locale.

For stock or contributor portals you build on top of Convertly, wire your UI to:

* `convertly.storage.files.update(id, { tags })` for manual tagging
* `convertly.ai.tagFile(id)` for AI suggestions
* `convertly.storage.files.search({ tags, tagMode: "all" })` for public browse pages

<Card title="Files and storage" icon="database" href="/docs/files-and-storage">
  Uploads, folders, CDN slugs, and storage limits.
</Card>

<Card title="JavaScript SDK" icon="code" href="/docs/sdk">
  `convertly.ai`, `convertly.storage.files.search`, and taxonomy helpers.
</Card>
