xpickle API

Generate images and video, manage your characters and gallery — over plain HTTPS + JSON. Requests act as your account with the same credits, plan limits, and content moderation as the app.

Authentication

Create a key under Account → API keys and send it on every request:

Authorization: Bearer xpk_...

The key is shown once at creation. Revoking it stops requests immediately. Base URL: https://app.xpickle.ai

Conventions

Account

GET/api/v1/me

Your plan tier, credit balance, and feature gates.

Returns: { tier, credits, features: { image, video, chat } }

GET/api/v1/costs

Credit price per paid action (image, chat, video_6s, video_12s, …).

Returns: { costs: { image: 5, chat: 1, ... } }

Characters

Your own creations plus characters you've collected from the library. Creating and editing runs the same moderation as the app.

GET/api/v1/characters

List your characters (own + collected). ?limit=100.

Returns: { characters: [{ id, name, gender, age, occupation, source: "own"|"collected", ... }] }

POST/api/v1/characters

Create a character from a profile sheet.

Body: { name, gender?, race?, age?, height?, hair_color?, eye_color?, skin_tone?, breast_size?, piercings?, body_type?, face_description?, appearance?, temperament?, occupation?, location?, kinks?, taboos?, interests?, disinterests? }

Returns: { id }

GET/api/v1/characters/:id

Full profile sheet (owner or collector). Anchor image URLs are owner-only.

PATCH/api/v1/characters/:id

Edit the sheet (creator only; re-moderated when published).

DELETE/api/v1/characters/:id

Delete a character.

Body: { mode: "keep-access" | "everyone" }

POST/api/v1/characters/:id/publish

Set library visibility and pricing (creator only).

Body: { visibility: "private"|"public"|"premium", price_model?, price_credits? }

POST/api/v1/characters/:id/collect

Add a library character to your collection.

Credits: Premium characters debit the publisher's list price.

DELETE/api/v1/characters/:id/collect

Remove from your collection (no refund).

POST/api/v1/characters/:id/anchor

Generate a reference anchor (creator only; slow — up to ~4 min).

Body: { kind: "face" | "clothed" | "nude" }

Returns: { url }

GET / POST/api/v1/characters/:id/anchor/history

List stored anchor versions / restore one (POST { kind, url }). Creator only.

POST/api/v1/characters/:id/profile-selfies

Generate the character's two profile selfies (creator only; slow).

Images

Async image generation (Qwen-Image-Edit-Rapid). Submit, then poll.

POST/api/v1/images

Submit a generation. 0 reference images = text-to-image; 1-3 = reference edit. Reference URLs must be this app's storage URLs (your uploads or prior generations). Prompt is moderated.

Body: { prompt, images?: [{ name, url }] , width?, height? (256-2048, multiples of 16), seed?, steps?, cfg?, negativePrompt?, batchSize? (1-4), characterIds? }

Returns: { generation: { id, status: "pending" } }

Credits: 1 × image per image (batchSize debits per variation).

GET/api/v1/images/:id

Poll a generation — also finalizes the finished job, so poll this (not the list). Failed jobs auto-refund.

Returns: { generation: { id, status: "pending"|"done"|"failed", url } }

GET/api/v1/images

Your gallery (finished images). ?character=<id>&since=<ISO>.

DELETE/api/v1/images/:id

Delete an image.

PATCH/api/v1/images/:id

Favorite / move to folder.

Body: { favorite?: true, folderId?: "<uuid>" | null }

POST / DELETE/api/v1/images/loras

Load an image LoRA from a Civitai/HF URL (POST { url, token? }) / remove one (DELETE { id }).

Videos

Video generation requires a paid plan (403 on free tier).

POST/api/v1/videos

Submit a clip. Backends: wan22 (default), hunyuan (needs startImageUrl), wan-rapid, wan-enhanced. Prompt is moderated.

Body: { prompt?, negative?, startImageUrl?, endImageUrl?, backend?, width?, height?, frames?, fps?, seconds? (6|12 — drives pricing), steps?, cfg?, seed?, tier? }

Returns: { clip: { id, status: "processing" } }

Credits: 1 × video_6s or video_12s by clip length. Failed jobs auto-refund.

GET/api/v1/videos/:id

Poll a clip — finalizes the finished job; returns video_url + poster_url when done.

GET/api/v1/videos

List your clips, newest first. ?limit=50.

DELETE/api/v1/videos/:id

Delete a clip.

PATCH/api/v1/videos/:id

Favorite / move to folder.

Body: { favorite?: true, folderId?: "<uuid>" | null }

POST / DELETE/api/v1/videos/folders

Create (POST { name }) / delete (DELETE { id }) a video folder.

POST / DELETE/api/v1/videos/loras

Load a video LoRA (POST { url, backend?, token? }) / remove one (DELETE { id }).

Uploads & folders

GET/api/v1/uploads

List your uploaded reference images.

POST/api/v1/uploads

Upload a reference image (base64 PNG/JPEG). The returned URL works as an image-gen reference or a video start frame.

Body: { dataBase64, name? }

Returns: { id, url }

DELETE/api/v1/uploads

Delete uploads.

Body: { id } or { ids: [...] }

GET / POST / DELETE/api/v1/folders

List / create ({ name }) / delete ({ id }) image-gallery folders.

Example: generate an image

# Submit (debits image credits)
curl -X POST https://app.xpickle.ai/api/v1/images \
  -H "Authorization: Bearer $XPICKLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "portrait of a redhead in golden hour light", "width": 768, "height": 1344}'
# → { "generation": { "id": "GEN_ID", "status": "pending" } }

# Poll until done
curl https://app.xpickle.ai/api/v1/images/$GEN_ID \
  -H "Authorization: Bearer $XPICKLE_API_KEY"
# → { "generation": { "status": "done", "url": "https://..." } }

Chat is not available over the API. Multipart-only flows (video frame upload, clip re-timing) are covered by /api/v1/uploads base64 uploads.