---
title: "Search Assets"
method: GET
path: "/assets/search"
tags: ["canvas-actions"]
---

# Search Assets

`GET /assets/search`

## Request

- Base URL: `https://api.moda.app/v1`
- URL: `https://api.moda.app/v1/assets/search`
- Auth: HTTP bearer

Stateless asset search returning refs that are directly usable in writes.

Team lane (``source=team``): the same ``FileSearchService`` hybrid search
the agent's ``search_assets`` tool uses, WITHOUT the agent-state ``img_``
ref formatter — results address assets by durable ``file_`` wire ids plus
proxy URLs.

Stock lane (``kind=photo&source=stock``): Unsplash. Each result carries a
``stock_unsplash_<photo id>`` id that is itself a usable ref — place it in
markup (``<image src="stock_unsplash_…"/>``) or an edit program and the
write pre-pass IMPORTS the photo into this team's storage (once per photo)
and points the node at the resulting durable Moda asset URL, reporting the
download to Unsplash at that moment. ``url``/``thumb_url`` here are Unsplash
CDN links for PREVIEW only — hotlink them to display results, never re-host
them or write them into a canvas — and ``attribution`` must be shown
wherever the photo appears.

The stock lane also returns ``provider_status``: ``"ok"``, or
``"unavailable"`` when stock search is not configured on this deployment (an
empty ``assets`` list then means "could not search", not "no matches").

Pagination (both lanes): at most ``limit`` results per page; advance by the
response's echoed ``limit`` while ``has_more`` is ``true`` (``offset =
offset + limit``). Team lane: ``total`` is the relevance-ranked result
count above the search's elbow cutoff — the search scores a bounded
candidate window (200), so ``total`` is exact within that window and the
collection is fully drainable through it. Stock lane: Unsplash pages
underneath, so the echoed ``limit`` is capped at the provider's 30-per-page
ceiling, ``offset`` must be a multiple of it, and ``total`` is the
provider-reported match count.

## Query parameters

- `q` string, required: Search query.
- `kind` 'icon' | 'photo': icon = Phosphor packs; photo = team gallery.
- `source` 'team' | 'stock': Where to search. 'team' (default) = this team's own assets. 'photo' + 'stock' searches the Unsplash stock library. Ignored for kind='icon': the icon packs ARE the stock icon library (public Phosphor packs, shared with every team), so there is no separate stock icon source.
- `limit` integer: Max results per page. Defaults to 20, caps at 50.
- `offset` integer: Results to skip — pass ``offset + limit`` (the response's echoed ``limit``) to page through.

## Headers

- `Moda-Version` '2026-04-12' | '2026-05-01'

## Response `200`

Successful Response

- object

## Other responses

- `401`: Authentication required.
- `402`: Insufficient credits for a metered operation.
- `403`: Permission denied for this scope.
- `404`: Resource not found.
- `409`: Conflict (idempotency / resource state).
- `422`: Request validation failed.
- `429`: Rate limit exceeded.
- `500`: Internal error.

## Changes

- **2026-11-03** `9ac6a3abc0f8`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/moda/apis/moda-public-api/changes/assets/search/get.md)

---

[API](https://skmtc.dev/moda/apis/moda-public-api.md) - [All operations](https://skmtc.dev/moda/apis/moda-public-api/llms.txt) - [OpenAPI document](https://skmtc.dev/moda/apis/moda-public-api/revisions/9ac6a3abc0f8?raw)
