Skip to content

Figma Sensor ​

What it ingests ​

Design files, comments, and version history from the Figma REST API:

Figma objectOntology entitySignal
Design file, FigJam board, Slides deckCreativeWork (source_type: design_document)file
Comment or replyCommentcomment
File creator, last editor, version and comment authorsPerson (identity)—

Each design file becomes one Design Document. Its creator, its last editor, and anyone who saved a version are linked to it with AUTHORED. Each comment becomes a Comment that its author AUTHORED. The comment is RELATED_TO its Design Document, and a reply is also RELATED_TO the comment it answers.

Comment threads are the decision signal. When a thread is resolved, the root comment is ingested again with the whole thread as its content and status: resolved, so the discussion that settled a design question is one readable record. Named versions ("Ready for dev", plus their descriptions) land in the Design Document's content.

People are matched by their Figma user id, which is stored as a figma:<id> identity key. Figma never returns another user's email address, so a Figma author links to an existing Person by display name the first time. After that the id keeps them on the same Person.

Read-only and poll-based against https://api.figma.com. The sensor never calls Figma's Tier 1 endpoints (the full document tree, nodes, or image renders). See Rate limits.

Credential ​

References a figma_access_token credential by id. The secret is a personal access token (figd_…), sent as X-Figma-Token. An OAuth access token is also accepted and sent as Authorization: Bearer. The sensor tells the two apart by the figd_ prefix.

bash
curl -sS -X POST https://your-corveil-host/api/credentials \
  -H "Authorization: Bearer <admin>" -H "Content-Type: application/json" \
  -d '{"type":"figma_access_token","name":"acme-figma","secret":"figd_<token>"}'

Store only the token value, not X-Figma-Token: … or Bearer ….

The token reads only what its user can see in Figma. Scopes narrow that further; they never widen it. Use a dedicated design-ops account that has access to the teams you want ingested, so the sensor keeps working when one person changes roles.

Required scopes

ScopeWhy
file_metadata:readFile name, folder, creator, last editor, and link
folders:readList a team's folders (projects) and their files. A token created before August 2026 with the deprecated projects:read also works.
file_comments:readComments. Optional if enabled_objects leaves comments out.
file_versions:readVersion history. Optional if enabled_objects leaves versions out.

file_content:read is not needed.

Config fields ​

Set at least one of team_ids, folder_ids, or file_keys.

KeyRequiredNotes
team_idsone of threeComma-separated team IDs. Every folder the token can see in the team is polled, including nested folders (up to three levels, 200 folders). A team URL is accepted too.
folder_idsone of threeComma-separated folder (project) IDs, polled with their subfolders, on their own or alongside whole teams.
file_keysone of threeComma-separated file keys or Figma file URLs (/design/, /file/, /board/, /slides/, …). Use this for drafts, files shared with you from outside your teams, or an OAuth token.
enabled_objectsnoExtras on top of the files themselves: comments, versions. Blank ingests both. files ingests the files alone. Unknown names are rejected at configure time.

There is no default_entity_type. This source emits two primary types (CreativeWork and Comment), so a single override would silently mistype the other.

Provider-side setup ​

  1. Sign in to Figma as the account the sensor will read as.
  2. Open Settings → Security → Personal access tokens and choose Generate new token.
  3. Set an expiry. Figma requires one on new personal access tokens, so note the date and rotate the credential before it lapses.
  4. Grant the read scopes in the table above: File metadata, Folders (or Projects on an older token), Comments, and Version history, each set to read-only.
  5. Copy the token. Figma shows it only once.
  6. Find each team ID. Open the team in the Figma file browser; the ID is the number after /team/ in the URL (https://www.figma.com/files/team/1234567890123456789/Acme). For a single folder, open it and copy the number after /project/ or /folder/.

Figma does not let a token list teams, so the team IDs have to come from the URL.

There is no admin-consent step. The token sees whatever its user sees.

Wire-up ​

POST /api/sensors

json
{
  "sensor_type": "figma",
  "name": "Acme Figma",
  "config": {
    "team_ids": "1234567890123456789",
    "file_keys": "https://www.figma.com/design/AbC123xYz00/Checkout-Flow",
    "enabled_objects": "comments, versions"
  },
  "credentials": { "access_token": "<figma_access_token credential id>" }
}

Verify ​

Run Test connection. It reads the first configured team's folders (or the first folder's files, or the first file's metadata). A rejected token fails at save or test rather than on the first poll. So does a valid token that can't see the team you named.

Once it's polling, the per-poll summary log shows files_ingested, files_swept_for_comments, and files_tracked. A team with files but files_tracked=0 usually means the token's user isn't a member of that team.

How incremental sync works ​

  • The cadence is the worker's poll interval. Each poll lists every folder's files and compares each file's last_modified with the value it last ingested.
  • Only changed files are re-read. A changed file costs three requests: its metadata, its versions newer than the last one ingested, and its comments. Unchanged files cost nothing beyond the listing.
  • First sync is spread out. One poll ingests at most 25 changed files, oldest edit first. The rest follow on the next polls. A team of 500 files takes about 20 polls to sync the first time.
  • Comments on unchanged files arrive through a sweep. Figma's last_modified moves on design edits, not on comments. So each poll also re-reads the comments of 10 unchanged files, round-robin. With N files, a comment on a file nobody is editing arrives within about N/10 polls. A comment on a file being edited arrives on the next poll.
  • The folder tree is cached for six hours. Changing team_ids or folder_ids re-walks it immediately.
  • An edited file lands a new event. The event id is figma:file:<key>@<last_modified>; the Design Document's entity id stays figma:file:<key>, so its properties refresh instead of duplicating.
  • A renamed file keeps its first name in the graph. The current name is on the entity's title property.
  • A file named "Untitled" gets its key appended (Untitled (AbC123xYz00)), so each untitled file stays its own Design Document.
  • Deletes are invisible. A file that disappears from a complete listing stops being tracked, but its entities stay.

Rate limits ​

Figma rate-limits per user and per endpoint tier, and the budget is shared with that user's other Figma integrations. The sensor uses file metadata (Tier 3) and folders, comments, and versions (Tier 2). It never uses Tier 1, which View and Collab seats get only a handful of times a month.

SeatTier 2Tier 3
Full or Dev seat25–100 per minute, by plan50–150 per minute, by plan
View or Collab seatup to 5 per minuteup to 10 per minute

Requests are paced 2.5 seconds apart, under the lowest paid Full-seat budget. A 429 with a Retry-After of a minute or less is retried up to three times. A longer wait means the user's budget is exhausted, so the poll stops. Files it already finished keep their progress; the rest resume next poll. Use a Full or Dev seat for the sensor's account. A View seat works for a handful of files but syncs slowly.

Known limits ​

  • Branches are not ingested. Only main files are listed.
  • No canvas content. Frame names, text layers, and components need the Tier 1 document tree, which the sensor deliberately doesn't call.
  • OAuth tokens can't list folders. Figma doesn't offer the folders endpoints to public OAuth apps, so an OAuth token only reads file_keys. Corveil does not refresh an OAuth token; rotate the credential when it expires.
  • Comment edits are not re-read. Figma comments have no edit timestamp, so a comment's text is captured when it's created (and again when its thread resolves).
  • Webhooks are not used. Figma's v2 webhooks need a public endpoint registered per team. Polling is the supported path.
  • Reactions are counted, not ingested as entities.