App blueprint · Design plugin

Design plugin asset browser

Ship an in-editor stock panel for Figma-style tools, browser design editors, or desktop plugins: search the full catalog, inspect metadata, place watermarked previews on the canvas, and pull full-resolution originals only when the user exports—always through your backend, never with a Bearer key in the plugin bundle. One plan: $50/month, 30 requests/minute shared across keys, unlimited serial original downloads, one concurrent transfer.

Who this blueprint is for

This page is a product and engineering playbook—not a host-specific plugin SDK. It maps UI surfaces to documented catalog endpoints so you can implement the same pattern in any design host that can call your HTTPS API.

Plugin authors

Teams building panels for canvas tools who need licensed search without embedding vendor secrets in distributable packages.

SaaS design editors

Web products with an “Insert stock image” rail that must stay key-safe under CSP and public JavaScript inspection.

Agency tooling teams

Internal design systems that wrap Epochal Stock for staff plugins and shared export pipelines.

Not for

Browser-only demos that call the catalog with a live key, free-tier experiments, video stock, or inventing /collections / GraphQL on Epochal.

Product features to ship

Keep the first release focused. Each feature below maps to a documented endpoint or to data you already store; none require undocumented APIs.

  • Search panel — free-text q, optional tag chips, sort, “Load more” via opaque cursor (GET /images).
  • Result grid — cards from thumbnail_url / title / dimensions; store stable id on each card.
  • Detail drawer — full metadata, tags, preview for the selected ID (GET /images/{id}).
  • Place on canvas — insert using preview_url or thumbnail_url only (no original, no API key on the client).
  • Export / download package — when the user exports, your backend runs POST /downloads and transfers originals serially.
  • Tag discovery (optional) — seed filter chips from GET /tags with image_count.
  • Auth to your product — plugin users sign into your account; only your server holds EPOCHAL_API_KEY.

Plan facts: $50 USD/month (first month $40 with the 20% upgrade discount) · full image catalog · 30 authenticated req/min per account (all keys share it) · up to 20 named keys · unlimited original downloads · one concurrent original transfer · free 1-month trial (2,000 requests at 2/min via POST /trial/signup) · no credits or video in v1.

Architecture (always three tiers)

Every catalog call follows the same rule used across this documentation site: Browser / Plugin UI → Your Backend → Epochal API. The Bearer key exists only on the backend.

Plugin never holds EPOCHAL_API_KEY

1. Plugin / editor UI Search, grid, drawer, place preview · product session cookie/JWT only
2. Your backend Validate params · rate-shape · Bearer key · log X-Request-ID
3. Epochal API https://epochalstock.com/api/v1 GET /images · GET /images/{id} · POST /downloads
4. Back to plugin JSON metadata + preview URLs · originals only via your export path

Do not put es_live_… in plugin source, manifest.json, browser extension storage, or client env files shipped to users. Catalog CORS with secret keys is not a supported public-browser pattern. Query-string keys are rejected (query_key_rejected).

Screen → endpoint map

Wire each UI surface to the smallest documented call. Prefer batch later only if you hydrate many saved IDs at once (see the moodboard blueprint).

Plugin screen / action Your API (example) Epochal endpoint Notes
Search box, filters, Load more GET /api/stock/search GET /images q, tags, tag_mode, sort, limit, cursor
Open detail drawer GET /api/stock/images/:id GET /images/{id} Title, tags, dimensions, preview URLs
Tag chip suggestions GET /api/stock/tags GET /tags Optional; sort by count
Place on canvas No Epochal call Use preview_url / thumbnail_url already returned
Export package / final file POST /api/stock/export POST /downloads then GET signed URL Backend only; serial; handle 409
Catalog size badge (ops) GET /api/stock/stats GET /stats Optional admin strip

Full parameter tables: Search & list, Detail & batch, Downloads, Tags & stats.

Detail drawer

When the designer selects a card, open a drawer fed by GET https://epochalstock.com/api/v1/images/{image_id} (proxied). Display title, description, dimensions, file extension, tags, and a larger watermarked preview. Do not expose original filesystem paths—the API never returns them.

Cache detail responses briefly on your server if the same ID is reopened often, but treat preview URLs as temporary display assets—re-fetch if the host expires or blocks them.

Place on canvas (previews only)

“Place” should feel instant. Use the preview_url (watermarked) or thumbnail_url already present on the search or detail payload. That placement does not require POST /downloads and must not pull a secret key into the plugin.

  • Store the Epochal id on the canvas node for later export mapping
  • Show a visual badge (“preview”) so designers know the full-res file is not yet attached
  • Respect host CORS/image loading rules for HTTPS preview URLs; proxy media through your CDN only if required
  • Never treat place-on-canvas as a license to redistribute originals outside your product’s terms

Export: originals only on the backend

When the user exports a design package or downloads full-resolution assets, your backend runs the documented two-step flow: mint a five-minute, single-use token with POST /downloads, then GET the signed download_url without the API key. Serialize transfers—the account allows only one concurrent original. On 409 download_already_active, wait and retry.

Deep dive: Safe original export pipeline and Original downloads.

Search proxy code (4 languages)

Example: proxy “golden forest” with tags nature,trees, tag_mode=all, sort newest, limit 30. The plugin calls your route; only the server talks to https://epochalstock.com/api/v1/images.

cURL
# Server-side only — never from the plugin
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"

Detail proxy sketch

cURL
curl -sS "https://epochalstock.com/api/v1/images/es_001_example" \
  -H "Authorization: Bearer $EPOCHAL_API_KEY" \
  -H "Accept: application/json"

Security callouts

Keys stay server-side. Plugin marketplaces, browser extensions, and desktop installers are public. Anyone can unpack your binary and extract an embedded es_live_… secret. Put the key in a secrets manager on your backend only.

Authenticate plugin traffic to you. Your /api/stock/* routes must require your own user/session auth. An open proxy turns your $50 plan into a public open relay and burns the shared 30 req/min budget for every stranger.

  • Whitelist query parameters; reject unexpected fields before calling Epochal
  • Cap q (200) and tag count (20) yourself—do not rely only on upstream validation
  • Do not log full Authorization headers or mint download URLs into long-lived access logs
  • Rotate keys via management APIs if a worker host is compromised—see Security & billing
  • No GraphQL, /upload, or client-side catalog keys in v1

Rate limits for a live plugin

The account limit is 30 authenticated requests per minute, shared across all named keys (max 20). Creating plugin-prod and plugin-staging does not double the budget.

Traffic Counts toward 30/min? Guidance
GET /images (each page) Yes · 1 Debounce search; cache short-TTL identical queries
GET /images/{id} Yes · 1 Cache drawer payloads; avoid re-fetch on every hover
POST /downloads Yes · 1 per mint Export worker only; serialize with concurrency lease
Binary GET of download_url No catalog unit Holds the single concurrent transfer until complete
Plugin loading preview images No CDN/media URLs—not catalog API calls

Headers and 429 behavior: Rate limits & errors.

Build checklist

  • Subscribe ($50/mo ACTIVE) and create a named key e.g. design-plugin-prod
  • Store EPOCHAL_API_KEY only on the backend / worker
  • Implement authenticated search + detail proxies
  • Render grid from thumbnails; place with preview URLs
  • Persist image IDs on canvas nodes for export
  • Build a serial export queue with 409 and 429 handling
  • Map 401 / 402 / 429 to clear plugin toasts
  • Document ops: which key, which env, how to rotate

Next steps

Moodboard app

Save IDs in your DB and hydrate with POST /images/batch.

Agency library

Named keys per project under a shared 30/min account budget.