Integrations · AI agents

One skill spec.
Every agent.

copyto.design ships as a skill — a small markdown file that teaches an agent one thing: how to POST HTML to api.copyto.design and hand the user back a .fig file. Drop it in Claude, Claude Code, Codex, or Cursor. Same skill body, four wrappers.

The whole API surface

The skill teaches one HTTP call.

Every integration on this page boils down to this single request. Authenticate with your sk_… key; pass either a url or raw html; get back a .fig file the user opens in Figma.

POSThttps://api.copyto.design/v1/open/html_to_fig_file
curl --location 'https://api.copyto.design/v1/open/html_to_fig_file' \
  --header 'Authorization: sk_xxx' \
  --header 'Content-Type: application/json' \
  --output 'output.fig' \
  --data '{
      "url": "https://copyto.design"
      // or "html": "<h1>Hello, Figma</h1>"
  }'
Authorization
Your API key, prefixed exactly as issued — sk_live_… for production, sk_test_… for sandbox. No Bearer prefix.
url — or — html
Send one. url renders the public page in our headless renderer; html takes a raw fragment or full document and skips the fetch.
Response
200 OK with application/octet-stream — the binary .fig file streamed directly in the body. Headers carry Content-Disposition: attachment; filename="output.fig", so curl --output / browser download / IDE agents drop it straight to disk.
The shape of a skill

Three moves. Same in every agent.

The skill markdown tells the agent when to fire (trigger phrases) and how (the call above). Everything else — wrapping, packaging, where the file lands on disk — is just the host agent doing its normal thing.

01
Agent writes HTML
A landing page, a card, a settings panel — whatever it just generated, or an URL the user pointed at.
<section class="hero">
  <h1>Hello</h1>
  <button>Get started</button>
</section>
02
Skill fires the request
One POST to /v1/open/html_to_fig_file. Engine resolves layout, types, tokens, streams back the binary .fig file in the response body.
parse layout tokens .fig
03
User opens in Figma
Save the response body to output.fig, drop it on the Figma desktop dock, or import in the browser. Native frames, Auto Layout, text styles — all editable.
Figma · open .fig
Pick your agent

Setup, in under a minute.

Every panel ships the same payload — a markdown skill file — wrapped in whatever folder convention that agent expects. The skill body is identical; the install path is the only thing that changes.

Recommended for most users

Claude (claude.ai)

Install copyto.design as a Skill. Claude reads the skill on demand whenever you ask for a Figma file, fires our API with the HTML it just produced, saves the binary .fig response to a working file, and surfaces it to the user as a one-click download.

SurfaceWeb · Desktop
MechanismSkill (Markdown)
AuthSkill secret
Setup time~60s
  1. 01

    Save the skill file

    Paste this into a new copy-to-design.skill.md. It's the canonical skill body — every other agent on this page wraps the same instructions, just in a different folder.

    copy-to-design.skill.md
    ---
    name: copy-to-design
    description: |
      Convert HTML the assistant generates (or a public URL) into an
      editable Figma file. Trigger whenever the user asks for a "Figma
      file", "Figma design", or wants to "open this in Figma".
    ---
    
    ## When to fire
    
    Fire this skill when the user says any of:
    - "make this a Figma file"
    - "give me the Figma version"
    - "open this in Figma"
    - "convert <url> to Figma"
    
    ## How to fire
    
    POST the HTML you just produced (or a URL the user named) to
    https://api.copyto.design/v1/open/html_to_fig_file.
    
    ```bash
    curl --location 'https://api.copyto.design/v1/open/html_to_fig_file' \
      --header 'Authorization: $CTD_API_KEY' \
      --header 'Content-Type: application/json' \
      --output output.fig \
      --data '{
          "url": "https://copyto.design"
      }'
    # or, for raw HTML:
    #   --data '{ "html": "<h1>Hello, Figma</h1>" }'
    ```
    
    ## What to return
    
    The response body is the binary .fig file itself (
    application/octet-stream). Save it to output.fig and surface
    it to the user as a downloadable attachment labeled "Open in Figma".
    
    ## Auth
    
    The skill secret CTD_API_KEY holds the sk_… key.
    Send it as the literal Authorization header value — no
    Bearer prefix.
  2. 02

    Upload to Skills

    In Claude, open Settings → Skills → New skill. Drop the file in. Set CTD_API_KEY as a skill secret (it never appears in transcripts).

    claude.ai/settings/skills
    copy-to-designHTML → editable .fig file. Triggers on "Figma" requests.
    Active
    research-helper
    Inactive
  3. 03

    Try it

    Tested prompt patterns — copy any one verbatim:

    • Build a pricing page in HTML and give me the Figma version.
    • Here's some HTML — <paste> — make it a Figma file.
    • Convert https://stripe.com/pricing to a Figma file.
For developers · agentic loops

Claude Code

Same skill, dropped into .claude/skills/ in your repo. Claude Code picks it up automatically and can fire html_to_fig_file mid-loop — handy when the agent is iterating on a UI and you want to spot-check it on a Figma canvas without leaving the terminal.

SurfaceCLI · IDE
MechanismSkill (Markdown)
AuthEnv var
Setup time~30s
  1. 01

    Drop the skill into your repo

    One command — clones the canonical skill into the project's .claude/skills/ directory.

    Terminal
    # 1. Set your API key — once, in your shell profile
    export CTD_API_KEY="sk_live_..."
    
    # 2. Install the skill into the current repo
    npx @copytodesign/skill install --target claude-code
    
    # Writes:  .claude/skills/copy-to-design/SKILL.md
    # Reads :  $CTD_API_KEY at call time, never on disk.
  2. 02

    Or write the file by hand

    The skill body is identical to Claude's — only the auth line changes. Claude Code resolves $CTD_API_KEY from the shell env at call time.

    .claude/skills/copy-to-design/SKILL.md
    ---
    name: copy-to-design
    description: HTML or URL → editable .fig file via api.copyto.design.
    allowed_tools: [Bash]
    ---
    
    When the user asks for a Figma file, run:
    
    ```bash
    curl -sS --location 'https://api.copyto.design/v1/open/html_to_fig_file' \
      --header "Authorization: $CTD_API_KEY" \
      --header 'Content-Type: application/json' \
      --output output.fig \
      --data "$(jq -nc --arg h \"$HTML\" '{html:$h}')"
    ```
    
    The response body is the binary .fig file.
    After --output output.fig writes it to disk,
    print the path back to the user as a clickable line:
    
      → Open in Figma: ./output.fig
  3. 03

    Use in a session

    Claude Code surfaces the skill on its own when the task involves Figma. No tool toggles, no /commands — it's just there.

    • Generate a settings page React component, then export the rendered HTML to Figma.
    • Take the JSX in src/Pricing.tsx, render it static, send to Copy to Design.
    • I'll paste a URL — convert each one to a .fig and stash the links in design-refs.md.
For OpenAI CLI / GPT custom agents

Codex (OpenAI)

Codex CLI loads skills from ~/.codex/skills/. Drop the same markdown body in and Codex starts treating "make this a Figma file" as a recognized intent — it shells out to curl against our endpoint with whatever HTML it just generated.

SurfaceCodex CLI · ChatGPT
MechanismSkill (Markdown)
AuthEnv var
Setup time~60s
  1. 01

    Install the skill

    Same package, different target. Codex picks it up on next session.

    Terminal
    export CTD_API_KEY="sk_live_..."
    npx @copytodesign/skill install --target codex
    
    # Writes:  ~/.codex/skills/copy-to-design.md
  2. 02

    The skill file Codex reads

    The frontmatter shape differs from Claude's, but the body — the API call — is byte-for-byte identical. The only Codex-specific bit is the tools declaration that authorizes the shell call.

    ~/.codex/skills/copy-to-design.md
    ---
    id: copy-to-design
    title: HTML → Figma file
    tools:
      - shell
    trigger:
      any_of:
        - "figma file"
        - "open in figma"
        - "make it a figma"
    ---
    
    ## Action
    
    ```bash
    curl --location 'https://api.copyto.design/v1/open/html_to_fig_file' \
      --header "Authorization: $CTD_API_KEY" \
      --header 'Content-Type: application/json' \
      --output output.fig \
      --data '{
          "html": "<HTML_FROM_CONVERSATION>"
      }'
    ```
    
    Substitute <HTML_FROM_CONVERSATION> with the most
    recent HTML you produced (escape quotes; pass through jq
    if convenient). For URL inputs, swap the body for
    { "url": "<url>" }.
    
    Return the path of the saved output.fig as a labeled link.
  3. 03

    Prompt patterns

    • Build a hero section in HTML, then make it a Figma file.
    • Visit example.com, grab the pricing section, open it in Figma.
    • Render this JSX to static HTML and convert to .fig.
For IDE-based agents

Cursor

Cursor's skill format is .mdc — markdown with a YAML frontmatter, scoped per project. Drop the same body into .cursor/rules/copy-to-design.mdc and the agent gains a "make it a Figma file" intent across every chat in that workspace.

SurfaceIDE
MechanismSkill (.mdc)
AuthEnv var
Setup time~1 min
  1. 01

    Add to .cursor/rules/

    Either run the installer, or hand-write this file. Cursor reloads rules without a restart.

    .cursor/rules/copy-to-design.mdc
    ---
    description: Turn HTML or a URL into an editable .fig file.
    globs:
      - "**/*.{html,jsx,tsx,vue,svelte}"
    alwaysApply: false
    ---
    
    When the user asks for a "Figma file" or to "open this in Figma",
    shell out to:
    
    ```bash
    curl --location 'https://api.copyto.design/v1/open/html_to_fig_file' \
      --header "Authorization: $CTD_API_KEY" \
      --header 'Content-Type: application/json' \
      --output output.fig \
      --data '{ "html": "<HTML>" }'
    ```
    
    Read $CTD_API_KEY from the user's environment. The response
    body is the binary .fig file (saved to output.fig by
    --output). Return that path as a markdown link the user can click.
  2. 02

    Same trigger phrases as everywhere else

    Once the rule is in place, Cursor's chat fires the skill automatically when the user mentions Figma. No tool toggles, no slash commands.

    • Take the open Tailwind file, render it static, give me a Figma version.
    • Open https://linear.app in Figma.
Heads up

Cursor's .mdc format is workspace-scoped — the skill won't follow you across projects. Add it to your dotfiles repo or a project template if you want it everywhere.

Authoring your own integration

Don't see your agent? Two function calls.

Any agent that can shell out (or do an HTTP POST) can run this skill. The contract is whatever your agent's skill folder is, plus the call below.

01

Write the skill body

A few lines of markdown — trigger phrases up top, the API call in the body. The four panels above are all minor variations on this.

# When the user asks for a "Figma file":
POST /v1/open/html_to_fig_file
{ "html": html }   // or "url": url
02

Fire the request

Authenticate with Authorization: sk_… (no Bearer). Pass exactly one of url or html. Stream the response body to disk with --output.

curl https://api.copyto.design\
  /v1/open/html_to_fig_file \
  -H "Authorization: $KEY" \
  -H "Content-Type: application/json" \
  --output output.fig \
  -d '{"url":"…"}'
03

Hand the file to the user

Surface the saved output.fig as a downloadable attachment or a clickable file path. Opens in Figma desktop (drag onto the dock) or the Figma web app (File → Open).

→ Open in Figma:
  ./output.fig
  # 142 KB · application/octet-stream
Troubleshooting

The four things that go wrong.

Skill never fires

Most agents only consider a skill if its description matches the user's intent. If the agent ignores "make this a Figma file", broaden the description in the frontmatter — list the trigger phrases verbatim. Also check that the skill is active in Claude / installed in the right folder for Codex / Cursor.

401 Unauthorized on the first call

Two common causes. First, the agent prepended Bearer to the header — our API expects the literal sk_… as the Authorization value. Second, the env var didn't reach the shell the agent spawned; in Claude Code and Codex, prefer setting CTD_API_KEY in ~/.zshrc / ~/.bashrc, not just the current terminal.

The Figma file looks shifted or stretched

For url inputs, set options.viewport to whatever width the page was designed for — otherwise we render at 1440 and your responsive layout reflows. For raw html, wrap it in a sized container or pass options.viewport explicitly.

API key leaked into the agent's transcript

Always pass the key through an env var or skill secret — never inline it in a prompt or skill body. If a key leaks, rotate it immediately at Settings → API keys; old keys revoke instantly.