{
  "name": "Presenta Agent API",
  "version": "1.1.0",
  "app": "https://presenta.design",
  "entry": "https://presenta.design/?agent=1",
  "bridge": {
    "global": "window.PresentaAgent",
    "handshake": "await PresentaAgent.ready()",
    "contract": "Every method returns a Promise of {ok:true,...} or {ok:false, code, message, ...}; methods never throw.",
    "errorCodes": [
      "bad_request",
      "not_ready",
      "busy",
      "rate_limited",
      "pro_required",
      "cors_blocked",
      "license_invalid",
      "too_large",
      "not_supported",
      "internal_error"
    ],
    "methods": {
      "discovery": [
        "getCapabilities()",
        "getState({includeImages?})",
        "getProStatus()",
        "getArtboardRect()"
      ],
      "composing": [
        "configure(patch)",
        "setImage(slot, source)",
        "setDevice(id, {orientation?})",
        "setLayout(layoutId)",
        "setBackground({type, value})",
        "setCanvasSize(presetId)",
        "applyTemplate(id)",
        "listTemplates()"
      ],
      "layers": [
        "addText(props)",
        "updateText(id, props)",
        "removeText(id)",
        "listTexts()",
        "addImageLayer(source, props?)",
        "updateImageLayer(id, props)",
        "removeImageLayer(id)",
        "listImageLayers()"
      ],
      "artboards": [
        "listArtboards()",
        "addArtboard({templateId?, activate?})",
        "switchArtboard(id)",
        "removeArtboard(id)"
      ],
      "output": [
        "preview({maxWidth?})",
        "exportImage({format?, scale?})",
        "stage(on, {fit?})"
      ],
      "video": [
        "getVideo()",
        "listShots()",
        "selectShot(id)",
        "addShot()",
        "removeShot(id)",
        "setShotRange(id, {start, dur})",
        "applyShotPreset(id, presetId) — compose the look first; snapshots the scene into the shot",
        "captureShotScene(id)",
        "setShotKeyframes(id, [{t, rx, ry, rz, p, s, x, y}])",
        "setVideoDuration(seconds)",
        "applyVideoPreset(id)",
        "seekVideo(seconds)",
        "playVideo()",
        "pauseVideo()",
        "openVideoPanel(open)",
        "exportVideo({durationSeconds?, fps?, videoBitsPerSecond?}) [PRO]"
      ],
      "pro": [
        "siteShot(url, {apply?}) [PRO]",
        "removeImageBackground() [PRO]",
        "activateLicense(key)"
      ]
    }
  },
  "mcp": {
    "server": "https://presenta.design/agents/presenta-mcp.mjs",
    "transport": "stdio",
    "requires": [
      "node >= 18",
      "playwright + chromium"
    ],
    "install": [
      "mkdir -p ~/.presenta && cd ~/.presenta",
      "curl -fsSL https://presenta.design/agents/presenta-mcp.mjs -o presenta-mcp.mjs",
      "npm i playwright && npx playwright install chromium",
      "claude mcp add --scope user presenta -- node ~/.presenta/presenta-mcp.mjs"
    ],
    "env": {
      "PRESENTA_URL": "app origin override",
      "PRESENTA_PROFILE": "browser profile dir",
      "PRESENTA_HEADLESS": "0 to watch"
    }
  },
  "skill": "https://presenta.design/agents/SKILL.md",
  "pricing": {
    "model": "freemium",
    "free": "Mockup composing, devices, layouts, backgrounds, shadows, 3D, DOF, effects, text & image layers, multi-artboards, video timeline authoring + preview, PNG/JPG/WebP export at any scale.",
    "pro": {
      "product": "Presenta Pro",
      "features": [
        "site_shots",
        "video_export",
        "bg_removal",
        "transparent_bg",
        "pro_templates"
      ],
      "plans": [
        {
          "id": "lifetime",
          "price": "$20 one-time",
          "checkout": "https://buy.polar.sh/polar_cl_XMDjd98QTTRtvFihIIlpZNPInQseWkIdhaB6H4LzF4j"
        },
        {
          "id": "monthly",
          "price": "$8/month",
          "checkout": "https://buy.polar.sh/polar_cl_8oYqqf3xRHjWGZiG1XhTrAsIRle8DXogG6e3N2sy4IZ"
        }
      ],
      "agentEtiquette": "Pro-gated calls return {code:'pro_required'} with these checkout links. Relay the offer to your human user; never purchase or activate a license without their explicit consent."
    }
  },
  "limits": {
    "maxImageBytes": 26214400,
    "maxExportScale": 4,
    "maxVideoSeconds": 60,
    "rate": {
      "export": "8/min",
      "preview": "20/min",
      "siteShot": "3/10min",
      "video": "2/5min",
      "configure": "120/min"
    }
  },
  "security": {
    "imageSources": [
      "data:image/(png|jpeg|webp|gif|avif);base64",
      "https://",
      "bundled app assets"
    ],
    "blocked": [
      "javascript:",
      "http:",
      "file:",
      "blob:",
      "data:text/*",
      "svg data urls"
    ],
    "notes": "Text layers render as plain text (markup escaped). No postMessage surface — same-tab automation only. Server endpoints validate licenses and rate-limit per IP."
  },
  "video": {
    "model": "Shots are cuts. Each shot = one clip {start, dur} with a camera pass (keyframes over rotateX/Y/Z, perspective, size, positionX/Y) and a scene (artboard look: device, image, background, effects) captured by applyShotPreset and restored at the cut.",
    "presets": [
      "scan-lr",
      "top-bottom",
      "low-angle",
      "zoom-out",
      "and 4 more orbits/overheads — see getCapabilities().videoPresets"
    ],
    "direction": "3 shots × 4 s; change device/crop/angle per shot (≥25°); browserUrl = the site shown; brand-derived background; one effect max per shot; record at 2× device pixels, ≥14 Mbps for 1080p.",
    "capture": "MCP records via tab capture at 2× (deviceScaleFactor 2), VP9 WebM."
  }
}
