GhostfeedGhostfeed MCPv5.3.0
REST API

Avatars

Generate draft AI avatars from typed traits, then approve or rename them. Drafts never enter the library without human approval; the user manages or discards unwanted drafts from the dashboard.

POST /api/v2/avatars

WRITE

MCP twin: create_avatar

Generate draft avatar(s) from appearance traits + an optional scene prompt. Returns drafts that are NOT saved to the library; the user must approve them. Any traits you omit are randomized. Costs credits per image; the result reports creditsSpent and creditsRemaining. Drafts are billed once at creation, never expire, and cost nothing to keep unapproved. Each draft carries dashboardUrl, the dashboard door to that draft.

Workspace-scoped writes name workspace in the body (or as a ?workspace= query param on a bodyless DELETE); the X-Workspace-Id header is for reads only.

Request body
{
  "type": "object",
  "properties": {
    "workspace": {
      "type": "string",
      "minLength": 1,
      "description": "Required write target: a workspace slug or id from list_workspaces. Writes never inherit the connection default."
    },
    "traits": {
      "description": "Appearance traits. Any you omit are randomized (gender-aware).",
      "type": "object",
      "properties": {
        "gender": {
          "type": "string",
          "enum": [
            "Female",
            "Male"
          ]
        },
        "ageBand": {
          "type": "string",
          "enum": [
            "18-19",
            "20s",
            "30s",
            "40s",
            "50s",
            "60s",
            "70+"
          ]
        },
        "heritage": {
          "type": "string",
          "enum": [
            "South Asian",
            "East Asian",
            "Black",
            "White",
            "Latino",
            "Middle Eastern",
            "Mixed"
          ]
        },
        "faceShape": {
          "type": "string",
          "enum": [
            "Oval",
            "Round",
            "Heart",
            "Square",
            "Angular"
          ]
        },
        "skinTone": {
          "type": "string",
          "enum": [
            "Porcelain",
            "Fair",
            "Light Medium",
            "Medium",
            "Olive",
            "Tan",
            "Deep"
          ]
        },
        "skinTexture": {
          "type": "string",
          "enum": [
            "Airbrushed clean",
            "Smooth natural",
            "Soft matte",
            "Freckled",
            "Textured pores",
            "Weathered rugged"
          ]
        },
        "hairColor": {
          "type": "string",
          "enum": [
            "Jet Black",
            "Black",
            "Dark Brown",
            "Medium Brown",
            "Light Brown",
            "Auburn",
            "Blonde",
            "Platinum Blonde",
            "Copper Red",
            "Salt & Pepper",
            "Gray",
            "Silver",
            "White"
          ]
        },
        "hairStyle": {
          "type": "string",
          "enum": [
            "Buzz cut",
            "Crew cut",
            "Fade",
            "Textured crop",
            "Short side part",
            "Slicked back",
            "Quiff",
            "Natural short",
            "Bob cut",
            "Layered cut",
            "Straight & sleek",
            "Soft waves",
            "Beach waves",
            "Loose curls",
            "Tight curls",
            "Soft bangs",
            "Center part",
            "Side part",
            "Ponytail",
            "Sleek bun",
            "Long & flowing",
            "Messy tousled"
          ]
        },
        "eyeColor": {
          "type": "string",
          "enum": [
            "Dark Brown",
            "Brown",
            "Hazel",
            "Green",
            "Blue",
            "Gray",
            "Amber",
            "Gray-Blue"
          ]
        },
        "bodyBuild": {
          "type": "string",
          "enum": [
            "Slim",
            "Athletic",
            "Average",
            "Muscular",
            "Broad",
            "Curvy",
            "Petite",
            "Plus-size"
          ]
        },
        "facialHair": {
          "type": "string",
          "enum": [
            "Clean shaven",
            "Stubble",
            "Short beard",
            "Full beard",
            "Goatee",
            "Mustache"
          ]
        },
        "makeupStyle": {
          "type": "string",
          "enum": [
            "No makeup",
            "Natural / minimal",
            "Soft glam",
            "Bold glam",
            "Smoky eye",
            "Dewy fresh"
          ]
        },
        "bustSize": {
          "type": "string",
          "enum": [
            "Petite",
            "Small",
            "Medium",
            "Large",
            "Very Large"
          ]
        },
        "outfitStyle": {
          "type": "string",
          "enum": [
            "Casual t-shirt",
            "Button-down shirt",
            "Henley shirt",
            "Polo shirt",
            "Hoodie",
            "Sweater",
            "Denim jacket",
            "Leather jacket",
            "Bomber jacket",
            "Suit jacket",
            "Tank top",
            "Flannel shirt",
            "Crop top",
            "Off-shoulder top",
            "Tube top",
            "Lace camisole",
            "Halter top",
            "Blouse",
            "Bodysuit",
            "Corset top",
            "Sundress",
            "Wrap top",
            "Cardigan",
            "Spaghetti strap top",
            "Bandeau top",
            "Blazer",
            "Kurta",
            "Sari",
            "Sherwani",
            "Hijab with modest outfit"
          ]
        }
      }
    },
    "notes": {
      "description": "Free-text scene / pose / mood. Anything that is NOT a fixed trait. Scene wishes are best effort, not guaranteed: view the returned image before presenting it.",
      "type": "string",
      "maxLength": 2000
    },
    "count": {
      "description": "How many draft variations to generate (default 1). Every draft in a call shares this ONE trait spec; count gives look variations of the same persona, not distinct people. For distinct personas, make one call per persona.",
      "type": "integer",
      "minimum": 1,
      "maximum": 4
    },
    "names": {
      "description": "A name for each draft, index-aligned with count. YOU (the AI) should pick trait-appropriate names; omit to let the server auto-name. Fewer names than count is fine: the remaining drafts get server-generated names.",
      "maxItems": 4,
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 100
      }
    },
    "model": {
      "description": "Image model (default gemini_flash). Higher tiers cost more credits.",
      "type": "string",
      "enum": [
        "gemini_flash_lite",
        "gemini_flash",
        "gemini_pro",
        "gpt_low",
        "gpt_medium",
        "gpt_high"
      ]
    },
    "idempotencyKey": {
      "description": "A stable key to reuse if you retry this exact request; a repeat with the same key is NOT charged again.",
      "type": "string",
      "maxLength": 200
    }
  },
  "required": [
    "workspace"
  ],
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Example response
{
  "success": true,
  "data": {
    "avatars": [
      {
        "avatarId": "avt_9f8e7d6c5b4a3210",
        "name": "Maya",
        "imageUrl": "https://cdn.ghostfeed.ai/avatars/drafts/avt_9f8e7d6c5b4a3210.png",
        "status": "draft",
        "dashboardUrl": "https://ghostfeed.ai/w/client-a/avatar?create=1&draft=avt_9f8e7d6c5b4a3210&ref=agent"
      }
    ],
    "traits": {
      "gender": "Female",
      "ageBand": "20s",
      "heritage": "South Asian",
      "faceShape": "Oval",
      "skinTone": "Medium",
      "skinTexture": "Smooth",
      "hairColor": "Black",
      "hairStyle": "Long Wavy",
      "eyeColor": "Brown",
      "bodyBuild": "Slim",
      "outfitStyle": "Casual"
    },
    "creditsSpent": 2,
    "creditsRemaining": 45,
    "total": 1,
    "page": 1,
    "pages": 1,
    "nextSteps": "1 draft avatar created, NOT yet in the library. Show them to the user and call approve_avatar with the avatarId(s) they want to keep. You cannot delete drafts; the user manages or discards the rest from the dashboard. Each draft dashboardUrl opens it in the dashboard. Report the spend: 2 credits spent, 45 remaining."
  }
}

POST /api/v2/avatars/:id/approve

WRITEIDEMPOTENT

MCP twin: approve_avatar

Approve a draft avatar by its avatarId, promoting it into the library (optionally rename). Only approve drafts the USER chose to keep. Returns dashboardUrl for the saved avatar.

Path parameters: id (from the URL).

Workspace-scoped writes name workspace in the body (or as a ?workspace= query param on a bodyless DELETE); the X-Workspace-Id header is for reads only.

Request body
{
  "type": "object",
  "properties": {
    "avatarId": {
      "type": "string",
      "description": "The avatarId of the draft to approve (from create_avatar)."
    },
    "workspace": {
      "type": "string",
      "minLength": 1,
      "description": "Required write target: a workspace slug or id from list_workspaces. Writes never inherit the connection default."
    }
  },
  "required": [
    "avatarId",
    "workspace"
  ],
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Example response
{
  "success": true,
  "data": {
    "avatarId": "avt_9f8e7d6c5b4a3210",
    "name": "Maya",
    "thumbnailUrl": "https://cdn.ghostfeed.ai/avatars/saved/avt_9f8e7d6c5b4a3210/thumb.png",
    "status": "saved",
    "dashboardUrl": "https://ghostfeed.ai/w/client-a/avatar?selected=avt_9f8e7d6c5b4a3210&ref=agent",
    "nextSteps": "Approved and saved to the library. Open it: https://ghostfeed.ai/w/client-a/avatar?selected=avt_9f8e7d6c5b4a3210&ref=agent"
  }
}

PATCH /api/v2/avatars/:id

WRITEIDEMPOTENT

MCP twin: rename_avatar

Rename an avatar (draft or saved) by its avatarId. Pure rename: does NOT save/approve a draft or change anything else.

Path parameters: id (from the URL).

Workspace-scoped writes name workspace in the body (or as a ?workspace= query param on a bodyless DELETE); the X-Workspace-Id header is for reads only.

Request body
{
  "type": "object",
  "properties": {
    "avatarId": {
      "type": "string",
      "description": "The avatarId to rename (draft OR saved)."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100,
      "description": "The new name."
    },
    "workspace": {
      "type": "string",
      "minLength": 1,
      "description": "Required write target: a workspace slug or id from list_workspaces. Writes never inherit the connection default."
    }
  },
  "required": [
    "avatarId",
    "name",
    "workspace"
  ],
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Example response
{
  "success": true,
  "data": {
    "avatarId": "avt_1a2b3c4d5e6f7081",
    "name": "Priya V2",
    "status": "saved",
    "dashboardUrl": "https://ghostfeed.ai/w/client-a/avatar?selected=avt_1a2b3c4d5e6f7081&ref=agent",
    "nextSteps": "Renamed."
  }
}

GET /api/v2/avatars

READ

MCP twin: list_avatars

List SAVED (library) avatars in the active workspace: id, name, thumbnail. Use this to find an avatarId for rename_avatar or content generation. Unapproved drafts are separate (list_draft_avatars).

Query parameters
{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (default 1).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Per page (max 100). Each tool documents its own default.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "workspace": {
      "description": "Target workspace: a slug, id, or exact name from list_workspaces. Omit to use this connection's default workspace. Must be inside the credential's grant and your current access; overrides the connection-level X-Workspace-Id header.",
      "type": "string"
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Example response
{
  "success": true,
  "data": {
    "workspace": {
      "id": "6a18c36ee586c7e44e4ece67",
      "name": "Client A",
      "slug": "client-a"
    },
    "avatars": [
      {
        "avatarId": "avt_1a2b3c4d5e6f7081",
        "name": "Priya",
        "imageUrl": "https://cdn.ghostfeed.ai/avatars/saved/avt_1a2b3c4d5e6f7081/thumb.png",
        "imageCount": 6,
        "gender": "Female",
        "creationMethod": "ai_generated",
        "createdBy": "64f1c2a1b2c3d4e5f6071829",
        "createdAt": "2026-06-01T08:30:00.000Z"
      }
    ],
    "total": 12,
    "page": 1,
    "pages": 1,
    "nextSteps": "These are SAVED library avatars in the active workspace. rename_avatar works on any of them by avatarId. Pending (unapproved) drafts are separate: list_draft_avatars."
  }
}

GET /api/v2/avatars/drafts

READ

MCP twin: list_draft_avatars

List draft avatars awaiting approval in the active workspace, newest first (paginated).

Query parameters
{
  "type": "object",
  "properties": {
    "page": {
      "description": "Page number (default 1).",
      "type": "integer",
      "minimum": 1,
      "maximum": 9007199254740991
    },
    "limit": {
      "description": "Per page (max 100). Each tool documents its own default.",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "workspace": {
      "description": "Target workspace: a slug, id, or exact name from list_workspaces. Omit to use this connection's default workspace. Must be inside the credential's grant and your current access; overrides the connection-level X-Workspace-Id header.",
      "type": "string"
    }
  },
  "$schema": "http://json-schema.org/draft-07/schema#"
}
Example response
{
  "success": true,
  "data": {
    "workspace": {
      "id": "6a18c36ee586c7e44e4ece67",
      "name": "Client A",
      "slug": "client-a"
    },
    "drafts": [
      {
        "avatarId": "avt_9f8e7d6c5b4a3210",
        "name": "Maya",
        "imageUrl": "https://cdn.ghostfeed.ai/avatars/drafts/avt_9f8e7d6c5b4a3210.png",
        "createdBy": "64f1c2a1b2c3d4e5f6071829",
        "createdAt": "2026-07-18T11:00:00.000Z"
      }
    ],
    "total": 1,
    "page": 1,
    "pages": 1,
    "nextSteps": "Approve the ones to keep (approve_avatar). You cannot delete drafts; the user manages or discards the rest from the dashboard."
  }
}

GET /api/v2/image-models

READ

MCP twin: list_image_models

List the image models create_avatar can use, with per-image credit cost, so you can offer the user options with prices.

No parameters.

Example response
{
  "success": true,
  "data": {
    "models": [
      {
        "id": "gemini_flash",
        "label": "Gemini Flash",
        "creditCost": 1,
        "provider": "google",
        "isDefault": true
      },
      {
        "id": "gpt_image",
        "label": "GPT Image",
        "creditCost": 3,
        "provider": "openai",
        "isDefault": false
      }
    ],
    "nextSteps": "Pass a chosen id as create_avatar `model` (default is the isDefault one). creditCost is per image."
  }
}