Skip to content

feat(figma): add Figma API module - #151

Open
seanspeaks wants to merge 2 commits into
nextfrom
cursor/figma-api-module-83fc
Open

seanspeaks wants to merge 2 commits into
nextfrom
cursor/figma-api-module-83fc

Conversation

@seanspeaks

@seanspeaks seanspeaks commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds @friggframework/api-module-figma at packages/v1-ready/figma/ — a Frigg v2 API module for the Figma REST API.

No prior package existed under packages/ (including needs-updating); this is a greenfield module shaped like packages/v1-ready/fathom/, with webhooks modeled on packages/v1-ready/hubspot/extensions/webhooks/.

What the API is / sources

Figma’s public REST API (https://api.figma.com) for files, folders/projects, comments, users, and Webhooks V2.

Source Link
Vendor OpenAPI (canonical) https://raw.githubusercontent.com/figma/rest-api-spec/main/openapi/openapi.yaml
Official OpenAPI repo https://github.com/figma/rest-api-spec
REST API intro https://developers.figma.com/docs/rest-api/
Authentication / OAuth https://developers.figma.com/docs/rest-api/authentication/ · OAuth apps
Scopes https://developers.figma.com/docs/rest-api/scopes/
Webhooks V2 https://developers.figma.com/docs/rest-api/webhooks/ · security

figma.openapi.yaml is a path-filtered extract of the vendor OpenAPI above: server URL, per-operation security/scopes, parameters, and request/response schemas are taken verbatim for the curated operations (webhook delivery callbacks omitted — not client operations). One operationId ↔ one Api method.

Auth method

OAuth 2 authorization code (recommended by Figma for multi-user apps):

  • Authorize: https://www.figma.com/oauth
  • Token: POST https://api.figma.com/v1/oauth/token with HTTP Basic (client_id:client_secret)
  • Refresh: POST https://api.figma.com/v1/oauth/refresh with Basic auth (body: refresh_token only)
  • Identity: GET /v1/me → externalId = user.id
  • Env: FIGMA_CLIENT_ID, FIGMA_CLIENT_SECRET, optional FIGMA_SCOPE, REDIRECT_URI

Default scopes (from vendor operation security requirements):
current_user:read, file_content:read, file_metadata:read, file_comments:read, file_comments:write, projects:read, project_metadata:read, folders:read, folder_metadata:read, webhooks:read, webhooks:write.

Access note: Public OAuth apps require Figma review before end-user authorization. Private apps are limited to the associated team/org.

Endpoints covered

operationId HTTP
getMe GET /v1/me
getFile / getFileMeta GET /v1/files/{key} · /meta
getComments / postComment / deleteComment file comments
getTeamProjects / getProjectFiles / getProjectMeta legacy projects
getTeamFolders / getFolderFiles / getFolderMeta folders (current)
getWebhooks / postWebhook / getWebhook / putWebhook / deleteWebhook / getTeamWebhooks / getWebhookRequests Webhooks V2

Endpoints skipped (same scope; not wrong — simply out of curated set)

Images/renders, file versions, components/styles/sets, variables, dev resources, activity/developer logs, library analytics, AI usage, payments, oEmbed, nested getFolderFolders, comment reactions. No comment update exists in the public REST API.

Vendor-spec follow-up (this push)

Diffed every curated operation against https://raw.githubusercontent.com/figma/rest-api-spec/main/openapi/openapi.yaml (paths, methods, params, request/response fields, auth/scopes, server URL). 0 structural mismatches after regen.

What changed:

  1. Regenerated figma.openapi.yaml from the vendor document (full component schemas/$refs for curated paths; removed invented global security: [OAuth2]; restored authentic request/response bodies).
  2. Added missing default scope project_metadata:read required by GET /v1/projects/{project_id}/meta.
  3. getFolderFiles(folderId, query) now forwards official branch_data query param (was missing).
  4. Capability manifest: scopes + object fields aligned to official schemas (GetFileResponse camelCase; project/folder meta snake_case; Comment / WebhookV2 complete fields). Removed incorrect file key field (not on GetFileResponse).
  5. Documented official putWebhook quirk: team_id is required but omitted from properties in the vendor schema (preserved as published).
  6. Spec-sync tests expanded to assert vendor shape (no global security, per-op scopes ⊂ OAuth2 scopes, branch_data, putWebhook quirk).

Capability manifest

figma.capabilities.json — schema capability-manifest/v0.1 with module, package, version, auth, and objects.*.fields[] (tagged) for user, file, project, folder, comment, webhook. Every declared method maps to a real Api method.

Fenestra

figma.fenestra.yaml — draft for Figma’s Plugin/Widget UI platform. Sourced from claude/fenestra-spec-draft-Q367t example; validates with fenestra.js validate.

Webhooks extension

extensions/webhooks/ — HubSpot-style Tier 3 receiver verifying body.passcode vs FIGMA_WEBHOOK_PASSCODE.

Proof

npm test — pass (28 tests)

cd packages/v1-ready/figma && npm test

PASS tests/definition.test.js
PASS tests/api.test.js
PASS tests/spec-sync.test.js
PASS tests/passcode-verifier.test.js

Test Suites: 4 passed, 4 total
Tests:       28 passed, 28 total

Capture: /opt/cursor/artifacts/figma-npm-test.txt

frigg validate --module — pass

From frigg cursor/frigg-validate-module-1721 (PR friggframework/frigg#702):

  ✓ The app definition is valid.
validateApiModuleDefinition.valid = true

frigg auth test . — pending credentials

No sandbox OAuth client / tokens in this environment.

Open questions

Closed by the vendor OpenAPI

  • Default scopes for project meta — answered: project_metadata:read is required for getProjectMeta (now included).
  • getFolderFiles query — answered: official param is branch_data (boolean, default false); client now forwards it.
  • Comment update — answered: no update operation in the vendor OpenAPI (create/delete only).
  • Webhook description max length — answered in OpenAPI: 150 characters (docs prose sometimes says 140).
  • Webhook event enum — answered: FILE_UPDATE, FILE_VERSION_UPDATE, FILE_DELETE, LIBRARY_PUBLISH, FILE_COMMENT, DEV_MODE_STATUS_UPDATE (+ PING in enum but delivery-only).
  • putWebhook body — answered (with quirk): required event_type, team_id, endpoint, passcode; team_id absent from properties in the published schema.

Still open

  1. Public OAuth app review — for marketplace/multi-tenant use, has Left Hook submitted (or will submit) a public Figma OAuth app?
  2. Projects vs folders — both implemented (projects deprecated upstream). Prefer folders-only in adopters?
  3. Webhook multi-tenant binding — Figma deliveries carry webhook_id + passcode but not the OAuth user id. Preferred pattern: per-tenant passcode, path segment, or webhook_id → entity.externalId side table?
  4. Plan access tokens — expose a non-OAuth setAuthParams path for org plan tokens, or keep OAuth-only?
  5. Capability manifest schema — confirm capability-manifest/v0.1 against the canonical frigg schema when packages/core/integrations/definitions/capabilities/ lands.
  6. Deferred surfaces — reactions / versions / components / variables until an integration needs them?

Credit

  • Shape/tests patterned on @friggframework/api-module-fathom
  • Webhooks extension patterned on @friggframework/api-module-hubspot extensions/webhooks/
  • OAuth Basic token exchange patterned on Zoom/Deel modules + Figma OAuth docs
  • Fenestra draft from claude/fenestra-spec-draft-Q367t example
  • OpenAPI operationIds/schemas from figma/rest-api-spec
Open in Web Open in Cursor 

cursoragent and others added 2 commits October 20, 2026 04:31
Add @friggframework/api-module-figma under packages/v1-ready/figma with
OAuth2 client, curated OpenAPI subset, capability manifest, Fenestra draft,
HubSpot-style webhooks extension, and offline jest/spec-sync coverage.

Co-authored-by: Sean Matthews <sean.matthews@lefthook.co>
Regenerate figma.openapi.yaml as a path-filtered extract of the vendor
OpenAPI (params, request/response schemas, per-op scopes, server URL).
Add project_metadata:read, forward getFolderFiles branch_data, and sync
capability field names to official schemas.

Co-authored-by: Sean Matthews <sean.matthews@lefthook.co>
@seanspeaks
seanspeaks marked this pull request as ready for review October 22, 2026 00:36
@seanspeaks seanspeaks added the auth-test pending Code and CI green; frigg auth test waits on credentials label Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth-test pending Code and CI green; frigg auth test waits on credentials

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants