Pixly Developer Docs

Everything Pixly's app can generate — virtual staging, photo enhancement, cinematic video — is callable by AI agents and scripts through one MCP endpoint, with an OAuth sign-in flow and a CLI on top. This page is the complete reference; the machine-readable mirror lives at /docs.md.

Getting started

The fastest path, end to end:

  1. Create an API key in Settings → API keys (shown once — copy it immediately). An active Pixly subscription is required.
  2. Connect a client (one-step setup per client) or install the CLI: npx pixly-cli help
  3. Ask for a staged room — or run pixly stage photo.jpg --style scandinavian

Generations spend the account's normal credit balance — same pipeline, quality, and pricing as the app, and every result also appears in the Pixly Library.

Authentication

Two credential types, both sent as Authorization: Bearer <token>:

  • API keys (pixly_sk_…) — for Claude Code, Cursor, scripts, and CI. Created in Settings, stored hashed, revocable instantly. Keys can never mint other keys.
  • OAuth 2.1 (pixly_at_… access tokens) — for clients with a sign-in flow, like claude.ai custom connectors. Public clients with PKCE S256 only; single-use authorization codes; refresh-token rotation.

OAuth surface (discovery starts from the 401 WWW-Authenticate header):

ParameterTypeRequiredDescription
GET /.well-known/oauth-authorization-servernoRFC 8414 authorization-server metadata (endpoints, PKCE methods, grant types)
GET /.well-known/oauth-protected-resource/api/mcpnoRFC 9728 protected-resource metadata — advertised in the 401 WWW-Authenticate header
POST /api/oauth/registernoRFC 7591 dynamic client registration (open; public clients; body: client_name, redirect_uris[])
GET /oauth/authorizenoUser consent page — query: response_type=code, client_id, redirect_uri, state, code_challenge, code_challenge_method=S256
POST /api/oauth/tokennoToken endpoint — grant_type authorization_code (code, code_verifier, client_id, redirect_uri) or refresh_token (rotates the pair). Form-encoded or JSON.

MCP endpoint

POST https://pixly.app/api/mcp

Model Context Protocol over streamable HTTP, stateless: single JSON responses, no SSE streams, no sessions. Protocol versions 2025-03-26 and 2025-06-18. Methods: initialize, tools/list, tools/call, ping; notifications return 202.

Example request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "virtual_staging",
    "arguments": {
      "r2Path": "users/<your-user-id>/staging/1754820000000-living-room.jpg",
      "style": "scandinavian",
      "numImages": 1
    }
  }
}

Example response — result.content[0].text is JSON (a job snapshot); tool failures set result.isError: true with an actionable message:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\n  \"jobId\": \"4bf4bb95-f5af-44d8-9508-65807f68636d\",\n  \"type\": \"image_staging\",\n  \"status\": \"processing\",\n  \"creditsCharged\": 1,\n  \"createdAt\": \"2026-08-10T20:07:08Z\",\n  \"note\": \"Still running — call get_job again in a few seconds.\"\n}"
      }
    ]
  }
}

Typical workflow

  1. Get the photo in: create_upload_ticket (local bytes — PUT to the returned uploadUrl) or upload_image_from_url. Both return an r2Path.
  2. Call a generation tool with that r2Path → job snapshot.
  3. Poll get_job until status: "completed" → download resultUrls. Image tools usually complete inline (up to ~2 min); videos take 1–5 minutes.

Tools reference

Generated from the live tool registry — this is exactly what tools/list returns.

virtual_staging

Furnish and style an empty (or badly furnished) room photo in a chosen interior style. The flagship tool. HD, watermark-free results. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)
stylestringyesStyle id from the Pixly styles catalog (lib/real-estate/styles.ts)
roomTypestringnoRoom type hint; omit to let vision infer it from the photo
customInstructionsstringnoOptional extra instructions blended into the staging prompt
numImagesinteger (default: 1)yesVariations to generate (1-4)
stagingQuality"standard" | "pro"nopro = higher-quality 2K tier at 2 credits/image

edit_staged_photo

Apply a specific change to a previously staged photo (swap the sofa, add a rug) while preserving everything else. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 path of the PREVIOUS staged result to edit
stylestringyesStyle id, used as context to match new elements
customInstructionsstringyesThe concrete edit to apply, e.g. "change the sofa to grey"
sourceJobIdstringnoJob the edited result came from (lineage)
sourceResultIndexintegernoWhich variation was edited

cinematic_motion

Turn a single listing photo into a short cinematic clip with a professional camera move (zoom, orbit, fly-through, crane up…). No second frame needed. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)
cameraMove"zoom" | "fly-through" | "orbit" | "pan" | "aerial" | "pull-back" | "crane-up" | "tilt-up" | "boom-down" | "drone-orbit" | "flyover" | "pull-away" | "handheld"yesCamera-move preset
durationSeconds5 | 10yesClip length; the routed model validates its supported tiers
format"9:16" | "16:9"yesAspect ratio

before_after_reel

Animate a before→after transformation (e.g. empty room → staged) into a social-ready reveal video from two frames. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
beforeR2PathstringyesStart frame (e.g. the empty room photo)
afterR2PathstringyesEnd frame (e.g. the staged result)
videoIntent"staging_reveal" | "staging_reveal_reverse" | "construction_timelapse"yes
revealStyle"smooth" | "slideIn" | "dropLand" | "glowBuild" | "movers"yesHow the transformation is revealed
durationSeconds5 | 10yes
format"9:16" | "16:9" | "1:1"yes

enhance_photo

Turn an amateur listing photo into a finished, professional real-estate photo (exposure, color, clarity). Returns 3 variants to pick from. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)

declutter_photo

Remove clutter, mess, and personal items from a listing photo while keeping the room, furniture, and architecture intact. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)

day_to_night

Turn a daytime listing photo into a magazine-style night scene — lights on, warm glow, dusk sky — with the building and camera angle unchanged. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)

plot_sign

Place a photorealistic 3D monument sign with your exact text (price, area, SOLD) onto a photo of an empty plot, matched to perspective and lighting. Costs credits from the user's Pixly balance.

ParameterTypeRequiredDescription
r2PathstringyesR2 object path of the uploaded source photo (from an upload-url ticket)
textstringyesSign label, verbatim — a price ("$1,200,000"), area ("800 m²"), or short word ("SOLD")
look"stone" | "metal" | "grass" | "sign"noSign material/style; defaults server-side
orientation"standing" | "lying"noLetter orientation (letter looks only); defaults server-side

upload_image_from_url

Import an image into Pixly from a URL. Returns the r2Path that every generation tool takes as its photo input. Use this first when the photo isn't already in Pixly.

ParameterTypeRequiredDescription
urlstringyesPublicly reachable image URL (JPG/PNG/WebP, max 10 MB) to import into Pixly

create_upload_ticket

Get a presigned upload URL for a LOCAL image file (when you have bytes, not a URL). PUT the file to uploadUrl with the same Content-Type, then pass the returned r2Path to a generation tool. Ticket expires in 1 hour.

ParameterTypeRequiredDescription
filenamestringyesOriginal filename, used for the extension
contentType"image/jpeg" | "image/png" | "image/webp"yesMIME type the PUT request will send

get_job

Check a generation job's status and fetch result URLs when it's done. Video jobs take 1-5 minutes — poll this with a few seconds between calls.

ParameterTypeRequiredDescription
jobIdstringyesJob id returned by a generation tool

list_library

List the user's recent generations (newest first).

ParameterTypeRequiredDescription
type"images" | "videos"noFilter by media type
limitinteger (default: 20)yes

get_credit_balance

The user's current Pixly credit balance and plan.

Jobs & results

Every generation tool and get_job return the same snapshot shape:

ParameterTypeRequiredDescription
jobIdstringyesJob id — pass to get_job to poll
type"image_staging" | "video_pair" | "video_tour"yesJob family
status"pending" | "processing" | "completed" | "failed"yesAnything not completed/failed is still running
creditsChargednumberyesCredits debited for this job
createdAtstring (ISO 8601)yesSubmission time
completedAtstring (ISO 8601)noPresent once finished
resultUrlsstring[]noPresigned download URLs (present when completed; valid 7 days)
errorstringnoFailure reason (failed jobs enter the 24h credit-refund review automatically)
notestringnoHint for agents, e.g. poll again in a few seconds

Result URLs are presigned and valid for 7 days; the generation itself stays in the user's Pixly Library permanently.

Errors & refunds

  • HTTP 401 — missing or invalid credential. The WWW-Authenticate header carries the OAuth resource-metadata URL so OAuth-capable clients discover the sign-in flow automatically.
  • JSON-RPC errors — -32700 parse, -32600 invalid request (batching is not supported), -32601 unknown method, -32602 invalid params, -32603 internal.
  • Tool errors result.isError: true with a message agents can act on: insufficient credits (with the amount needed), invalid input (with the exact field), or a source photo that's no longer available.
  • Refunds — a job that fails after the charge enters refund review automatically; credits return within 24 hours. No action needed.

CLI

npx pixly-cli help          # or: npm install -g pixly-cli
export PIXLY_API_KEY=pixly_sk_...

Node ≥ 18, zero dependencies. Local photo arguments upload automatically; results download to the current directory (--out to choose a path; multiple variations get -1, -2, … suffixes).

pixly stage <photo> --style <id>

Virtually stage a room photo. Local files upload automatically.

  • --style <id> (required) — style id, e.g. scandinavian, modern-luxury
  • --room <type> — room-type hint; omitted = inferred from the photo
  • --instructions <text> — extra instructions blended into the prompt
  • --variations <1-4> — number of variations (default 1)
  • --pro — 2K quality tier (2 credits/image)
  • --out <file.jpg> — output path (default: <name>-staged.jpg)
pixly enhance <photo>

Professional photo enhancement — returns 3 variants.

  • --out <file.jpg>
pixly declutter <photo>

Remove clutter and personal items.

  • --out <file.jpg>
pixly day-to-night <photo>

Turn a daytime photo into a night scene.

  • --out <file.jpg>
pixly plot-sign <photo> --text "SOLD"

Photorealistic 3D monument sign on an empty-plot photo.

  • --text <label> (required, max 24 chars)
  • --look stone|metal|grass|sign
  • --orientation standing|lying
  • --out <file.jpg>
pixly motion <photo>

Cinematic camera-move clip from a single photo.

  • --move zoom|fly-through|orbit|pan|aerial|pull-back|crane-up|tilt-up|boom-down|drone-orbit|flyover|pull-away|handheld
  • --duration 5|10 (default 5)
  • --format 9:16|16:9 (default 9:16)
  • --out <file.mp4>
pixly reel --before <a.jpg> --after <b.jpg>

Before→after reveal video from two frames.

  • --intent staging_reveal|staging_reveal_reverse|construction_timelapse
  • --reveal smooth|slideIn|dropLand|glowBuild|movers (default smooth)
  • --duration 5|10 · --format 9:16|16:9|1:1 · --out <file.mp4>
pixly job <jobId>

Job status + result URLs (JSON).

pixly jobs

Recent generations.

  • --limit <n> (default 20)
  • --type images|videos
pixly balance

Credits remaining and plan.

pixly tools

List every available tool.

For AI agents

This entire reference is available as pure markdown at https://pixly.app/docs.md (also linked from /llms.txt). To teach an agent Pixly in one message, paste this:

Connect to Pixly (real-estate photo & video AI) via MCP:
- Endpoint: https://pixly.app/api/mcp (streamable HTTP, stateless JSON responses)
- Auth: header "Authorization: Bearer pixly_sk_..." (user creates the key at https://pixly.app/app/settings) or OAuth sign-in
- Workflow: create_upload_ticket (local file) or upload_image_from_url → returns r2Path → call a generation tool (virtual_staging, enhance_photo, declutter_photo, day_to_night, plot_sign, cinematic_motion, before_after_reel, edit_staged_photo) → poll get_job until status "completed" → download resultUrls.
- Generations spend the user's Pixly credit balance (check with get_credit_balance). Failed jobs auto-refund within 24h.
- Full reference: https://pixly.app/docs.md