Agent skills →

For Agents

Create an API key in Settings as a project owner, scoped to the permissions and project it needs. Send Authorization: Bearer YOUR_KEY to /api/v1. Keys are shown once, hashed at rest, expire, and can be revoked.

One file. Any structure.

Download the JSON Schema. Every screen has a stable ID, native pixel dimensions, SHA-256 checksum, raw base64 image, a nested section path and a row/column position.

{
  "schemaVersion": 1,
  "export": {
    "version": "v2",
    "title": "Onboarding experiments"
  },
  "screens": [
    {
      "id": "consumer-a-welcome",
      "title": "Welcome",
      "section": [
        "Onboarding",
        "Consumer",
        "Test A"
      ],
      "column": 0,
      "row": 0,
      "width": 1206,
      "height": 2622,
      "sha256": "SHA256_OF_DECODED_IMAGE",
      "image": "RAW_BASE64_IMAGE"
    }
  ]
}

Section names are your choice: product areas, audiences, experiments, platforms, or any other hierarchy (up to 32 levels). A parent includes its descendants. Each distinct path has its own layout: columns progress left to right, row 0 is the main flow, negative rows sit above and positive rows below. IDs are unique within an export; cells are unique within a section. Preserve screen IDs across versions to correlate feedback.

Import protocol

  1. Validate the single file locally and verify all checksums.
  2. POST its manifest with image fields removed.
  3. PUT each decoded screenshot to the returned export ID, up to three concurrently.
  4. POST complete. Only fully published exports appear to reviewers.

Rerunning an identical version resumes safely. Changing an existing version returns 409; use a new version. Limits: 200 screens, 3 MB per image, 20 megapixels per image, 100 MB total decoded data. API requests allow 600/minute/key. A large export may require waiting for the next rate-limit window; respect 429 and retry. Browser import and the CLI use this same protocol.

API reference

EndpointScopeBehavior
PATCH /projects/:p/exports/:e/screens/:sexports:writeUpdate frame tags: {tags: string[]}. Screenshot bytes and original manifest remain unchanged.
GET /projects/:p/people?q=comments:readFind current project members for @mentions. Returns IDs, names and photos.
DELETE /projects/:p/exports/:e/comments/:ccomments:writeDelete your own comment. Other people’s replies are preserved.
GET /projectsprojects:readList projects owned by the key owner.
POST /projectsprojects:writeCreate: {name, description?}. Unrestricted project key required.
GET /projects/:pprojects:readRead a project.
PATCH /projects/:pprojects:writeUpdate: {name, description?}. Owner only.
DELETE /projects/:pprojects:writeArchive project. Owner only.
GET /projects/:p/exportsexports:readList published export versions.
POST /projects/:p/exportsexports:writeCreate/resume a draft: import manifest without image fields. Returns {id,status}.
GET /projects/:p/exports/:eexports:readRead manifest, nested section paths, upload status and private image URLs.
PUT /projects/:p/exports/:e/screens/:sexports:writeUpload raw PNG/JPEG/WebP bytes. SHA-256 and pixel dimensions must match manifest.
POST /projects/:p/exports/:e/completeexports:writePublish atomically after all images have arrived.
GET /projects/:p/exports/:e/screens/:sexports:readStream a private screenshot with the same authentication.
GET /projects/:p/exports/:e/commentscomments:readList comments; optional status=open|resolved. Join screenId to the manifest for section context.
POST /projects/:p/exports/:e/commentscomments:writeCreate: {screenId,body,x,y,parentId?}. x/y normalized 0–1. parentId replies to a root.
PATCH /projects/:p/exports/:e/comments/:ccomments:writeUpdate {resolved?: boolean, body?: string}. Body edits are author-only. Resolve root threads.

Collections use cursor pagination: {items, nextCursor}, with 100 items per page. Pass ?cursor=nextCursor until null. Export and comment collections are ordered by ID; sort by createdAt when presenting a timeline. API errors use {error, issues?}; statuses 401 unauthenticated, 403 forbidden, 404 unavailable, 409 conflict, 413 too large, 422 invalid input, 429 rate limited.

Framehuddle CLI

The CLI is open source, with versioned releases and automatic Homebrew updates. Source and documentation · Releases

brew install b-nnett/framehuddle/framehuddle

# Set FRAMEHUDDLE_API_KEY securely in your environment.
framehuddle projects list --json
framehuddle init --project PROJECT_ID --export EXPORT_ID
framehuddle exports import ./export.visual-feedback.json
framehuddle feedback --status open --json
framehuddle screens get SCREEN_ID --output ./screen.png
framehuddle --help

# Upgrade:
brew update && brew upgrade framehuddle

# Existing Acquire exports (from the app repository):
npm run convert:acquire -- board.figma.json export.visual-feedback.json v1

Project sharing and API key management are available only to a signed-in human in the app. Agents cannot mint more keys or grant other accounts access. Screenshots require authentication; there are no public blob URLs.