Quickstart

Describe the image you need in plain language and get matching photos from the Pix4Less library, from your code or straight from your AI agent. Search only returns existing photos; creating a new image is a separate, explicit call.

  1. Create an API key

    Sign in and create a key in your dashboard. New accounts get a one-time 100-credit ($0.20) trial after verifying their email. Keep the key on your server or in your terminal, never in browser code. Save it once so every example below works as-is:

    Terminal
    export PIX4LESS_API_KEY="cai_live_..."
  2. Connect your AI agent (optional)

    Using Claude, ChatGPT, Claude Code, Cursor, VS Code or another agent? Add https://pix4less.com/mcp and sign in when it asks. Agents don’t need an API key. Setup for each app →

  3. Search from code

    A search that returns at least one result costs 1 credit ($0.002); a search with no matches is free. Previews are free to view, and the full-resolution original is bought separately in step 4.

    Terminal
    curl "https://pix4less.com/v1/images/search" \
      -X POST \
      -H "X-API-Key: $PIX4LESS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "query": "coffee",
        "filters": { "orientation": "landscape", "min_width": 1600 },
        "page": 1,
        "per_page": 1
      }'
  4. Download the original

    Pass the image id from the search result. You pay once per photo; later downloads of the same photo are free. Fetch the returned url without your API key, and don’t log it: it is a signed link.

    Terminal
    curl -X POST "https://pix4less.com/v1/images/IMAGE_ID/download" \
      -H "X-API-Key: $PIX4LESS_API_KEY"
    
    # → { "data": { "url": "https://…", "expires_at": "…", "owned": true }, "request_id": "…" }

Start with a broad subject, then add detail and filters for your use case. A valid search can return no matches; check the result count before downloading and never automatically repeat a charged search. Current prices are always at GET /v1/pricing (no key needed).

MCP server for AI agents

Pix4Less is a remote Model Context Protocol server at https://pix4less.com/mcp (Streamable HTTP). Add the URL to your AI app and sign in with your Pix4Less account when it asks: there is no API key to copy. Your agent can then find, preview, download and create images for you. Every tool calls the /v1 API, so prices, limits and errors are the same as in your code. You can see and disconnect connected apps in your dashboard.

Fastest: let your agent set itself up

Copy this prompt into Claude Code, Codex, Gemini CLI, Cursor, Antigravity or any agent that can edit its own settings. The agent works out which app it is running in, adds Pix4Less to its configuration and tells you how to sign in. The prompt contains no secret.

Paste into your agent
Add the Pix4Less MCP server to your own MCP configuration, then help me sign in to it.

Server: https://pix4less.com/mcp (remote, Streamable HTTP)
Sign-in: OAuth. No API key is needed: the app opens a Pix4Less sign-in page in my browser the first time it connects.

Work out which app you are running in and use its own setup, for every project (user scope):
- Claude Code: run  claude mcp add --scope user --transport http pix4less https://pix4less.com/mcp  then tell me to run /mcp, pick pix4less and choose Authenticate.
- Codex: run  codex mcp add pix4less --url https://pix4less.com/mcp  (it starts the sign-in; later: codex mcp login pix4less)
- Gemini CLI: run  gemini mcp add --scope user --transport http pix4less https://pix4less.com/mcp  then tell me to run /mcp auth pix4less
- Cursor: in ~/.cursor/mcp.json add under "mcpServers":
  "pix4less": { "url": "https://pix4less.com/mcp" }
  then tell me to open Cursor Settings → MCP and click Connect next to pix4less.
- VS Code (Copilot): in the user mcp.json (command: MCP: Open User Configuration) add under "servers":
  "pix4less": { "type": "http", "url": "https://pix4less.com/mcp" }
- Antigravity or Windsurf: in mcp_config.json add under "mcpServers":
  "pix4less": { "serverUrl": "https://pix4less.com/mcp" }
- Claude (desktop, web or mobile) and ChatGPT cannot change their own settings: tell me to add https://pix4less.com/mcp as a custom connector (Claude: Settings → Connectors → Add custom connector) and sign in.

Rules:
- Merge into the existing file; keep every other server and setting.
- If you cannot change the configuration yourself, give me the exact command or file edit to make.
- Never ask me for a password or an API key: I sign in on pix4less.com in my browser.

When done, tell me whether I need to restart or reload the app. Once the pix4less tools are available, call list_collections (free) to confirm the connection.

Prefer to do it yourself? Pick your client:

Claude on the web, desktop and mobile. Click Add to Claude, or open Settings → Connectors → Add custom connector and paste the URL. Then click Connect and sign in. Connectors you add here also show up in Claude Code. The Free plan allows one custom connector.
Add to Claude
Connector URL
https://pix4less.com/mcp

Scripts, CI or a client that cannot sign in? Send an API key from your dashboard as Authorization: Bearer instead; the key then decides the account and credits. For example in Claude Code:

Terminal
claude mcp add --transport http pix4less https://pix4less.com/mcp \
  --header "Authorization: Bearer $PIX4LESS_API_KEY"

Try it

Ask your agent something like:

  • “Find three landscape photos of a cozy coffee shop and show me the previews.”
  • “Pick an image for each section of this blog post and download the ones I approve.”
  • “Nothing fits? Generate a red canoe on an alpine lake at sunrise in 16:9.”
search_images
Search with the main filters (aspect ratio, resolution, orientation, collection, tags, size, format) and safe_search; include_previews returns small thumbnails so the agent can judge images visually
browse_images · random_image · list_collections
Free discovery without a query
get_image · download_image
Details (with 4K upscale availability) and a signed full-resolution URL
generate_image · get_generation · list_generations · cancel_generation
Create an image when nothing fits (the description is the prompt argument); waits briefly and returns the preview
create_batch · get_batch · get_batch_results
Up to 100 images delivered within 24 hours at batch prices
list_presets · create_preset · delete_preset
Keep a consistent style, e.g. one look for every blog image
get_pricing
The live price book (free)

A typical content workflow: search for each section’s image, generate one with a saved preset when nothing fits, download the chosen file and host it yourself, and use the image description as alt text. Check each image’s license before publishing.

Authentication

Send your API key in the X-API-Key header. Authorization: Bearer works too; if both are sent, X-API-Key wins. Keep keys server-side and create a separate key for each environment. AI apps connected to the MCP server sign in with OAuth instead and never see a key; their sign-in tokens only work with the MCP server.

X-API-Key: cai_live_...
# or
Authorization: Bearer cai_live_...

Create and manage keys in your dashboard →

Pricing & credits

Everything is prepaid credits. 1 credit = $0.002 USD. New accounts receive a one-time 100-credit ($0.20) trial grant once their email is verified. The machine-readable price book is at GET /v1/pricing (no auth).

Quick search (search_type: "fast")
1 credit ($0.002) per successful request (our AI ranking model reviews 30 candidates), returning up to 12 images
Thorough search (search_type: "deep")
3 credits ($0.006) per successful request (our AI ranking model reviews 100 candidates), returning up to 12 images
Library photo download
1 credit ($0.002) per standard photo (HD: 3 credits, 4K: 10 credits), charged once per account; re-downloads are free
Create a new image
20 credits ($0.04) for 1K (2K: 40 credits) with Pix4Less Standard; other models are priced per model at GET /v1/pricing. Refunded automatically if generation fails, except when the model declines the prompt under its usage policy. 4K generation is not offered
Generation access
Trial credits can create with Pix4Less Standard; other models require a successful top-up or paid subscription invoice. New images join the public catalog
Prepaid credit top-up
Add $10 to $500 via Stripe instant checkout
Plans
Monthly credit-grant subscriptions with higher rate limits — the live catalog is served at GET /v1/pricing

When credits run out the API answers 402 payment_required with details.credits_required, details.balance, details.topup_url, and details.pricing_url, so clients can resolve it without a human.

Search credits are charged only after a valid search completes with at least one result. Invalid input, service failures, and zero-result searches do not consume search credits. Requests are not idempotent: validate locally and do not automatically retry an uncertain search. Unlimited accounts are exempt from credit charges.

Batch API. Submit up to 100 new-image requests at once to POST /v1/batches for delivery within 24 hours, at a discount off the standard price. Pix4Less Standard only; poll GET /v1/batches/{id} for status.

Batch · 1K
8 credits (60% below the standard 1K price)
Batch · 2K
14 credits (60% below the standard 2K price)

Endpoints

Base URL https://pix4less.com. Every endpoint except GET /v1/pricing needs an API key. The full schema is in the OpenAPI 3.1 spec.

Search and browse
POST/v1/images/searchSearch published images using plain text and filters — from 1 credit ($0.002) per request with results
GET/v1/imagesBrowse the library without a query, 12 per page in a shuffled order (pass seed back to keep it) — free
POST/v1/images/randomDraw one random image, like the website's I feel lucky — free; uses the monthly random-draw allowance
GET/v1/collectionsList published collections; use a slug as filters.collection — free
GET/v1/images/{id}Metadata and preview URLs — free; rate limits apply
Your images
GET/v1/libraryEvery image your account generated or downloaded, newest first; ?q, ?source=generated|downloaded, ?cursor — free; re-downloading an owned image is free too
Download
POST/v1/images/{id}/downloadSigned full-resolution URL — from 1 credit ($0.002) per photo, charged once per account; ?rendition=upscaled_4k for the 4K upscale
GET/v1/images/{id}/upscaleWhether a 4K upscale exists and its dimensions — free
Generate
POST/v1/images/generateQueue one new image without searching — from 20 credits (1K) with Pix4Less Standard; other models priced at GET /v1/pricing
GET/v1/generation-requestsList your generation jobs, newest first, filtered by model or status — free
GET/v1/generation-requests/{id}Poll a generation job; ?wait= long-polls up to 25 s — free; rate limits apply
GET/v1/generation-requests/{id}/previewThe job's JPEG preview once it is preview_ready or fulfilled — free
POST/v1/generation-requests/{id}/cancelCancel a job while its cancellable flag is true; the charge is refunded
Batches
POST/v1/batchesQueue up to 100 new images for delivery within 24 hours at batch prices
GET/v1/batches/{id}Batch status and per-item progress — free
GET/v1/batches/{id}/resultsFinished images of a batch — free
Style presets
GET/v1/presetsBuilt-in and your custom style presets
POST/v1/presetsSave a custom preset to reuse across generations
DELETE/v1/presets/{id}Remove one of your custom presets
Pricing
GET/v1/pricingPublic machine-readable price book (no auth, no charge)

For search, query accepts up to 2,000 UTF-16 code units after trimming whitespace; anything longer is rejected with 400 invalid_request. search_type accepts "fast" (default; our AI ranking model reviews 30 candidates) or "deep" (our AI ranking model reviews 100 candidates). filters is optional. Pagination defaults to page 1 with 12 results, the most a page can hold. To browse for free, use GET /v1/images: a search with a blank query is still charged when it returns results.

Generate instead of search

The website’s Generate button and POST /v1/images/generate queue a new photo directly. Supply query, a nonblank description up to the model’s prompt limit after trimming (generation_max_prompt_length_by_model in GET /v1/pricing; currently 451 characters for Pix4Less Standard), and optionally model, resolution (1K or 2K), aspect_ratio (16:9 default, 1:1, 4:3, 9:16 or 4:5), preset and negative_prompt. A 1K image with Pix4Less Standard costs $0.04, with no search charge. Trial credits can create with Pix4Less Standard; other models unlock after your first purchase.

Node.js 20+ (server-side)
// Server-side, after checking GET /v1/pricing and approving the cost:
const headers = {
  "X-API-Key": process.env.PIX4LESS_API_KEY,
  "Content-Type": "application/json",
  // Reuse the same key when retrying this exact request.
  "Idempotency-Key": crypto.randomUUID()
};
const response = await fetch("https://pix4less.com/v1/images/generate", {
  method: "POST", headers,
  body: JSON.stringify({ query: "A red canoe on a still alpine lake at sunrise" })
});
if (!response.ok) throw new Error("Generation request failed; retry only with the same Idempotency-Key");
const { data: job } = await response.json();
// Save job.id. If pending/generating, long-poll job.status_url + "?wait=25".
// Honor 429 Retry-After. Stop at fulfilled, failed, or rejected.
// On fulfillment, job.image is the preview. To download the included original:
// POST /v1/images/{job.image.id}/download (no body).

Creation returns 202 while queued or generating, or 200 for a terminal result such as a rejected prompt. Polling returns 200 with the current status, not necessarily a finished image. Most jobs finish in about a minute; a job still unfinished at its deadline_at (30 minutes, or 24 hours for batch items) fails with timed_out and is refunded. Failed jobs are refunded; prompts rejected by our screen before generation are not charged. A prompt the model itself declines under its usage policy fails with reject_reason: "prompt_refused" and is not refunded. Successful generation includes download ownership.

As a prerequisite for using generation services, all generated images join the searchable shared catalog under our Commercial License Agreement. Creators automatically accept the Creator Royalty Program, earning back up to 25% of generation costs in credits when other paying members download their creations.

If you submit a description identical to one of your own or another account’s active job, you join that job and pay once for it. That sharing ends when the job finishes: submitting again afterwards creates a new, chargeable job. Save the job ID and poll it instead of repeating the POST. The job’s download_url is a website-session route; API clients download with POST /v1/images/{id}/download.

Safe retries with Idempotency-Key. POST /v1/images/generate and POST /v1/batches accept an optional Idempotency-Key header (1–255 printable ASCII characters; a fresh UUID per logical request works well). Within 24 hours, retrying with the same key and the same body replays the first response with Idempotent-Replayed: true and no new charge, so an uncertain network response can be retried safely. Reusing a key with a different body or endpoint returns 422 idempotency_key_reused; a retry while the first request is still running returns 409 idempotency_in_progress with Retry-After. Successes and deterministic client errors such as 400 are stored; 5xx, 402, 408, 409 and 429 responses are not, so you can retry the same key after them. Keys are scoped to your account.

Filters

orientation
landscape, portrait, or square; aliases horizontal and vertical are accepted
tags
Up to 20 tags, each 1–80 characters after trimming; every supplied tag must match
collection
Collection slug from GET /v1/collections, 1–100 characters after trimming
aspect_ratio
16:9, 1:1, 4:3, 3:2, 9:16, 4:5 or all (also accepted at the top level)
resolution
1K (up to 2.5 MP), 2K (at least 2.5 MP), 4K (at least 6 MP) or all; aliases standard, hd, 4k
min_width / max_width
Width bounds in pixels
min_height / max_height
Height bounds in pixels
min_aspect_ratio / max_aspect_ratio
Numeric width ÷ height bounds
min_megapixels / max_megapixels
Original-resolution bounds
format
Original format: jpg, jpeg, png, webp, or avif

Pixel bounds must be positive integers; aspect-ratio bounds must be greater than zero and at most 10; megapixel bounds must be greater than zero and at most 500. Each minimum must not exceed its maximum. Unknown request or filter fields are rejected.

Current search behavior

Ranking blends weighted full-text relevance, exact phrase and metadata boosts, coverage of each requested visual concept, close visual vocabulary, and typo-tolerant word similarity. Detailed prompts therefore favor images that cover the whole scene rather than images that happen to repeat one keyword.

Each text-search result includes match_confidence, a bounded retrieval estimate from 0 to 0.99. Preserve the returned blended-relevance order; confidence is not the sole ordering key, a probability, or a guarantee of subjective fit. Filter-only browsing returns null because there is no query to compare.

Getting more results. session_id is null on a plain search, where page selects the slice. To walk through unseen matches instead, send your own UUID as session_id, or set shuffle: true and the response returns a new one. Reuse it with the same query and previously returned images are excluded, even across concurrent requests. When every match has been returned, the next call starts over and returns shuffle_cycle_restarted: true. Shuffle requires a nonblank query containing a letter or digit. Sessions expire after 24 hours of inactivity.

Ready, published images are searchable whether or not a human has reviewed them. A rejected image is hidden immediately.

Results expose only web and/or thumbnail previews. The top-level url selects web when available, otherwise thumbnail. Original dimensions describe the source, not the responsive preview. Preview URLs are same-origin, unsigned, edge-cached, and may be reused; store id as the durable identity. Private generation details are not returned; generation.provenance is always null.

The full-resolution original is authorized by POST /v1/images/{id}/download, with no body required. Success returns { data: { url, expires_at, owned: true }, request_id }. owned describes entitlement after this request, not whether credits were charged. Download the image from data.url without forwarding your API key. Do not log signed URLs.

Previously purchased photos remain downloadable even when your credit balance is zero. A fresh original URL still requires a valid API key and a currently deliverable image; existing ownership does not bypass publication or rate-limit checks.

The optional download_path in image metadata is a website-session helper under /api/images/, not an API-key endpoint. API clients must use the explicit /v1/ download route above.

Errors and rate limits

Errors include a stable machine code, human-readable message, and request ID. Authenticated responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Capacity protections may change while the service grows, so clients should not hardcode a request rate. Request-rate 429s (rate_limit_exceeded, creation_rate_limited) include Retry-After; allowance errors such as random_quota_exceeded tell you when the allowance resets instead. Handle 400 validation, 401 authentication, 402 credits, 404 image availability, and 5xx server failures separately.

Error response
{
  "error": {
    "code": "invalid_request",
    "message": "The search request body is invalid.",
    "request_id": "4df17ec1-10ef-4c88-99cf-37ce84ced788"
  }
}

Node.js quickstart

Download the tested Node.js quickstart. It fetches live pricing, performs one search, handles no matches, and authorizes one download. By default it only reads pricing. Credit-using mode requires both explicit opt-in and a PIX4LESS_MAX_CREDITS preflight budget; this is an estimate, not a server-side spending cap.

Terminal
node pix4less-quickstart.mjs
# After setting PIX4LESS_API_KEY and PIX4LESS_MAX_CREDITS securely:
node pix4less-quickstart.mjs --allow-credit-charges
your-server.mjs
// Save /examples/pix4less-quickstart.mjs beside your server script.
import { runQuickstart } from "./pix4less-quickstart.mjs";

// Defaults to a public price-book read: no key, search, or credit charge.
const { priceBook } = await runQuickstart();

// Only after you approve the current search + download cost:
const result = await runQuickstart({
  apiKey: process.env.PIX4LESS_API_KEY,
  allowCreditCharges: true,
  maxCredits: Number(process.env.PIX4LESS_MAX_CREDITS)
});

// result.download may be absent when search has no matches.
// Fetch result.download.url privately WITHOUT an API-key header.
// Do not log signed URLs. Store result.imageId to request a fresh URL.
// owned: true confirms entitlement, not whether credits were charged.

Read llms.txt · Read OpenAPI 3.1