Skip to content

Register Figma Personal Access Token

Migrated from OAuth on 2026-05-07

Replaces the prior GET /figma/oauth, GET /figma/oauth/token, and POST /figma/oauth/refresh endpoints. The user now generates a PAT in Figma settings and submits it to this endpoint instead of going through an OAuth redirect.

Method

REST method is adopted.

HTTP Method

POST: Validate and persist the user's Figma Personal Access Token.

Naming Convention

To unify the naming of query parameters and nodes and improve readability, snake_case is used for URIs and JSON nodes in requests.

Request and Response

Headers

Meta information is set in HTTP headers, not in the response body.

Request Headers

  • Authorization โ€” required, Cognito JWT
  • Content-Type โ€” application/json
  • Accept
  • Accept-language

Response Headers

  • Content-Type

Register PAT

URI

POST /figma/token

Request Body

{
  "personal_access_token": "<figma-pat>"
}

Request Fields

Name Type Required Description
personal_access_token string Required The Figma PAT pasted by the user. Non-empty, max 256 chars, no whitespace.

Response

The response is JSON.

{
  "cognitoSub": "user-cognito-sub",
  "lastValidatedAt": 1746576000000,
  "createdAt": 1746576000000,
  "updatedAt": 1746576000000,
  "createdBy": "user-cognito-sub",
  "updatedBy": "user-cognito-sub"
}

Response Fields

Name Type Description
cognitoSub string User's Cognito identifier
lastValidatedAt number Timestamp of the successful GET /v1/me validation (epoch milliseconds, nullable)
createdAt number Creation timestamp (epoch milliseconds)
updatedAt number Update timestamp (epoch milliseconds)
createdBy string Audit column โ€” the Cognito sub that created the row
updatedBy string Audit column โ€” the Cognito sub that last updated the row

Requests are snake_case, responses are camelCase. The request body node is personal_access_token, while the response keys are camelCase, as returned by formatTokenOutput. This page previously documented snake_case response keys and omitted createdBy / updatedBy; that did not match the implementation.

The PAT itself is never returned in any response โ€” only metadata about the stored row.

Authentication

Authentication is performed using JSON Web Tokens (JWT) issued by Amazon Cognito. The PAT is associated with the authenticated user's Cognito sub.

Error Handling

Description Status Code Status Name Error Code
Validation failed (format / empty / whitespace) or PAT rejected by Figma (401/403 from GET /v1/me) 400 Bad Request invalid_figma_token
Missing or invalid Cognito JWT 401 Unauthorized
Rate limit exceeded 429 Too Many Requests
Internal server error 500 Internal Server Error
Figma API unreachable / 5xx 502 Bad Gateway

When Figma returns 429 to our GET /v1/me validation, the response surfaces Figma's Retry-After to the client.

Processing Flow

  1. Authenticate the caller via Cognito JWT โ€” extract cognito_sub.
  2. Validate personal_access_token format (non-empty, โ‰ค256 chars, no whitespace). On failure โ†’ 400 invalid_figma_token.
  3. Call GET https://api.figma.com/v1/me with header X-Figma-Token: <pat>.
  4. 200 โ†’ continue.
  5. 401 / 403 โ†’ 400 invalid_figma_token.
  6. 429 โ†’ propagate as 429 with Figma's Retry-After.
  7. 5xx โ†’ 502.
  8. Encrypt the PAT (AES-256) and upsert into figma_token keyed by cognito_sub. Set last_validated_at to the current time.
  9. Return the response payload above.

Rate Limiting

This endpoint is rate limited: - Limit: 10 requests per minute - Scope: Per user (identified by Cognito sub)

Security

  • The PAT is encrypted at rest with AES-256.
  • The PAT is never returned in any API response after registration.
  • Logs and traces must redact the PAT โ€” log only the cognito_sub and validation outcome.
  • The user is responsible for revoking superseded PATs in Figma's own settings UI.

Detailed Flowchart

flowchart TD
    Start([POST /figma/token]) --> Auth[Authenticate Cognito JWT]
    Auth --> AuthOK{Valid JWT?}
    AuthOK -->|No| Err401[401 Unauthorized]
    AuthOK -->|Yes| Validate[Validate PAT format]
    Validate --> FormatOK{Valid format?}
    FormatOK -->|No| Err400[400 invalid_figma_token]
    FormatOK -->|Yes| CallMe[GET https://api.figma.com/v1/me<br/>X-Figma-Token: PAT]
    CallMe --> FigmaResp{Figma response}
    FigmaResp -->|401/403| Err400
    FigmaResp -->|429| Err429[429 Too Many Requests<br/>passthrough Retry-After]
    FigmaResp -->|5xx| Err502[502 Bad Gateway]
    FigmaResp -->|200| Encrypt[Encrypt PAT AES-256]
    Encrypt --> Upsert[Upsert figma_token<br/>by cognito_sub]
    Upsert --> Success[200 OK]

Related