Developer Image API · v1

Security & billing

Keep secret API keys and management sessions on your server. The catalog is available on a single $50 USD/month plan after PayPal reports the subscription ACTIVE. This page covers the operational security checklist, management endpoint map, billing states that block catalog access, and commercial license expectations.

Safe architecture

Authenticated catalog calls and management cookies must never be exposed to public browser JavaScript. Your product UI talks to your backend; your backend holds the Bearer key (and, for portal operations, the management session).

Never put the API key in the browser

Browser / app UI User session only · no EPOCHAL_API_KEY
Your backend Validate input · secrets manager · timeouts
Epochal API https://epochalstock.com/api/v1

Catalog traffic

Authorization: Bearer es_live_… on search, detail, batch, tags, stats, and download-token minting. Keys are hashed at rest; the full secret is shown only once at creation.

Management traffic

Portal register/login, keys, billing, and usage use a server-side management session plus CSRF. Do not expose management cookies or PayPal credentials to the browser.

Binary originals

Two-step flow: mint with the Bearer key, then transfer via a short-lived download_url without the key. Treat that URL as a secret until expiry.

CORS policy

Public browsers are not supported clients for authenticated catalog endpoints (cors_not_supported). Design for a same-origin or trusted backend proxy.

Security checklist

Follow this list for every production deployment that touches the Developer Image API.

Production security controls

  • Secrets storage: Keep keys in a secrets manager or environment variable—never source control, URLs, mobile apps, browser bundles, screenshots, or support messages.
  • Per-project keys: Create a separate named key for each website/backend (up to 20). Revoke only the affected key if one project is compromised.
  • No browser calls: Never call the authenticated API directly from a public browser. Your backend should validate user input and proxy only required fields.
  • Timeouts: Set connect and read timeouts on every HTTP client so hung sockets cannot pin workers indefinitely.
  • Retry policy: Retry only 429, 502, and 503 with bounded exponential backoff and jitter. Do not blindly retry other 4xx (auth, validation, subscription) errors.
  • Download URL secrecy: Treat signed download URLs as secrets until they expire or are used. Do not log or persist them in analytics.
  • License compliance: Store only necessary metadata and follow the Epochal Stock license. Do not redistribute originals as standalone files or power a competing stock marketplace.
  • Monitoring: Monitor usage and Request-IDs. Unexpected traffic across multiple keys still consumes the shared account rate limit (30 req/min).
  • Key rotation: Rotate keys periodically and immediately after suspected exposure.

Related guides

Common mistakes

Do not embed live keys in frontend builds. Public env prefixes (NEXT_PUBLIC_, VITE_, Expo public config), browser extensions, mobile app binaries, and desktop renderer processes are all reverse-engineerable. If a key may have shipped to clients, revoke it in the portal and create a new named key.

Do not put keys in URLs. Query-string authentication (?api_key=…) is rejected with query_key_rejected because URLs leak into browser history, proxies, CDN logs, and analytics. Use the Authorization: Bearer header only.

Do not expose management sessions to JavaScript. Portal cookies, CSRF tokens, and PayPal credentials belong on your server (or trusted BFF). Browser code should never call /portal/*, /keys, or /billing/* with credentials intended for Epochal management.

Do not log download URLs or Authorization headers into long-lived APM, error trackers, or third-party analytics. Keep X-Request-ID for support instead.

  • Do not create a single “god key” shared by every environment—blast radius is the entire product line.
  • Do not spin parallel original downloads; one concurrent transfer is enforced per account.
  • Do not retry 401/402/422 in a tight loop—fix config or billing first.
  • Do not assume extra API keys increase the 30 req/min ceiling—they share one account budget.

Plan reminder

Developer Image API v1 has a free trial and one commercial plan:

Plan Price Catalog API limit Original downloads Projects / keys
Free Trial $0 for 1 month All image collections 2 requests/minute · 2,000 total requests Counted toward the request budget 1 key (issued at signup)
Developer API $50 USD / month — first month $40 (20% off) All image collections 30 requests/minute per account Unlimited; one concurrent transfer Up to 20 named keys
  • Free 1-month trial (instant key via POST /trial/signup: 2,000 requests, 2/minute, one trial per email); no per-image billing, credit balance, bundle pricing, or video access in v1.
  • First-time subscribers get 20% off the first month ($40, then $50/month) automatically — see the pricing & upgrade page.
  • All keys belonging to an account share the same rate limit and concurrent-download lease.
  • Additional API keys can be created only after an active subscription (trials include one key).
  • Base URL for catalog traffic: https://epochalstock.com/api/v1

Account & billing integration

The developer website (or your own admin backend) should proxy these management calls and keep the Epochal management session server-side. Do not expose management cookies or PayPal credentials to browser JavaScript.

Method Path Purpose
GET /portal/csrf Start management session and obtain CSRF token.
POST /portal/register Register name, company, email, and 12+ character password.
POST /portal/login Log in with email/password.
POST /portal/logout End session.
GET /account Current account, plan, status, and CSRF token.
GET / POST /keys List keys or create a named key (create only after active subscription).
DELETE /keys/{key_id} Revoke a key immediately.
POST /trial/signup Public: instant free-trial account plus es_test_ key (no session/CSRF).
POST /billing/subscription Create the PayPal subscription and return approval URL. Portal session or Bearer API key (expired trials may still upgrade). First-time subscribers get the $40-first-month plan automatically; body {"plan":"regular"} forces full price.
GET /billing/upgrade?t=… Signed-token one-click redirect (302) straight to PayPal checkout.
POST /billing/upgrade-link Public: {email} → personalized upgrade link (used by the upgrade page's checkout form).
GET /billing/status Current subscription state.
POST /billing/cancel Stop renewal; catalog access remains until paid period end.
GET /usage Daily per-endpoint request/error/download totals.

Integration notes

  • Management session is server-side. Your backend obtains cookies from GET /portal/csrf (or login flows), stores them securely, and attaches them on subsequent portal calls. End users of your product should not receive Epochal management cookies.
  • CSRF required for state changes. State-changing management requests require the session cookie plus X-CSRF-Token. Registration and login first call /portal/csrf, retain the cookie, and send the token.
  • API key only after active subscription. Creating keys before PayPal reports an active plan will fail. Sequence: register → subscribe → wait for ACTIVE → create key.
  • PayPal webhooks activate access. PayPal sends signed events to POST /api/v1/webhooks/paypal. Catalog access activates only after PayPal reports the subscription ACTIVE. Webhook event IDs are idempotent.

Session & CSRF pattern

A typical server-side management client follows this order. Paths below are relative to the API base (https://epochalstock.com/api/v1) unless your deployment documents a separate portal host.

Management session bootstrap

GET /portal/csrf Cookie + CSRF token
POST login/register X-CSRF-Token + cookie
Billing / keys Same session · CSRF on writes
Sequence
1. GET  /portal/csrf
   → Set-Cookie: management session
   → body/header includes CSRF token

2. POST /portal/register  (or /portal/login)
   Headers:
     Cookie: <session>
     X-CSRF-Token: <token>
     Content-Type: application/json
   Body (register): name, company, email, password (12+ chars)

3. POST /billing/subscription
   Headers: Cookie + X-CSRF-Token
   → returns PayPal approval URL for the $50/month plan

4. User approves in PayPal → webhook ACTIVE → account can create keys

5. POST /keys  { "name": "design-app-prod" }
   → secret shown once; store in secrets manager as EPOCHAL_API_KEY

6. Catalog traffic uses Bearer key only (no management cookie required)

Invalid CSRF returns HTTP 403 with invalid_csrf. Login abuse can return 429 login_rate_limited. See Rate limits & errors for the full code table.

Subscription states & catalog access

Billing is webhook-driven. Approving PayPal is necessary but not sufficient until the platform records an ACTIVE subscription from a verified webhook event.

State / signal Catalog API What to do
No subscription / not yet ACTIVE Blocked — typically HTTP 402 subscription_required Complete PayPal approval; wait for ACTIVE webhook; then create keys.
ACTIVE Allowed with a valid Bearer key Normal operation; monitor usage and rate-limit headers.
past_due (payment failure / suspension) Blocks catalog access402 subscription_past_due Resolve payment with PayPal/billing; restore ACTIVE before retrying catalog traffic.
Cancel requested (POST /billing/cancel) Access remains until the paid period ends Stop renewal; plan offboarding; keys stop working after the paid boundary.

past_due blocks the catalog. Payment failure or suspension changes the account to past_due and blocks catalog access until the subscription is healthy again. Design your product UX to surface billing recovery rather than infinite API retries on 402.

  • Activation occurs only after PayPal reports ACTIVE (signed webhook).
  • Webhook event IDs are idempotent—safe to process duplicates without double-applying state.
  • POST /billing/cancel stops renewal; access continues through the already-paid period.
  • Creating a second overlapping subscription may return 409 subscription_exists.
  • Key limit is 20; excess create attempts return 409 key_limit_reached.

Commercial license

The commercial license at epochalstock.com/license applies to API usage and licensed images.

  • Images licensed during an active subscription remain licensed after cancellation for the rights granted under the license terms—cancellation stops new API access at the paid period boundary; it does not claw back previously licensed uses as defined by the license.
  • Store only the metadata your product needs. Do not redistribute original files as a standalone stock library or operate a competing marketplace on top of the catalog.
  • Follow attribution or display rules if/as required by the license page; keep license text accessible to your end customers where your product redistributes creative works.
  • When in doubt, read the full license document and consult counsel for your jurisdiction and product model.

Monitoring, usage, and key rotation

Request IDs

Every response includes X-Request-ID (and usually meta.request_id or error.request_id). Log it on success and failure; include it in support tickets—never the API key.

GET /usage

Management endpoint for daily per-endpoint request, error, and download totals. Poll from your backend admin tools, not from public clients.

Shared budget

Unexpected traffic on any key still burns the account’s 30 req/min and the single download lease. Alert when X-RateLimit-Remaining stays near zero.

Rotation

Create a new named key, deploy it, then DELETE /keys/{id} for the old key. Rotate immediately after suspected exposure (git push, screenshot, support paste, client bundle).

Download URL secrecy: mint tokens only on trusted servers; prefer streaming originals through your backend when end users must not see signed URLs. Full flow: Downloads.

Next steps

Authentication

Bearer keys, lifecycle, and security rules for catalog traffic.

Downloads

Two-step originals, token expiry, and concurrency lease.

Code examples

Multi-language server samples for search through downloads.

Overview

API capabilities and documentation map.