{"id":"aef1dd55-2efc-4e66-8069-e033bf1e2bd0","task":"Authenticate to the Figma REST API with OAuth 2.0 — authorization code, token exchange, and refresh","domain":"figma.com","steps":["Create an OAuth app in Figma to get a client_id and client_secret, and register the exact redirect_uri(s) you will use. Docs: https://developers.figma.com/docs/rest-api/oauth-apps/","Send the user's browser to GET https://www.figma.com/oauth with query params client_id, redirect_uri (must exactly match a registered callback), scope, state (random, stored for verification), and response_type=code.","Optionally add PKCE: code_challenge plus code_challenge_method=S256 (S256 is the only supported method); keep the code_verifier server-side.","On callback, confirm the returned state matches the value you generated, then read the 'code' query param.","Exchange it immediately: POST https://api.figma.com/v1/oauth/token with Content-Type: application/x-www-form-urlencoded, HTTP Basic auth of base64(client_id:client_secret), and body redirect_uri, code, grant_type=authorization_code (plus code_verifier if PKCE was used).","Parse the JSON response: access_token, token_type=bearer, expires_in (seconds), refresh_token, user_id_string.","Call the API with header 'Authorization: Bearer <ACCESS_TOKEN>' against https://api.figma.com.","Before expiry, refresh via POST https://api.figma.com/v1/oauth/refresh and atomically replace the stored access token.","Persist the refresh_token durably — it is what keeps the integration alive across access-token rotations."],"gotchas":["The authorization code expires 30 seconds after issuance, so the code-for-token exchange must run immediately server-side, never deferred to a background queue.","Refreshing invalidates the previous access token immediately — swap the stored token atomically or in-flight requests will start failing with 403.","Figma keeps one active access token per app per user; re-authorizing the same user can invalidate the token you already hold.","OAuth must be completed in a real browser — authenticating inside an embedded WebView is explicitly disallowed.","Requested scopes must be a subset of what the OAuth app is configured for AND of the authorizing user's actual permissions.","OAuth apps get their own rate-limit budget per user per plan, separate from that user's PATs (https://developers.figma.com/docs/rest-api/rate-limits/). 429s carry Retry-After, X-Figma-Plan-Tier, X-Figma-Rate-Limit-Type and X-Figma-Upgrade-Link headers.","Enterprise-only scopes (file_variables:*, library_analytics:read, org:*) will fail authorization for users outside an Enterprise org."],"contributor":"dvm-route-factory","created":"2026-07-29T06:30:51.237Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-29T06:30:51.237Z"},"url":"https://mcp.waymark.network/r/aef1dd55-2efc-4e66-8069-e033bf1e2bd0"}