Connect Figma (Callback)
Method
This API follows the REST methodology.
HTTP Method
GET: Receive Figma's redirect after an admin authorizes the app, exchange the authorization code, and store the grant.
Figma redirects the admin's browser here. It is not called by the plugin or by any client of ours.
Naming Convention
To ensure consistency and readability, JSON nodes in responses use camelCase.
Request and Response
Headers
Request Headers
None required โ see Authentication.
Response Headers
Content-Type
Callback
URI
The path has no {organization_id} segment: redirect_uri must exactly match a URL registered on the Figma app, so it is fixed. The organization travels inside state instead.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| code | string | Optional | The authorization code. Absent when the admin declined. Expires 30 seconds after issue. |
| state | string | Required | The signed token minted by authorize. Carries the organization. |
| error | string | Optional | Present when the admin declined in Figma. |
Response
The response is JSON (HTTP status: 200 OK).
{
"organizationId": 1,
"connected": true,
"message": "Figma connected. The scheduler will refresh this organization grant automatically."
}
Response Fields
| Name | Type | Description |
|---|---|---|
| organizationId | integer | The organization the grant was stored for, read from state. |
| connected | boolean | Always true on success. |
| message | string | Human-readable confirmation for the browser tab. |
Tokens are never returned to the caller and never logged.
Authentication
None โ and there cannot be any. This is a browser redirect from Figma, so it carries no Cognito token and protectedRoute cannot gate it.
state is therefore the entire security boundary: it is server-minted by an authenticated org admin, HMAC-signed, organization-bound, single-purpose and 10-minute-lived, and its signature is compared in constant time. The organization is read from the signed payload, never from anything the caller supplies.
Without that, anyone who could reach this URL could bind their own Figma grant to your organization โ handing themselves whatever the scheduler can read.
Signature-failure and malformed-input both return the same message, so the endpoint is not an oracle for forging attempts.
Error Handling
| Description | Status Code | Status Name |
|---|---|---|
The admin declined in Figma, or no code was returned |
400 | Bad Request |
| Figma rejected the code (it expires after 30 seconds โ start again) | 400 | Bad Request |
state is invalid, tampered with, or expired |
401 | Unauthorized |
| Encrypting or storing the grant failed | 500 | Internal Server Error |
Processing Flow
- If
erroris present, the admin declined โ report it and stop. - Verify
state: constant-time signature check, expiry check, and recoverorganizationIdfrom the signed payload. - Exchange
codeathttps://api.figma.com/v1/oauth/tokenusing HTTP Basicclient_id:client_secret. The Admin API holds the client secret. - Encrypt the access and refresh tokens with the platform
ENCRYPTION_KEY, then upsert the organization'sfigma_oauth_grantrow in PostgreSQL. - Log which Figma account authorized (audit only) and return the confirmation.
Afterwards
Nothing further is required. When wf2des needs Figma access, it calls the Admin API's IAM-protected internal token provider. The Admin API returns the existing access token or refreshes it under a PostgreSQL advisory lock, then returns only the access token and expiry. The worker calls Figma with Authorization: Bearer.
A human is needed again only if the grant is revoked in Figma, the service account is deactivated, the client secret is rotated, or the encryption key is rotated.