Skip to content

Generate Wireframe from Imported Page (Trigger)

Method

This planned API follows the REST methodology. It creates one Code2WF generation row from a completed Page Import and dispatches one asynchronous worker message.

HTTP Method

POST: Generate a wireframe from an imported page

Naming Convention

Request and response JSON use camelCase. The SQS payload uses snake_case.

Request and Response

Headers

Request Headers

  • Authorization
  • Content-Type
  • Accept
  • Accept-language

Response Headers

  • Content-Type

Generate Wireframe from Imported Page

URI

POST /api/v1/organizations/{organization_id}/projects/{project_id}/code2wf

Path Parameters

Name Type Required Description
organization_id integer Required Organization ID
project_id integer Required Project ID

Request Body

{
  "pageImportId": "0195f16e-6f11-7ea8-b45c-f6712ed9d8a3",
  "figmaFileKey": "aBc1DeFg2HiJ3kLmNoPqRs",
  "screenId": "AUTORACE_DATABASE",
  "placementTarget": "128:9001"
}

Request Parameters

Name Type Required Description
pageImportId string (UUID) Required Completed Page Import in the organization/project from the URI.
figmaFileKey string Required Target Figma file, following the same validation as WF2Des.
screenId string Required Caller-confirmed screen ID, normally prefilled from the imported page name; persisted verbatim like wf2des.screen_id.
placementTarget string Optional Figma node selected as placement context, following wf2des.placement_target; omitted is normalized to null. On the current page, shared placeRoot uses its absolute x/y without changing the target; unavailable targets fall back to viewport center.

Code2WF does not accept a repository, public URL, HTML/CSS, viewport, source hash, status, attempt, result, or materialization fields.

Response

New row (HTTP status: 201 Created):

{
  "code2wfId": "019ffa75-01c0-75a2-8123-456789abcdf0",
  "pageImportId": "0195f16e-6f11-7ea8-b45c-f6712ed9d8a3",
  "figmaFileKey": "aBc1DeFg2HiJ3kLmNoPqRs",
  "screenId": "AUTORACE_DATABASE",
  "placementTarget": "128:9001",
  "status": "0",
  "attempt": 1,
  "createdAt": "2026-08-13T09:30:00Z"
}

Response Fields

Name Type Description
code2wfId string Backend-generated UUIDv7 row ID and poll key.
pageImportId string Imported-page source row.
figmaFileKey string Target Figma file.
screenId string Caller-provided screen ID.
placementTarget string | null Optional placement context.
status string "0" processing, "1" completed, or "2" failed.
attempt integer Always 1 in the MVP.
createdAt string Row creation time (ISO 8601).

Code2WF reuses the platform wf2des_status type and uses only processing/completed/failed in this flow. It has no phase, reject, or cancel transition.

Authentication

Authentication uses an Amazon Cognito JWT. The caller must have Write access to the project.

Trigger Identity

The backend generates a new UUIDv7 code2wfId for every valid trigger. Two requests with identical bodies create two rows and dispatch two jobs. The API accepts no caller-generated ID and has no request-deduplication index.

Error Handling

Description Status Code Status Name
Invalid Figma field or caller-owned field 400 Bad Request
Missing authentication credentials 401 Unauthorized
Page Import, organization, project, or authorized scope not found 404 Not Found
Page Import is not completed 409 Conflict
Page Import result resolution or SQS dispatch fails 500 Internal Server Error

If Page Import result resolution or dispatch fails after row creation, the backend best-effort marks the row failed and returns the shared API error envelope:

{
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Internal Server Error"
  }
}

The failed row remains visible through the scoped history list. The MVP does not redispatch it; another valid trigger creates a new backend-generated code2wfId.

Processing Flow

  1. Authenticate and verify Write access.
  2. Validate the Figma fields.
  3. Verify the project belongs to the organization in the path, then fetch the non-deleted Page Import by (page_import.id, page_import.project_id = project_id) and require completed status. This service check enforces the scope that independent foreign keys cannot.
  4. Generate UUIDv7 and insert the minimal code2wf row with status="0" and attempt=1.
  5. Read and verify the immutable normalized manifest once. Use those exact bytes to derive one consistent page_result_url, page_result_hash, and capture_hash pin set; missing or corrupt bytes fail before dispatch.
  6. Send one SQS message with those exact source values.
  7. If resolution/dispatch fails, compare-and-set (id, attempt=1, status="0") to failed and record a safe error_message.
  8. Return the created row.

The PostgreSQL row stores only page_import_id; it does not copy Page Import result pointers or hashes. This verified S3 read is not a PostgreSQL/S3 transaction.

Detailed Flowchart

flowchart TD
  Start([POST]) --> Auth[Authenticate and authorize]
  Auth --> Source[Validate completed Page Import]
  Source --> Row[Generate UUIDv7; insert status 0; attempt 1]
  Row --> Resolve[Resolve immutable Page Import result]
  Resolve --> Queue[Send SQS message]
  Queue -->|Success| Created[201 Created]
  Queue -->|Failure| Failed[CAS row to status 2; return 500]

Asynchronous Processing

The worker reads only the Page Import result referenced in SQS, writes one immutable Code2WF result in S3, and reports through the shared AI-status webhook. Workers never write PostgreSQL.

SQS Payload

{
  "code2wf_id": "019ffa75-01c0-75a2-8123-456789abcdf0",
  "organization_id": 1,
  "project_id": 7,
  "attempt": 1,
  "nonce": "8bed02b2-c93d-4854-8f4f-1c91744dc419",
  "page_import_id": "0195f16e-6f11-7ea8-b45c-f6712ed9d8a3",
  "page_result_url": "s3://bucket/1/7/page-import/0195f16e-6f11-7ea8-b45c-f6712ed9d8a3/normalized/manifest.json",
  "page_result_hash": "sha256:44a7f61a6f90f476c349b264c0cbd824ce45ecad0d9985f0750f8a251aa9592a",
  "capture_hash": "sha256:90e54d8b9cf4ff0fdc2b927b4453d59f4c3e219c236bb398e660aca50a62ae27",
  "screen_id": "AUTORACE_DATABASE"
}

nonce is transport correlation only. It is not stored in PostgreSQL and the webhook row transition compares (id, attempt, current status), not nonce.