Use case · Tag curation

Tag-driven curation & discovery

Editors and product teams need theme-first discovery—not only free-text search. Use GET https://epochalstock.com/api/v1/tags for normalized tags with image_count, GET /tags/{tag} for a single theme, then filter the catalog with GET /images?tags=….

The problem

Keyword boxes alone do not support editorial workflows. Curators want “show me everything tagged forest,” ranked by how much inventory exists, with stable filters they can pin into home screens and seasonal campaigns.

Unknown vocabulary

Teams guess query strings instead of browsing the catalog’s real tag set.

Empty themes

Without counts, UIs promote filters that return zero or near-zero results.

Inconsistent labels

Ad-hoc client taxonomies diverge from the normalized tags on each image.

Weak browse modes

“Explore by theme” needs list + detail tag APIs, not only q= search.

Who it hurts

  • Editorial / creative directors building seasonal packs and brand mood lanes
  • Design-tool product managers shipping tag chips and “popular themes” rails
  • Agency librarians who map client briefs to existing catalog language
  • CMS operators who want “related by tag” suggestions without inventing categories

Solution: tags API + filtered images

Treat tags as a first-class discovery index. List them with counts, optionally drill into one tag, then load images that carry those tags.

Goal Endpoint Notes
Browse / search tag vocabulary GET /tags q, sort=name|count, order, limit, cursor
Confirm one theme GET /tags/{tag} Normalized tag, exact image_count, filtered image URL hint
List assets for a theme GET /images?tags=… Optional tag_mode=all|any, sort, limit, cursor
Catalog scale context GET /stats total_images, total_tags, catalog_built_at

Complete parameter tables and live catalog tools: Tags & catalog statistics. Image filter details: Search & list images.

Live tag frequency (sample)

Top tags by image_count (limit 12), loaded server-side via the docs site’s API client when a key is configured. Values are escaped for safe HTML rendering. Live from API

Use these names exactly (normalized) when calling GET /images?tags=…. Prefer showing counts in chip UIs so curators avoid empty themes.

Curation flow

Theme discovery → asset grid

GET /tags sort=count · seed chips / rails
GET /tags/{tag} Confirm count before pinning
GET /images?tags= tag_mode all|any · cursor pages
Curate Save IDs · batch hydrate · export
  • Cache popular tag lists briefly on your server (counts change slowly relative to search traffic)
  • URL-encode path tags on GET /tags/{tag} (spaces and special characters)
  • For multi-chip filters, choose tag_mode=all (intersection) vs any (union)
  • Combine tags with optional q when editors refine a theme with free text

Step-by-step implementation

  1. Load a tag index with GET /tags?sort=count&order=desc&limit=50 for “Popular themes.”
  2. Optional typeahead: GET /tags?q=fore&sort=name&order=asc as the curator types.
  3. On chip select, either navigate with a known tag or confirm via GET /tags/{url_encoded_tag}.
  4. Fetch images with GET /images?tags=forest&sort=newest&limit=30 (add more tags and tag_mode as needed).
  5. Page with next_cursor; store selected IDs for batch rehydrate or downloads.

Endpoint map

GET /tags

Params: q, sort (name|count), order (asc|desc), limit, cursor. Items: tag + image_count.

GET /tags/{tag}

One normalized tag, exact count, and the corresponding filtered image list URL for follow-up calls.

GET /images?tags=

Up to 20 comma-separated tags; tag_mode=all (default) or any; full search sort/limit/cursor support.

GET /stats

Show total inventory beside your curation chrome so editors know catalog scale at a glance.

Code examples

List top tags by count

cURL
curl -sS "https://epochalstock.com/api/v1/tags?sort=count&order=desc&limit=50" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY" \
  -H "Accept: application/json"

Get one tag + filter images

cURL
# One tag (URL-encode the path segment)
curl -sS "https://epochalstock.com/api/v1/tags/golden%20hour" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY"

# Images carrying that theme (plus another tag, both required)
curl -sS "https://epochalstock.com/api/v1/images?tags=golden%20hour,nature&tag_mode=all&sort=newest&limit=30" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY" \
  -H "Accept: application/json"

Tag typeahead with q

cURL
curl -sS "https://epochalstock.com/api/v1/tags?q=fore&sort=name&order=asc&limit=20" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY"

Rate-limit notes

Every authenticated tags or images call counts toward the shared 30 requests per minute per account budget. Popular-tag rails should be cached on your backend (for example 5–15 minutes) so every editor page view does not re-hit GET /tags.

Debounce typeahead (q) so each keystroke does not become a full rate unit. Coalesce identical in-flight requests. On HTTP 429, honor Retry-After.

  • Seed chips once per session or from a short server cache
  • Prefer sort=count for home rails; sort=name for A–Z browsers
  • Image paging still uses opaque cursor values—never invent them
  • Unknown tag paths return tag_not_found (HTTP 404) on GET /tags/{tag}

Full limits and errors: Rate limits & errors.

Next steps

Tags & stats

Live catalog totals, full tag chart, and parameter reference for /tags and /stats.

Asset search

Combine tag chips with free-text q and cursor pagination.

Bulk metadata

After curators multi-select, rehydrate IDs with POST /images/batch.

GET /images

Complete filter, sort, and pagination docs for image listing.