# Pikes documentation

Every public Pikes documentation page, concatenated. Generated 2026-09-13.
Individual pages: https://pikes.ai/docs/workflows · https://pikes.ai/docs/api · https://pikes.ai/docs/mcp · https://pikes.ai/docs/ai

---

<!-- Pikes product workflows — https://pikes.ai/docs/workflows -->

# Pikes product workflows

Setup instructions for creating assets with Pikes and using them in your existing tools. For current plans and credit allowances, see [pricing](https://pikes.ai/pricing).

## From a Claude brief to a Pikes asset

Claude can call Pikes image and video tools through the remote MCP server. Pikes uses your product references and saved brand context to guide generation; check the result before using it in a campaign.

1. Create a Pikes account and add product reference images and brand guidance. Generation consumes Pikes credits.
2. Connect https://pikes.ai/mcp in a supported MCP client and authorize access to Pikes. The connection guide includes Claude desktop, web and Claude Code setup.
3. Ask Claude to find the relevant product and generate a specific scene or creative variation. Include the intended format, placement and constraints.
4. Review the returned asset and its product details. For major changes, start again from the original reference: repeated edits can compound distortion.

[MCP setup and authentication](/docs/mcp) · [AI workflow and limitations](/docs/ai) · [API tools and parameters](/docs/api)

## Turn product references into ad variations

Start with an actual SKU photo, your brand guidance and a clear creative brief. Generate several compositions, review product fidelity and prepare the selected assets for your advertising workflow.

1. Upload a clear product reference and describe the audience, scene, offer and intended placement.
2. Generate variations in the image or video workflow. Set the aspect ratio for the placement and keep room for copy and interface overlays.
3. Review labels, packaging, generated text and claims. Check the current placement requirements in Meta Ads Manager before export.
4. Export approved assets and complete ad setup, targeting, budget and publication in Meta Ads Manager. Pikes creative generation and performance analysis do not by themselves publish a campaign.

[Generation limits and formats](/docs/api) · [Pricing and credit use](/pricing) · [Product content examples](/examples)

## Product photography with a review step

Use product references to create studio-style and lifestyle images for a product detail page. Reference-based generation guides the model toward your product; it does not guarantee identical labels, colors or packaging in every output.

1. Start with a clear, unobstructed photo of the actual product.
2. Describe the background, lighting, camera angle and intended crop.
3. Compare the generated image with the reference, including small text and packaging geometry.
4. Export approved results. Regenerate or edit failures, allowing for the additional credit cost.

[Workflow limitations](/docs/ai) · [Pricing and credits](/pricing)

## Bring Pikes images into your Figma file

The Pikes AI plugin connects your Pikes account to a Figma design file. Browse available images in the plugin or send a selected batch from Pikes, then place those images on the canvas for your design work.

1. Open the Pikes AI plugin in Figma and connect the Pikes account that holds your assets. Contact Pikes if you need the installation details.
2. Keep the plugin open in the target design file. Select one or more images in Pikes and choose Add to Figma, or browse the images available in the plugin.
3. Place the images on the current Figma canvas. Imported assets are image layers arranged for you to position in your layout.
4. Use Figma to add typography, vectors and layout. Importing a generated image does not turn its text or objects into editable vector layers.

[Get plugin installation help](mailto:leo@pikes.ai) · [Pricing and credits](/pricing) · [Create product photos](/for/pdp)

---

<!-- Pikes API Reference — https://pikes.ai/docs/api -->

# Pikes API Reference

Base URL: `https://pikes.ai`

There are two ways into Pikes programmatically, and they run the same tools over the same account:

| | Use it for | Auth |
|---|---|---|
| **MCP server** — `POST /mcp` | Agent clients (Claude, ChatGPT connectors, anything speaking MCP) | OAuth 2.1, or an API key as a bearer token |
| **REST tool calls** — `POST /mcp/tools/:toolName` | Your own orchestration layer; no MCP client needed | API key |
| **Product-shot endpoints** — `POST /api/product-shot` | One-shot product photography from a file upload | API key |

Every call runs as a Pikes **user** and spends that user's credits. There is no team- or org-level credential today; see [Workspace scoping](#workspace-scoping) before you plan around it.

- MCP protocol: **2025-06-18** (also accepts `2024-11-05`)
- Transports: `streamable_http`, `http_sse`
- OAuth scopes: `generate_image`, `edit_image`, `expand_image`, `read_images`
- Published at [https://pikes.ai/docs/api](https://pikes.ai/docs/api), linked from Settings → API and Settings → Claude / MCP
- Verified against `https://pikes.ai` on 2026-08-25

These facts and the tool catalogue below are written by `server/__tests__/api-surface-probe.js` from a live server — see [Verifying this document](#verifying-this-document).

---

## Authentication

### OAuth 2.1 (MCP clients)

Standard discovery — point a compliant MCP client at `https://pikes.ai/mcp` and it will find everything itself:

- `GET /.well-known/oauth-authorization-server`
- `GET /.well-known/oauth-protected-resource`

| Endpoint | Purpose |
|---|---|
| `POST /mcp/oauth/register` | Dynamic client registration (RFC 7591) |
| `POST /mcp/oauth/authorize` | Authorization code |
| `POST /mcp/oauth/token` | Token exchange / refresh |
| `POST /mcp/oauth/revoke` | Revocation |

PKCE is required (`S256`). Grants: `authorization_code`, `refresh_token`. Scopes: `generate_image`, `edit_image`, `expand_image`, `read_images`.

### API keys (headless)

Keys look like `psk_…`, are stored only as a SHA-256 hash, and are accepted two ways:

```
Authorization: Bearer psk_…
x-api-key: psk_…
```

Create one in the app under **Settings → API** (or **Settings → Claude / MCP** for a key you'll paste into an MCP client), or over the API. Key management is authenticated by the **user's session JWT**, never by a key — a key cannot mint or revoke keys.

```bash
# Create
curl -X POST https://pikes.ai/api/keys \
  -H "Authorization: Bearer <SUPABASE_SESSION_JWT>" \
  -H "Content-Type: application/json" \
  -d '{"name": "orchestrator"}'

# → { "success": true, "key": { "id": "...", "name": "orchestrator",
#     "keyPrefix": "psk_754fed7b...", "rawKey": "psk_…", "createdAt": "..." } }
```

`rawKey` is returned **once**. Store it then; it cannot be read back.

```bash
curl https://pikes.ai/api/keys -H "Authorization: Bearer <JWT>"          # list (metadata only)
curl -X DELETE https://pikes.ai/api/keys/<keyId> -H "Authorization: Bearer <JWT>"   # revoke
```

Listing returns `id`, `name`, `key_prefix`, `created_at`, `last_used_at`, `revoked` — never key material. Revoking a key you don't own returns `404`.

**Scope difference worth knowing:** API-key calls carry `generate_image`, `edit_image`, `expand_image`. OAuth additionally carries `read_images`.

---

## REST tool calls

`POST /mcp/tools/:toolName` — the whole tool catalogue as ordinary HTTP. The body is the tool's arguments; no JSON-RPC envelope.

```bash
curl -X POST https://pikes.ai/mcp/tools/generate_image \
  -H "x-api-key: psk_…" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Amber supplement bottle on warm marble, soft window light",
    "aspectRatio": "4:5",
    "model": "consistency_pro",
    "resolution": "2K"
  }'
```

Responses come back in MCP content-block form. The payload is JSON encoded inside `text`:

```json
{ "content": [ { "type": "text", "text": "{\"success\":true,\"images\":[…]}" } ] }
```

Tool-level failures return HTTP `200` with `"isError": true` and the reason in the same block — check `isError`, not just the status code:

```json
{ "content": [ { "type": "text", "text": "{\"success\":false,\"error\":\"Could not fetch account info\"}" } ], "isError": true }
```

Missing or bad credentials return `401`:

```json
{ "error": "Unauthorized",
  "message": "OAuth token or API key required. Authorize at /mcp/oauth/authorize or use x-api-key header" }
```

---

## MCP transport

- `POST /mcp` — Streamable HTTP, JSON-RPC 2.0 (`initialize`, `tools/list`, `tools/call`, `resources/*`, `prompts/*`). Protocol `2025-06-18`, with `2024-11-05` still accepted.
- `POST /mcp/sse` + `POST /mcp/message` — the deprecated SSE transport, kept for older clients.
- `GET /mcp` — server info: transports, auth URLs, and the live tool list.

Discovery is open on purpose: `initialize` and `tools/list` answer without credentials, so a client can inspect the catalogue before anyone authorizes it. Executing a tool always needs one.

```bash
curl -X POST https://pikes.ai/mcp \
  -H "Authorization: Bearer psk_…" -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

Claude Code, for reference:

```bash
claude mcp add --transport http pikes-ai https://pikes.ai/mcp
```

---

## Tool catalogue

29 tools, as reported by `tools/list`.

**Image and video**

| Tool | Description |
|---|---|
| `generate_image` | Generate a new image from scratch using a text prompt. Use this when the user wants to create a completely new image without any input images. |
| `edit_image` | Edit or modify existing images based on instructions. Supports single image editing AND multi-image combining (e.g. placing a product into a scene). For single image: pass imageUrl. For combining images: pass imageUrls — first image is the product/main subject, last image is the scene/context, middle images are style references. Provide exactly one of imageUrl or imageUrls. This replaces the old remix_images tool. |
| `expand_image` | Extend or outpaint an image's canvas to a new aspect ratio or size. The expansion is content-aware but NOT steerable: the underlying model (Ideogram Reframe) fills the new canvas from the source image alone — there is no directional control and no prompt guidance. Use edit_image if the user wants specific new content added around the image. |
| `animate_image` | Animate a still image into a short video. Picks between several models via the `model` param: |
| `remove_background` | Remove the background from a product image, returning a transparent PNG. Use this when the user wants to isolate a product, cut out the background, or get a transparent version of an image. |
| `upload_image` | Upload an image to get a publicly accessible URL for use with edit_image, expand_image, etc. |

**Async jobs**

| Tool | Description |
|---|---|
| `submit_image_job` | Start an image/video generation ASYNCHRONOUSLY and return a jobId immediately (does NOT wait for the render). Use this instead of generate_image/edit_image when you want to avoid long waits/timeouts on 4K or video, run several jobs in parallel, or build a pipeline. After submitting, poll get_image_job with the returned jobId until status is "completed", then use the result URLs (e.g. feed one into another submit_image_job with tool="edit_image"). For tool="animate_image", pick the video model via videoModel (NOT model) and use duration/resolution/endImageUrl/generateAudio/videoUrls/audioUrls as with the sync animate_image tool. Credits are charged once, when the job runs. |
| `get_image_job` | Retrieve a job submitted with submit_image_job. Returns status ("processing" \| "completed" \| "failed" \| "timed_out"), progress, and — when completed — the result images/videos with downloadable URLs. Poll until status is "completed" (or "failed"/"timed_out"). On "completed", results[] contains { assetId, url, width, height, aspectRatio, assetType }. |

**Products, brand and account**

| Tool | Description |
|---|---|
| `get_product_images` | Search the user's saved product library and return image URLs. Call this tool IMMEDIATELY — without asking the user first — whenever they mention a product by name or reference (e.g. "the t-shirt", "my sneakers", "the coffee bag", "possible t shirt", "that product"). Do NOT ask the user to upload an image or confirm — just call this tool. The returned URLs can be passed directly to edit_image. |
| `fetch_products_from_website` | Fetch product images directly from a brand's website. Use this when the user gives a website URL or domain, or asks to grab/import/pull products FROM a site (e.g. "grab the products from acme.com"). Do NOT use it for products already in the user's library — use get_product_images for those; if get_product_images finds nothing and the user has mentioned their website, call this. Works only on Shopify-powered stores (most DTC brands are); non-Shopify sites return a no-products error. By default it also saves the found products into the user's product library; set save_to_library to false only if the user explicitly wants a look without importing. Returns product titles and image URLs you can pass straight to edit_image. |
| `get_all_context` | Retrieve all context files (brand knowledge, guidelines, campaign rules, etc.) with full content. Use when the injected context was truncated or you need inactive files. Context files are the user's persistent brand knowledge base. |
| `update_context` | Update or create a context file. Context files store persistent brand knowledge (voice, memory, colors, campaign rules, audience info, etc.). If a file with this name exists, its content is replaced. If not, a new file is created. When updating, rewrite the full content with your changes incorporated. |
| `get_account_info` | Get the user's account information including credits remaining, subscription plan, and usage. Use when the user asks about their account, credits, or usage. |

**Boards**

| Tool | Description |
|---|---|
| `list_boards` | List the user's image boards. Use this BEFORE add_images_to_board or update_board to find an existing board's id, or to confirm a board with that name doesn't already exist before calling create_board. Includes personal boards and any team boards the user has access to. Returns: id, name, description, is_public, team_ids, image_count. |
| `get_board_images` | Read the images on a board and return their downloadable URLs + metadata. Identify the board by boardId (preferred — use list_boards to find it) or by name (returns the most recently updated board you can access with that name). Returns each image's url, videoUrl (for videos), width/height/aspectRatio, assetId, name (display name), model, source, origin, prompt, assetType, and position, plus the board's namingTemplate. `origin` is "upload" (the user put it on the board) or "generated" (Pikes made it) — boards mix both, since generated results are saved back onto the board holding the references. When sourcing a product shot or style reference to feed into edit_image / submit_image_job, filter to origin "upload": reusing a generated image as a source compounds its distortions. `prompt` is the generation prompt that created the image (empty for uploads) — to recreate a similar shot, start from that prompt and adapt it. |
| `create_board` | Create a new image board. Returns the board id — pass it to add_images_to_board next. Visibility defaults to "private"; pass "team" + teamIds to share with one or more teams, or "public" to make the board world-readable. Public boards return share_url (https://pikes.ai/b/<id>) — when sharing a link, use that exact URL; never construct board URLs yourself. |
| `update_board` | Edit an existing board's name, description, or visibility. Only the board owner can update. To change visibility, pass the new "visibility" value (and teamIds when switching to "team"). Pass null for fields to leave unchanged. Boards cannot be deleted via MCP. Public boards return share_url (https://pikes.ai/b/<id>) — when sharing a link, use that exact URL; never construct board URLs yourself. |
| `add_images_to_board` | Add one or more images to a board. Pass assetId(s) from generate_image / edit_image / expand_image ("id" field), OR image URL(s) via publicUrl/publicUrls — Pikes URLs are linked directly, and EXTERNAL http(s) image URLs (e.g. find_ads ad stills, web images) are automatically fetched and re-hosted as the user's assets. Do not run a dummy edit_image just to get an id. The user must be the board owner or a team member with write access. |
| `batch_rename_assets` | Rename assets on a board (sets each asset's display name — storage URLs never change). Flow: get_board_images first (returns name/model/source/prompt per image), derive a short concept name per image from its prompt/content, then ALWAYS show the user the proposed old → new rename table and wait for confirmation BEFORE calling this tool. Names: lowercase, hyphens inside, underscores between fields, no spaces. This renames the global asset name (visible everywhere); for per-download filename conventions set the board's namingTemplate via update_board instead. |
| `list_teams` | List the teams the user is a member of. Use this when the user asks to share a board with a team — you need the team id to pass to create_board / update_board with visibility="team". |

**Research**

| Tool | Description |
|---|---|
| `find_ads` | Search Foreplay's ad library for real ads from any brand/competitor — for INSPIRATION and competitive research, NOT as generation inputs. Signature use: find a competitor's (or a niche's) ads that have run a LONG time, which signals the creative is likely working ("winning ads") — set sort:"longest_running", live:true, minRunningDays (30=working, 60/90=proven). Also browse by keyword/theme, niche, format, or platform. Returns ad image stills + metadata (brand, days running, headline, CTA). Analyze their composition, then create with the user's OWN product — do NOT pass the returned ad URLs into edit_image as the product. |

**Meta Ads and everything else**

| Tool | Description |
|---|---|
| `meta_get_ad_accounts` | List all Meta ad accounts the user has access to. Returns account ID, name, currency, and status. Call this first to get the accountId needed for other Meta tools. |
| `meta_get_ad_comments` | Read user comments on a Meta ad — Facebook AND Instagram. Resolves the ad to its underlying post automatically (works on dark/unpublished posts too), so pass an adId from meta_get_ads, NOT a post id. |
| `meta_get_ad_creative` | Get just the creative assets for a specific ad by ID. Use this when you already know the ad_id and only need the creative (not metrics). |
| `meta_get_ad_insights` | Get detailed performance insights with conversions, ROAS, and breakdowns. |
| `meta_get_ads` | Get ads with creative assets, performance metrics, conversions, and ROAS in a single call. |
| `meta_get_audience_breakdowns` | Get available audience and delivery segment rows for specific ads. |
| `meta_get_campaigns` | List campaigns for an ad account. Returns campaign ID, name, objective, status, budget, and date range. |
| `meta_get_page_comments` | Read user comments on a Facebook Page's ORGANIC posts (posts that were never run as ads). Use alongside meta_get_ad_comments for full voice-of-customer coverage. Pass a pageId (e.g. the pageId returned by meta_get_ad_comments, or the part before the underscore in an effective_object_story_id). Returns comments tagged source:"organic". Requires that the user administers the page. |

`GET /mcp` returns the same list with full schemas.

### Common parameters

| Parameter | Values |
|---|---|
| `aspectRatio` | `auto`, `21:9`, `16:9`, `3:2`, `4:3`, `5:4`, `1:1`, `4:5`, `3:4`, `2:3`, `9:16` (default `9:16`) |
| `resolution` | `1K`, `2K`, `4K` — for `consistency_pro` these map to quality `low` / `medium` / `high` |
| `model` | `creativity_pro` (Google Nano Banana Pro, default) and `consistency_pro` (OpenAI GPT Image 2 — stronger text and label fidelity) are the two to reach for. Also accepted: `creativity_fast`, `creativity_light`, `flux_krea`, `ideogram_v3`, `ideogram_v4`, `google_edit`, `google_edit_pro`, `gpt_image_2_edit` |
| `imageCount` | 1–4 (default 1) |
| `imageUrls` | up to 9 reference images on `edit_image` |

Product identity is reference-conditioned, not fine-tuned: pass the actual pack shots as `imageUrls` (or let `get_product_images` fetch them from the product library) and the model works from those pixels. New packaging = new reference images, no retraining step.

### Long renders

4K and video can outrun an HTTP timeout. Submit and poll instead:

```bash
curl -X POST https://pikes.ai/mcp/tools/submit_image_job \
  -H "x-api-key: psk_…" -H "Content-Type: application/json" \
  -d '{"tool":"generate_image","prompt":"…","resolution":"4K"}'
# → jobId

curl -X POST https://pikes.ai/mcp/tools/get_image_job \
  -H "x-api-key: psk_…" -H "Content-Type: application/json" \
  -d '{"jobId":"…"}'
```

Credits are charged once, when the job runs. Jobs are scoped to the caller.

---

## Product-shot endpoints

Two multipart endpoints for the simplest case — send a file, get a finished shot.

```bash
curl -X POST https://pikes.ai/api/product-shot \
  -H "x-api-key: psk_…" \
  -F "image=@bottle.jpg" \
  -F "aspect_ratio=4:5" \
  -F "resolution=4K"
```

| | `/api/product-shot` | `/api/product-shot-custom` |
|---|---|---|
| Prompt | Fixed studio product-photography prompt | Your `prompt` field (required) |
| `aspect_ratio` | `auto` (default) or any ratio above | same |
| `resolution` | `1K` (default) or `4K` | same |

`1K` runs Nano Banana; `4K` runs Nano Banana Pro. Success:

```json
{ "success": true, "image": { "url": "…" }, "creditsUsed": 12 }
```

Cost today: **6 credits** at `1K`, **12 credits** at `4K`. Rate limit: **30 requests per minute per key**. Credits are pre-charged and refunded automatically if the render fails.

---

## Errors

| Status | Meaning |
|---|---|
| `400` | Validation — missing prompt, bad `aspect_ratio`, unknown `resolution`, `imageCount` out of range |
| `401` | No/invalid/revoked credential |
| `402` | Insufficient credits, or no active subscription — body carries the shortfall detail |
| `404` | Not found, or not yours (revoking someone else's key looks like this on purpose) |
| `429` | Rate limited (product-shot endpoints) |
| `500` | Render or server failure — pre-charged credits are refunded |

MCP tool calls that fail for content or upstream reasons return `200` with `isError: true` rather than an HTTP error.

Only the product-shot endpoints are rate limited today. On `/mcp` and `/mcp/tools/*` the practical ceiling is the account's credit balance — build your own backoff if you fan out hard.

---

## Workspace scoping

A credential identifies **one user**, and calls execute in that user's personal workspace: assets created over the API land with no team attached, whatever teams the user belongs to. `list_teams` exists so a board can be shared with a team after the fact, but there is no way to say "run this call as the ACME workspace."

Practical consequences for a multi-seat evaluation:

- Two users running the same brief will not see each other's product library or Context unless those were created in a shared team through the app.
- Assets generated headlessly won't appear in a team workspace by themselves.

If a connection that belongs to a team rather than a person is a requirement, treat it as a roadmap item, not a configuration flag.

---

## Verifying this document

`server/__tests__/api-surface-probe.js` exercises this surface end to end and rewrites the generated blocks above from what the server answered, so the doc cannot quietly drift from the API.

```bash
# against a local server (PORT=5099 node -r ./__tests__/boot-stub.js index.js)
node server/__tests__/api-surface-probe.js

# against production, no account needed — discovery, transport, auth negatives
node server/__tests__/api-surface-probe.js --base https://pikes.ai --quick

# refresh the generated blocks in this file
node server/__tests__/api-surface-probe.js --write-docs

# include one real 1K render (~6 credits)
node server/__tests__/api-surface-probe.js --generate
```

It covers discovery and PKCE advertisement, the auth negatives (no credential, bogus key, minting a key without a session), the key lifecycle across two accounts including cross-account revoke, `initialize` and `tools/list`, a REST tool call and its content-block envelope, revocation actually killing a key, and whether every live tool is documented here. A full run creates two throwaway users and deletes them; `--quick` creates nothing. Exit code is non-zero on any failure, so it drops straight into a loop or a scheduled check.

---

## Data and billing notes

- Generated assets are stored in the caller's Pikes library and are retrievable through the board and asset tools.
- Credits are charged per generation, by model and resolution; `creditsUsed` is returned where a call charges directly. A failed render is refunded.
- Data governance, incident response, and third-party risk policies live in `docs/policies/`.

---

<!-- Pikes MCP Server — https://pikes.ai/docs/mcp -->

# Pikes MCP Server

Connect Claude, ChatGPT, Cursor — anything that speaks the Model Context
Protocol — to the Pikes image tools. The agent generates, edits, animates and
files images in the user's own Pikes account, spending that account's credits.

```
https://pikes.ai/mcp
```

Protocol `2025-06-18` (also accepts `2024-11-05`), Streamable HTTP with SSE for
streaming responses. The server identifies itself as `pikes-ai`, titled
**Pikes**, with PNG icons and a website URL so a client can show a proper
connector card rather than a bare string, and advertises three capabilities — **tools**, **prompts** and **resources**, each with
`listChanged`. The full tool catalogue, parameters and error codes live in the
[API reference](/docs/api).

| Method | Transport |
| --- | --- |
| `POST /mcp` | JSON-RPC messages |
| `GET /mcp` | SSE stream for server-initiated messages |
| `DELETE /mcp` | End a session (send the session id you were given) |

## Connect

### Claude (desktop or claude.ai)

1. [Install Pikes for Claude](https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Pikes&connectorUrl=https%3A%2F%2Fpikes.ai%2Fmcp).
2. Review the prefilled name (`Pikes`) and remote MCP URL (`https://pikes.ai/mcp`), then continue.
3. Authorize when prompted — the OAuth screen signs you into Pikes and hands the
   connector a scoped token. No API key to paste, nothing to rotate by hand.

### Claude Code / Cursor

```bash
claude mcp add --transport http pikes https://pikes.ai/mcp
```

Or in `.mcp.json`:

```json
{
  "mcpServers": {
    "pikes": {
      "type": "http",
      "url": "https://pikes.ai/mcp"
    }
  }
}
```

### ChatGPT

Add `https://pikes.ai/mcp` as a custom connector and authorize the same way.

## Authentication

**OAuth 2.1 (preferred).** Point the client at `https://pikes.ai/mcp` and it
discovers everything it needs:

```
GET /.well-known/oauth-authorization-server
GET /.well-known/oauth-protected-resource
```

PKCE (S256) is required. Clients that register themselves do so through
`POST /mcp/oauth/register` (RFC 7591); the rest of the flow runs through
`/mcp/oauth/authorize`, `/mcp/oauth/token` and `/mcp/oauth/revoke`. Scopes:
`generate_image`, `edit_image`, `expand_image`, `read_images`.

**API key.** For clients that can't complete OAuth, create a key under
**Settings → Claude / MCP** in the app and send it as either header:

```
Authorization: Bearer psk_…
x-api-key: psk_…
```

A key carries the full rights of the user who made it, so treat it like a
password: keys are stored only as a SHA-256 hash and can be revoked at any time
from the same screen.

## What the agent gets

| Group | Tools |
| --- | --- |
| Generate & edit | `generate_image`, `edit_image`, `expand_image`, `remove_background`, `upload_image` |
| Video | `animate_image` |
| Audio & voices | `generate_speech`, `generate_sound`, `generate_music`, `design_voice`, `list_voices` |
| Long renders | `submit_image_job`, `get_image_job` (returns a job id instantly; poll it) |
| Products & brand context | `get_product_images`, `fetch_products_from_website`, `get_all_context`, `update_context`, `get_account_info` |
| Boards | `list_boards`, `get_board_images`, `create_board`, `update_board`, `add_images_to_board`, `batch_rename_assets`, `list_teams` |
| Asset library & brand | `search_assets`, `list_asset_folders`, `create_asset_folder`, `file_assets_in_folder`, `get_brand_colors`, `save_brand_colors`, `save_product`, `set_naming_convention`, `manage_folders`, `manage_context_folders` |
| Presentation | `present_results` (all result types) |
| Research & Meta ads | `find_ads`, `meta_get_ads`, `meta_get_ad_insights`, `meta_get_ad_creative`, `meta_get_campaigns`, `meta_get_ad_comments`, `meta_get_page_comments`, `meta_get_audience_breakdowns`, `meta_get_ad_accounts` |

Every tool's parameters and defaults are documented in the
[API reference](/docs/api#tool-catalogue). Meta tools need the user's Meta
account connected in Pikes first.

Each tool ships a display title and the standard MCP annotations, so a client
knows what it is dealing with before it calls. Read tools carry `readOnlyHint`;
generation tools declare themselves as writes that are
not idempotent — the same prompt twice is two images and two charges — and
`update_context` and `batch_rename_assets` are marked `destructiveHint`,
because both replace what was there.

### Prompts

Four ready-made prompts, each taking arguments the client fills in:

| Prompt | Arguments |
| --- | --- |
| `product_photography` | `product_description` (required), `style`, `background` |
| `social_media_ad` | `product_or_service` (required), `platform`, `mood` |
| `brand_lifestyle` | `brand_values` (required), `target_audience`, `visual_style` |
| `product_on_model` | `product_image_url` (required), `context` (required), `style` |

### Resources

Once the connection is authorized, `resources/list` returns the account's own
material plus the shared interactive result view:

| Resource | What it is |
| --- | --- |
| `pikes://images/recent` | The account's recent generations |
| `pikes://images/<id>` | One generation, by id |
| `pikes://brand-profiles/active` | The active brand context (voice, colours, guidelines) |
| `pikes://brand-profiles/list` | A summary of that context |
| `ui://pikes/results-v2` | MCP App: media, voices, boards, products, context, jobs, colors, and ad data |
| `ui://pikes/image-viewer` | Compatibility alias for the shared result view |
| `ui://pikes/ad-preview` | Compatibility alias for the shared result view |

The `ui://` entries are MCP Apps (`text/html;profile=mcp-app`). Media creation
returns the view directly. Read and intermediate write tools return complete
`structuredContent` plus their existing text fallback, so agents can analyze and
chain results without repeatedly opening an iframe. Call `present_results` with
a source tool name and its result object to show the final selection. It supports
every advertised source tool and never executes that tool again.

The app uses the standard MCP Apps bridge and a self-contained HTML resource
(no external JavaScript dependency). It follows the host theme, reports its
content height, loads media on demand, and uses explicit host capabilities for
links, downloads, follow-up messages, and read-only job polling. A missing
capability leaves a usable fallback. No button generates or mutates saved data
automatically. A failed host action is shown inline, and cancellation stops job
polling. See [MCP app QA](mcp-app-qa.md) for the repeatable local check loop.

If a host caches the tool catalogue, refresh/reconnect Pikes once after upgrading
to discover `present_results`. Existing resource URIs remain supported.

### Everything answers 401 until you sign in

`initialize`, `tools/list` and `prompts/list` all return `401` without a
credential, carrying the challenge a client needs to build its sign-in link:

```
WWW-Authenticate: Bearer error="invalid_token",
  error_description="Authorization required",
  resource_metadata="https://pikes.ai/.well-known/oauth-protected-resource/mcp"
```

The JSON-RPC body carries the same thing in a form code can read — a stable
`data.code` of `auth_required` plus absolute `resource_metadata`,
`authorization_endpoint` and `registration_endpoint` URLs.

Protected Resource Metadata (RFC 9728) is served at every shape a client tries:
`/.well-known/oauth-protected-resource`, the path-inserted
`/.well-known/oauth-protected-resource/mcp`, and
`/mcp/.well-known/oauth-protected-resource`. Authorization server metadata
likewise answers at `/.well-known/oauth-authorization-server`, `…/mcp`, and
`/mcp/.well-known/oauth-authorization-server`.

## Calling a tool over plain HTTP

An orchestration layer that doesn't want an MCP client can call the same tools
directly — same auth, same arguments, JSON in and out:

```bash
curl -X POST https://pikes.ai/mcp/tools/generate_image \
  -H "x-api-key: psk_…" -H "Content-Type: application/json" \
  -d '{"prompt":"a matte black bottle on wet stone","aspectRatio":"4:5","resolution":"2K"}'
```

## When something fails

| Status | What it means |
| --- | --- |
| `401` | No credential, or a revoked/invalid key — the body names the header to use |
| `402` | Out of credits, or no active subscription; the body carries the shortfall |
| `429` | Rate limited (product-shot endpoints) |

A `401` always carries `WWW-Authenticate` and a `data.code` of `auth_required`;
follow `resource_metadata` to the authorization server rather than hard-coding
an endpoint.

Generations spend the connected account's credits, and a failed render is
refunded. `get_account_info` reports the balance without leaving the agent.

More: [API reference](/docs/api) · [Connecting an AI agent](/docs/ai) ·
[MCP specification](https://modelcontextprotocol.io/)

---

<!-- Connect an AI agent to Pikes — https://pikes.ai/docs/ai -->

# Connect an AI agent to Pikes

Pikes is a product-imagery engine an agent can drive: it generates and edits
images that keep a real product's label, text and proportions intact, animates
them, and files the results in the user's boards. Everything below runs against
the user's own Pikes account and spends that account's credits.

## What an agent can do

- **Product photography** — put a real product into a new scene, on a model, or
  in a lifestyle setting, with its label and text intact.
- **Image editing** — combine several references (product + scene + style),
  extend a canvas to another aspect ratio, cut a product out on transparency.
- **Video** — animate a still into a short clip, with audio on the models that
  support it.
- **Brand context** — read and write the account's brand knowledge (voice,
  colours, guidelines) so generations stay on-brand across sessions.
- **Products** — search the saved product library, or import products from a
  Shopify store.
- **Research** — pull competitor ads from the Foreplay library, and read Meta ad
  performance, creative and comments when the account is connected.

## Three ways in

| Path | Best for | Start here |
| --- | --- | --- |
| **MCP server** | Claude, ChatGPT, Cursor, any MCP client | [MCP setup](/docs/mcp) |
| **REST tool calls** | Your own orchestration code — the same tools over plain HTTP | [API reference](/docs/api#rest-tool-calls) |
| **Product-shot endpoints** | One-call product photography from an image file | [API reference](/docs/api#product-shot-endpoints) |

### The shortest possible start

```bash
# 1. Create a key in the app (Settings → API), then:
curl -X POST https://pikes.ai/mcp/tools/generate_image \
  -H "x-api-key: psk_…" -H "Content-Type: application/json" \
  -d '{"prompt":"a matte black bottle on wet stone","aspectRatio":"4:5"}'
```

```bash
# Or hand it a product photo and get a studio shot back:
curl -X POST https://pikes.ai/api/product-shot \
  -H "x-api-key: psk_…" \
  -F "image=@bottle.jpg" \
  -F "aspect_ratio=4:5" \
  -F "resolution=4K"
```

## Authentication

API keys look like `psk_…`, are created in the app under **Settings → API** (or
**Settings → Claude / MCP**), and are accepted as either header:

```
Authorization: Bearer psk_…
x-api-key: psk_…
```

Keys are stored only as a SHA-256 hash and can be revoked at any time. Key
management itself is authenticated by the user's session — a key cannot mint or
revoke keys. MCP clients that can complete OAuth 2.1 should do that instead of
holding a key; see [MCP setup](/docs/mcp#authentication).

## What it costs

Calls spend the account's credits, charged per generation and refunded if a
render fails. The two fixed-price endpoints:

| Call | Credits |
| --- | --- |
| `POST /api/product-shot` at `1K` | 6 |
| `POST /api/product-shot` at `4K` | 12 |

Tool calls through MCP or `/mcp/tools/…` are priced by the model and resolution
they run at — `get_account_info` returns the current balance, and a `402`
response carries the shortfall. Rates and plans are on
[pikes.ai](https://pikes.ai/#pricing).

## Ground rules worth telling your agent

- Reach for `get_product_images` the moment a user names a product; don't ask
  them to upload something they already have in Pikes.
- Ads returned by `find_ads` are research, not inputs — analyse the
  composition, then generate with the user's own product.
- Feed generations from original uploads rather than from previous outputs;
  re-editing a generated image compounds its distortions.
- Long renders (4K, video) belong on `submit_image_job` + `get_image_job`
  instead of a blocking call.

## More

[API reference](/docs/api) · [MCP setup](/docs/mcp) ·
[llms.txt](https://pikes.ai/llms.txt) ·
[every page in one file](https://pikes.ai/llms-full.txt) · questions: leo@pikes.ai
