Record Feedback
Method
This API follows the REST methodology.
HTTP Method
POST: Record designer feedback on a completed wf2des generation.
Feedback is bookkeeping only. It stamps feedbackStatus on the wf2des row so consumers can see how the generated design was received โ whether it was hand-fixed before use or adopted as-is. It emits no SQS message, fires no webhook, and triggers no follow-on generation run. The generation itself is unchanged.
Naming Convention
To ensure consistency and readability, JSON nodes in requests and responses use camelCase. SQS payload nodes use snake_case.
Request and Response
Headers
Meta information is set in HTTP headers, not in the response body.
Request Headers
AuthorizationContent-TypeAcceptAccept-language
Response Headers
Content-Type
Record Feedback
URI
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| organization_id | integer | Required | Organization ID |
| project_id | integer | Required | Project ID |
| wf2des_id | string | Required | wf2des ID |
Request Body
The request body is JSON.
Request Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| feedbackStatus | string (enum) | Required | How the generated design was received. "0" fixed (adopted after manual correction) / "1" adopted (used as-is). Any other value is 400. |
This endpoint carries only the flag. The feedback detail (
{status, changed_nodes[], diff_url, at, by}) is written by the plugin directly towf2des-api(POST /internal/wf2des/{wf2des_id}/feedback) before this endpoint is called โ detail first, flag last. The detail never travels through this endpoint (the backend's service token is read-only on the data plane). See Processing Flow.
Response
The response is JSON (HTTP status: 200 OK).
{
"wf2desId": "8f14e45f-ceea-467d-9a3e-1b2c3d4e5f60",
"status": "1",
"phase": null,
"feedbackStatus": "0",
"attempt": 1,
"recordedAt": "2026-07-10T09:30:00Z"
}
Response Fields
| Name | Type | Description |
|---|---|---|
| wf2desId | string | wf2des ID |
| status | string (enum) | Generation status โ unchanged by feedback. Feedback is recorded only on a completed run ("1"). |
| phase | string | null | Generation phase โ null on a completed run (feedback does not touch it). |
| feedbackStatus | string (enum) | The stamped value โ "0" fixed / "1" adopted. |
| attempt | integer | Fencing counter of the run (unchanged by feedback). |
| recordedAt | string | ISO 8601 timestamp when feedback_status was stamped (updatedAt mirror). |
Status / phase enums (wf2des row):
status:"0"processing ยท"1"completed ยท"2"failed ยท"3"rejected ยท"4"cancelledphase(insidestatus "0",nullonce terminal):"0"parse ยท"1"awaiting_confirm ยท"2"assemblefeedbackStatus:"0"fixed ยท"1"adopted
Feedback is idempotent by last-write. Re-recording feedback overwrites the prior feedbackStatus (the plugin re-writes the detail via wf2des-api the same way) and returns 200 OK with the current value.
Authentication
Authentication is performed using JSON Web Tokens (JWT) issued by Amazon Cognito.
Any authenticated session with Write access to the project may record feedback โ it is not restricted to the session that triggered the generation. The feedback detail is written by the plugin to the design_generation_result document via the wf2des-api data plane before this endpoint stamps the row.
Error Handling
The following status codes are returned for errors.
| Description | Status Code | Status Name |
|---|---|---|
Missing or invalid feedbackStatus (absent, or not "0" / "1") |
400 | Bad Request |
| Missing authentication credentials | 401 | Unauthorized |
| Insufficient permissions | 403 | Forbidden |
| wf2des, project, or organization not found | 404 | Not Found |
| Internal server error | 500 | Internal Server Error |
Feedback is accepted only on a completed run (status "1"). A row that is not completed is treated as not found for feedback purposes and returns 404 โ feedback has no meaning on a processing, failed, rejected, or cancelled generation.
Processing Flow
The backend owns the wf2des PostgreSQL row and is the sole writer. Recording feedback is a single detail-first-flag-last sequence applied backend-side โ the worker holds no PostgreSQL credentials and never participates. No SQS message is emitted, no webhook fires, and no follow-on run is triggered; the endpoint only annotates a completed row and its result document.
- Extract organization ID, project ID, and
wf2des_idfrom path parameters; extractfeedbackStatusfrom the request body. - Verify the user has Write access to the project.
- Validate
feedbackStatus("0"fixed /"1"adopted); on an absent or unknown value, return 400. - Load the
wf2desrow; if it does not exist, is soft-deleted, or itsorganization_id/project_iddoes not match the path, return 404. - Confirm the row is
status "1"completed; if it is in any other state, return 404 (feedback applies only to a completed run). - Detail first (precondition). The feedback detail โ the
feedbackblock ({status, changed_nodes[], diff_url, at, by}, referenced fromartifact_urls.feedback_diff) โ has already been written by the plugin directly towf2des-apibefore this call. Detail before flag guarantees a flagged row always has its feedback detail present; this endpoint neither accepts nor persists the detail. - Flag last. Stamp
feedback_statuson thewf2desrow in one PostgreSQL transaction (also stampingupdated_at/updated_by).status,phase, andattemptare untouched. - Return the row with the stamped
feedbackStatus.
Re-recording overwrites the prior detail document and re-stamps feedback_status (last-write-wins). Because feedback is bookkeeping only, there is no compare-and-set on attempt โ the flag simply reflects the most recent feedback recorded against the completed run.
Detailed Flowchart
flowchart TD
Start([POST /feedback]) --> Auth[Auth & Parameter Extraction]
Auth --> Service[Service Layer]
Service --> AccessCheck[Access Check]
AccessCheck --> HasAccess{Write Access?}
HasAccess -->|No| Err403[403 Forbidden]
HasAccess -->|Yes| Validate[Validate Body<br/>feedbackStatus '0' fixed / '1' adopted]
Validate --> BodyValid{Valid?}
BodyValid -->|No| Err400[400 Bad Request]
BodyValid -->|Yes| LoadRow[Load wf2des Row<br/>WHERE id = :wf2des_id]
LoadRow --> RowExists{Exists &<br/>org/project match?}
RowExists -->|No| Err404[404 Not Found]
RowExists -->|Yes| Completed{status '1'<br/>completed?}
Completed -->|No| Err404
Completed -->|Yes| DetailNote[Detail precondition<br/>the plugin has already written the<br/>feedback detail via wf2des-api]
DetailNote --> FlagLast[Flag last<br/>stamp feedback_status in one PG txn<br/>status / phase / attempt untouched]
FlagLast --> FlagResult{Success?}
FlagResult -->|No| Err500[500 Internal Server Error]
FlagResult -->|Yes| Success[200 OK<br/>row with feedbackStatus stamped]