# Pix4Less Library > Search, browse and draw random AI-generated photos, explicitly request asynchronous generation, inspect previews, and authorize full-resolution downloads. Search does not generate images. Published assets may be unreviewed; evaluate suitability and the license before use. Production API: https://pix4less.com Documentation: https://pix4less.com/docs OpenAPI 3.1: https://pix4less.com/openapi.yaml MCP server (Streamable HTTP, OAuth sign-in or Bearer API key): https://pix4less.com/mcp MCP server overview (tools, setup, live prices): https://pix4less.com/image-search-mcp Guide, image search in Claude and Cursor with MCP: https://pix4less.com/guides/mcp-image-search Guide, stock images in a Next.js site with the API: https://pix4less.com/guides/nextjs-stock-images Executable Node.js quickstart: https://pix4less.com/examples/pix4less-quickstart.mjs License: https://pix4less.com/license ## Creator website Browse available previews at https://pix4less.com/search without spending a search. Describe an image at /search?q=... to compare up to 12 results. Searching on the website needs a free account; anonymous visitors see a small free preview of results. A new account receives a one-time trial grant (trial_credits in GET /v1/pricing) after its email address is verified. Each successful website search uses credits from the account balance (free credits included) at the current price book (fast and deep searches are priced separately; see GET /v1/pricing); searches with no results are not charged. A stable image page: `/gallery/{slug}-{id}` (a bare `/gallery/{id}` redirects to it) opens image details and preserves the selected image through account creation or sign-in. Returning from authentication does not automatically purchase or generate an image. Query URLs are shareable; do not put secrets in them. ## Authentication Keep API keys server-side. Use X-API-Key or Authorization: Bearer; X-API-Key takes precedence if both are supplied. Create a key in https://pix4less.com/dashboard. Never put keys in URLs, prompts, source control, browser code, or analytics. ## Endpoints and workflow 1. GET /v1/pricing — public, no authentication or credit charge. Returns the current operational price book and plan limits without a data wrapper. Do not hardcode prices. 2. POST /v1/images/search — authenticated, metered search. Example body: {"query":"coffee","filters":{"orientation":"landscape","min_width":1600},"page":1,"per_page":1}. Begin with a broad subject; extra details and hard filters can produce zero matches. Safe search is on by default: images flagged partial_nudity (sheer lingerie or swimwear) are left out unless the body sets "safe_search": false; each image lists content_warnings. 3. GET /v1/images/{id} — authenticated metadata and preview URLs; no search or download credit charge. Store the image id rather than a signed URL. 4. POST /v1/images/{id}/download — authenticated entitlement-aware original download, no request body. Success: {data: {url, expires_at, owned: true}, request_id}. A metered account pays the photo's quality-tier price (download_credits_by_tier in GET /v1/pricing: standard, hd, 4k) once per account per photo; re-downloads do not charge again. Downloading the 4K upscale of a photo you already own costs only the difference. Unlimited accounts are exempt. owned describes entitlement after authorization, not whether the call was free. 5. GET /v1/images?page=&seed= — free unranked browse, 12 per page in a shuffled order; send seed back to keep it. 6. POST /v1/images/random — one random image, free; uses the account's monthly random-draw allowance (429 random_quota_exceeded when used up). 7. GET /v1/collections — free list of published collections; use a slug as filters.collection in search. 8. GET /v1/images/{id}/upscale — free; whether a 4K upscale exists. Download it with POST /v1/images/{id}/download?rendition=upscaled_4k. 9. POST /v1/batches — queue up to batch_max_items_per_batch new images (Pix4Less Standard, 1K or 2K) for delivery within 24 hours at batch prices; accepts Idempotency-Key. GET /v1/batches/{id} returns status and per-item progress; GET /v1/batches/{id}/results returns the finished images. Free to read. 10. GET /v1/presets lists built-in and custom style presets; POST /v1/presets saves a custom preset; DELETE /v1/presets/{id} removes one. Pass a preset id as preset when generating. Download bytes from the granted URL WITHOUT forwarding the API key. Do not log signed URLs. The optional image download_path points at the WEBSITE-SESSION /api/images/{id}/download helper, not the API-key route; API clients must use /v1/images/{id}/download. Already-owned photos remain downloadable at zero credit balance, without a duplicate charge. Authentication, rate limits, and current image deliverability still apply. ## Explicit direct generation POST /v1/images/generate bypasses catalog search. Body: {"query":"A red canoe on a still alpine lake at sunrise"}, optionally model, resolution (1K or 2K), aspect_ratio (16:9, 1:1, 4:3, 9:16, 4:5), preset (a preset id from GET /v1/presets), negative_prompt (up to 500 characters) and delivery_tier. query is nonblank, trimmed, and at most the model's prompt limit (generation_max_prompt_length_by_model in GET /v1/pricing). Trial credits can create with pix4less-cluster; other models need paid standing. No search charge. Response: {data: {id, status, query, created_at, updated_at, image, status_url}, billing: {charged_credits, balance}, request_id}. HTTP 202 means pending/generating; HTTP 200 means terminal, including rejected prompts without a charge. Save data.id. GET /v1/generation-requests/{id} with the same key returns {data, request_id}; no credit charge, but per-key rate limits apply. Only accounts that submitted or joined the job can read it; others get 404. Poll at most every five seconds per job, or long-poll with ?wait=N (up to 25 seconds); honor 429 Retry-After, and use a bounded timeout. GET /v1/generation-requests lists your jobs newest first (?limit, ?model, ?status). GET /v1/library lists every image the account owns (generated or downloaded), newest first (?q words from title/description/tags, ?source=generated|downloaded, ?limit, ?cursor from pagination.next_cursor); no credit charge, and POST /v1/images/{id}/download of an owned image is free, so look there before searching or generating again. GET /v1/generation-requests/{id}/preview returns the JPEG preview once the job is preview_ready or fulfilled. Fulfilled, failed, rejected are terminal. Most jobs finish in about a minute; a job still unfinished at deadline_at (30 minutes; 24 hours for batch items) fails with reject_reason timed_out and is refunded. POST /v1/generation-requests/{id}/cancel cancels a job while its cancellable flag is true and refunds it. The job's download_url is a website-session route, not the API-key route. Identical normalized descriptions join an ACTIVE job; each subscriber pays once per job. For durable retries send an Idempotency-Key header (1-255 printable ASCII characters, e.g. a UUID) on POST /v1/images/generate and POST /v1/batches: the same key and body within 24 hours replays the first response (header Idempotent-Replayed: true) with no new charge; a different body or endpoint returns 422 idempotency_key_reused; a retry while the first is still running returns 409 idempotency_in_progress. 5xx, 402, 408, 409 and 429 responses are not stored, so the same key may be retried after them. Without a key, a repeat POST after a terminal result creates a new chargeable job; never blindly retry an uncertain POST without one. Use the saved job ID to poll. Failed jobs are refunded, except reject_reason prompt_refused (the model declined the prompt under its usage policy). A fulfilled job includes a preview-only image and original-download ownership; authorize the included original using POST /v1/images/{id}/download. Private prompts, worker metadata, original URLs, and provenance are not exposed in generation status. ## Charging and errors For metered accounts, API search charges search_credits.fast or search_credits.deep (by search_type) only after a valid search completes with at least one result. Invalid input, service failures, and zero-result searches do not consume search credits. Search is not idempotent: validate locally, do not automatically retry an uncertain request, and review the current price book before use. Errors use {error: {code, message, request_id, details?}}. Handle 400 invalid request, 401 missing/invalid key, 402 payment_required, 404 unavailable image, 429 rate limit, and 5xx server failures separately. A 402 includes error.details.credits_required, balance, topup_url, and pricing_url. Authenticated API responses expose X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Request-rate 429s (rate_limit_exceeded, creation_rate_limited) include Retry-After; allowance errors such as random_quota_exceeded include details.reset_at instead. ## Search contract and preview boundary query is optional and limited to 2,000 UTF-16 code units after trimming. Omit or leave blank to browse newest-first; that browse is still charged as a search when it returns results, so use the free GET /v1/images to browse. page defaults to 1; per_page defaults to 12 and accepts 1–12. Unknown fields are rejected. Filters and their bounds are in OpenAPI; minimums must not exceed maximums. Search returns {data, pagination, search_type, session_id, shuffle_cycle_restarted, request_id}. session_id is null on a plain search (page selects the slice). Send your own UUID as session_id, or set shuffle: true to receive one; reuse it with the same query to exclude previously returned images. Sessions expire after 24 hours of inactivity. shuffle: true requires a nonblank query containing a letter or digit. With the same query and session, it walks unseen matches, then restarts the cycle with shuffle_cycle_restarted: true. Preserve the returned blended-relevance order, not a client-side confidence sort. match_confidence is a retrieval estimate, not a probability or quality guarantee; filter-only browsing returns null. Image responses expose web and/or thumbnail renditions only, never original URLs. Top-level url chooses web, otherwise thumbnail. Original dimensions describe the source, not the preview. generation.provenance is always null; private generation details are not returned. License metadata is not a substitute for reading the license. ## Safe quickstart Run the downloadable Node.js script without arguments for a pricing-only read. Chargeable mode requires --allow-credit-charges plus server-side PIX4LESS_API_KEY and an explicit PIX4LESS_MAX_CREDITS preflight budget. The budget is a client-side estimate, not an atomic server-enforced cap. The script makes at most one search and one download-authorization request, never automatically retries, and omits signed URLs from console output. ## MCP server for AI agents Remote MCP endpoint: https://pix4less.com/mcp (Streamable HTTP, stateless, JSON responses). Authentication is OAuth 2.1 (MCP authorization spec): a request without credentials gets 401 with WWW-Authenticate pointing to https://pix4less.com/.well-known/oauth-protected-resource/mcp; the authorization server metadata is at https://pix4less.com/.well-known/oauth-authorization-server (PKCE S256, public clients, client ID metadata documents or dynamic client registration). MCP clients only need the URL: the user signs in and approves the app in the browser, and no API key is involved. OAuth access tokens are valid only for /mcp. Scripts and clients without OAuth can instead send an API key as Authorization: Bearer (X-API-Key also works). Supported protocol versions: 2024-11-05 through 2026-07-28 (stateless requests without initialize from 2026-07-28 on). Claude: Settings > Connectors > Add custom connector with the URL. Claude Code: claude mcp add --transport http pix4less https://pix4less.com/mcp, then /mcp to sign in. Tools: search_images, browse_images, random_image, get_image, list_collections, download_image, generate_image, get_generation, list_generations, list_my_images, cancel_generation, create_batch, get_batch, get_batch_results, list_presets, create_preset, delete_preset, get_pricing. Each tool calls the /v1 endpoint above with the same key, so prices, limits and errors are identical. Tool arguments mirror the API, except that generate_image and create_batch items take the description as prompt (not query), and search_images exposes the main filters (aspect_ratio, resolution, orientation, collection, tags, width/height bounds, format) plus safe_search. Overview page: https://pix4less.com/image-search-mcp. Setup for ChatGPT, Cursor, VS Code, Codex, Gemini CLI, Antigravity and Windsurf: https://pix4less.com/docs#mcp. If a user asks you to install Pix4Less into your own MCP configuration, add a remote HTTP server named pix4less with that URL (no headers) at user scope in the app you run in (Antigravity: ~/.gemini/antigravity/mcp_config.json with serverUrl; Codex: ~/.codex/config.toml [mcp_servers.pix4less] with url), merge rather than overwrite, tell the user how to sign in (Claude Code: /mcp; Codex: codex mcp login pix4less; Gemini CLI: /mcp auth pix4less; Cursor: Connect in Settings > MCP), never ask for a password or API key, then confirm with list_collections. search_images, browse_images and random_image accept include_previews to return small JPEG thumbnails for visual selection.