Catalog · GET /images

Search & list images

GET https://epochalstock.com/api/v1/images is the primary discovery endpoint for design apps. Combine free-text search across title, description, and tags with up to twenty normalized tag filters, choose how tags combine, pick a stable sort order, and page through results with opaque cursors.

Overview

Without query parameters the endpoint returns a page of recent catalog entries (default sort newest, default limit 30). Adding q switches the default sort to relevance so text matches rank highest. Every call counts as one authenticated request toward the shared 30 requests/minute account limit.

Text search

q matches title, description, and tags (max 200 characters).

Tag filters

Up to 20 comma-separated normalized tags with all or any logic.

Stable paging

Pass next_cursor unchanged. Never decode or invent cursors.

Rich page payload

Response includes images, total, limit, next_cursor, and filters.

Requires a valid Bearer key. See Authentication if you are still wiring headers.

Parameter reference

All parameters are optional query-string fields on GET /images.

Parameter Type Default Description
q string empty Full-text style search over title, description, and tags. Maximum 200 characters. Excess length returns a validation error.
tags comma-separated strings empty Up to 20 normalized tags (for example nature,trees,gold). Prefer tags discovered via GET /tags.
tag_mode all | any all Whether every listed tag is required (all) or at least one tag is enough (any).
sort relevance | newest | oldest relevance when q is set; otherwise newest Stable result order for the current filter set. Use with consistent paging.
limit integer 1–100 30 Number of images returned on this page. Larger pages use fewer requests for bulk browse UIs.
cursor string empty Opaque token from the previous response’s next_cursor. Omit on the first page.

Tag mode: all vs any

When you pass multiple tags, tag_mode controls how they combine. The default all is best for precise design-tool filters; any widens the set for exploratory browsing.

Default

tag_mode=all

An image must include every listed tag.

tags=nature,trees&tag_mode=all

Matches only assets tagged with both nature and trees. Ideal for “narrow the catalog” UI chips where users stack constraints.

Broad

tag_mode=any

An image must include at least one listed tag.

tags=gold,metal,blue&tag_mode=any

Matches assets tagged with gold or metal or blue. Useful for mood boards and multi-theme pickers.

Combine carefully with q. Text search and tag filters apply together. A tight all tag set plus a specific q can return zero hits even when each filter alone would succeed—surface “clear filters” in your UI.

Sort modes

Mode When to use Notes
relevance Keyword search, natural-language prompts, typeahead results. Default whenever q is non-empty. Best ranking for text matches.
newest Browse feeds, “latest arrivals”, admin review queues. Default when q is omitted. Chronological recency.
oldest Archive sweeps, backfill jobs, deterministic full scans. Pair with cursor paging to walk the catalog from earliest entries.

Keep sort (and all other filters) identical across pages of the same result set. Changing sort mid-cursor produces undefined ordering relative to the previous page.

Cursor pagination

List responses may include next_cursor. When it is present and non-null, pass it as the next request’s cursor query parameter—byte-for-byte, without decoding, re-encoding, or constructing your own tokens. When next_cursor is null or absent, you have reached the end of the filtered set.

  • Do not decode, parse, or invent cursors—they are opaque server tokens.
  • Replay the same q, tags, tag_mode, sort, and limit on every page.
  • Invalid or expired cursors return invalid_cursor (HTTP 400)—restart from the first page.
  • Use total for UI counts; do not assume total / limit pages if the catalog is changing.

Code examples

Search for “golden forest”, require both nature and trees, sort by newest, and return up to 30 results. Load the API key from the environment only.

cURL
curl -sS "https://epochalstock.com/api/v1/images?q=golden+forest&tags=nature,trees&tag_mode=all&sort=newest&limit=30" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY" \
  -H "Accept: application/json"

Following next_cursor

Minimal pattern for walking every page of a fixed filter set.

cURL
# First page
curl -sS "https://epochalstock.com/api/v1/images?tags=forest&sort=newest&limit=50" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY"

# Next page — paste next_cursor exactly
curl -sS "https://epochalstock.com/api/v1/images?tags=forest&sort=newest&limit=50&cursor=CURSOR_FROM_PREVIOUS" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY"

Sample JSON response

Successful responses wrap the page payload in data and include meta.request_id. Image records expose catalog metadata and safe preview URLs— original filesystem paths are never returned. The list view omits description, file_size, and file_extension; request a single image (GET /images/{image_id}) or POST /images/batch for the full record.

{
  "data": {
    "images": [
      {
        "id": "es_001_example",
        "slug": "golden-forest-canopy",
        "title": "Golden Forest Canopy",
        "collection": "nature",
        "width": 6000,
        "height": 4000,
        "tags": ["nature", "trees", "forest", "gold"],
        "created_at": "2025-11-02T14:22:10Z",
        "thumbnail_url": "https://epochalstock.com/…/thumb.jpg",
        "preview_url": "https://epochalstock.com/…/preview.jpg"
      }
    ],
    "total": 128,
    "limit": 30,
    "next_cursor": "eyJvZmZzZXQiOi4uLn0",
    "filters": {
      "q": "golden forest",
      "tags": ["nature", "trees"],
      "tag_mode": "all",
      "sort": "newest"
    }
  },
  "meta": {
    "request_id": "req_01HZX…"
  }
}

images

Array of image objects for the current page (length ≤ limit).

total

Estimated or exact count of matches for the active filters—use for UI totals.

next_cursor

Opaque token for the next page, or null/omitted when finished.

filters

Echo of normalized filters applied server-side—handy for debugging client state.

Filtering tips for design apps

  • Seed filter chips from GET /tags so users only pick normalized tags that exist.
  • Debounce free-text q input (200–300 ms) and cap length at 200 characters client-side.
  • Default multi-tag pickers to tag_mode=all; offer an explicit “match any tag” toggle for broader discovery.
  • Cache first-page results per filter fingerprint briefly on your backend to protect the 30 req/min budget.
  • Prefer limit=50–100 for infinite-scroll grids; smaller limits for typeahead previews.
  • Store image id values, then load full metadata with detail or batch endpoints when the user focuses a card.
  • Show watermarked preview_url / thumbnail_url in the canvas; request originals only on export.
  • Surface X-Request-ID in support logs when a search returns unexpected empties.

Next steps: load a single asset with image detail & batch, or explore popular tags via tags & stats.