Outcome
Submit a community or company build request for review, without confusing submission with build execution.
POST /api/developer-console/build-requests
Before you start
Use the original authenticated organization, the published Developers requests:write permission and the discovered canonical Developers workspace bound separately at the required write access. Discover the profile/workspace through supported reads rather than fabricating ids.
The route resolves a non-suspended, non-revoked Developers workspace context before parsing the body. Shared context can initialize the local profile or workspace mirror before later validation refusal; it does not mint a new Auth workspace. A pending submission is not onboarding completion, a permission grant, a queued execution or a release.
Review the intended request text and any sensitive company or budget details before authorizing this confirmed mutation. Validate and plan the exact input/resource context first. The examples below are source-derived synthetic UNRUN data with fictional identities; no request was submitted or private data read.
Request and effects
Action: app_topolo_developers.build_requests.create.
POST creates a new request identity using createId and inserts it into the intake database with the authenticated user, current developer/organization/workspace, normalized lower-case email, saved requester name/company and role metadata. Client input cannot choose those identities, status, reviewer or source.
Native input is title and summary, optionally requestType,impact,budgetContext; unknown properties are refused. requestType is community or company and defaults to community. Source trims title/summary/impact/budgetContext and lowercases the request type; do not rely on source coercions to bypass the stricter published schema.
After trimming, title must be4–140 characters, summary20–2000, impact at most1000 and budgetContext at most500. Thus a space-padded value passing the native length check can still fail the handler after trimming. Empty optional impact/budget fields become null in storage and empty strings in the formatted result.
The initial status is pending and source is developer-console. Successful HTTP201 returns the complete {success:true,message,data:{request}} envelope. The identifier is data.request.id, not a top-level id or data.id. This submits work for review; no build, app, deployment, budget approval, recipient message or delivery outcome is established.
The helper inserts first and then reads/hydrates the saved request from intake/control databases. Current developerName/developerEmail may reflect the current profile while email/requesterName/companyName are the submitted snapshot. The formatter omits null reviewedAt,reviewedBy,reviewNotes and does not project workspaceId even though it is stored.
There is no request-provided idempotency key, stable caller request id, uniqueness check or transaction covering the insert and hydrated response in this route. A lost or failed response after insertion can leave a real pending request. Repeating the same input can create another identity; do not blindly replay.
If the follow-up SELECT cannot find its row, the formatter permits request:null; this is not sufficient evidence of a usable created request. A hydration failure after insert is not an automatic rollback. Preserve actual response/request identifiers and reconcile through the supported listing/reviewer owner before any further mutation.
Worked requests and responses
Submit a community request with the default type
Complete synthetic UNRUN HTTP201, assuming all permission/workspace checks, insert and hydration succeed. The server-generated id/time and fictional profile are illustrative; absent review fields are omitted.
Input:
{
"title": "Inventory planning request",
"summary": "Please review a proposed inventory planning connector for our fixture workspace."
}
Response:
{
"success": true,
"message": "Developer build request created successfully",
"data": {
"request": {
"id": "req_docs_fixture_community",
"userId": "usr_docs_fixture",
"developerId": "dev_docs_fixture",
"organizationId": "org_docs_fixture",
"email": "developer@example.invalid",
"requesterName": "Fixture Developer",
"companyName": "Fixture Company",
"requestType": "community",
"title": "Inventory planning request",
"summary": "Please review a proposed inventory planning connector for our fixture workspace.",
"impact": "",
"budgetContext": "",
"status": "pending",
"source": "developer-console",
"submittedAt": "2026-10-21T00:00:00.000Z",
"developerName": "Fixture Company",
"developerEmail": "profile@example.invalid"
}
}
}
Read back this exact request id and pending status; no build execution or delivery is implied.
Submit a company request with impact and budget context
Complete synthetic UNRUN HTTP201 with explicit company type. A budgetContext string records submitted context and does not approve spending. No request or business operation was executed.
Input:
{
"title": "Inventory planning request",
"summary": "Please review a proposed inventory planning connector for our fixture workspace.",
"requestType": "company",
"impact": "Reduce manual stock planning.",
"budgetContext": "Proposal only; no budget approved."
}
Response:
{
"success": true,
"message": "Developer build request created successfully",
"data": {
"request": {
"id": "req_docs_fixture_company",
"userId": "usr_docs_fixture",
"developerId": "dev_docs_fixture",
"organizationId": "org_docs_fixture",
"email": "developer@example.invalid",
"requesterName": "Fixture Developer",
"companyName": "Fixture Company",
"requestType": "company",
"title": "Inventory planning request",
"summary": "Please review a proposed inventory planning connector for our fixture workspace.",
"impact": "Reduce manual stock planning.",
"budgetContext": "Proposal only; no budget approved.",
"status": "pending",
"source": "developer-console",
"submittedAt": "2026-10-21T00:00:00.000Z",
"developerName": "Fixture Company",
"developerEmail": "profile@example.invalid"
}
}
}
Verify the saved identity/text/type against this intended request; do not infer an approval or execution assignment.
A title made of spaces is refused after trimming
Complete synthetic UNRUN rawHTTP422. This four-space title passes native minLength4 but trims to empty in the handler. The selected insert is not reached; earlier shared context effects remain separate.
Input:
{
"title": " ",
"summary": "Please review a proposed inventory planning connector for our fixture workspace."
}
Response:
{
"success": false,
"error": {
"message": "Please review the highlighted fields.",
"details": {
"title": true
}
}
}
Correct the intended title and revalidate; do not invent a created request from this refusal.
Verify and recover
-
After an actual authorized submission, use build_requests.list with the original authenticated user context and separately required requests:read permission. Find the exact returned data.request.id and compare pending status, requestType and intended text; similar titles alone are insufficient.
-
The current list filters by authenticated user rather than organization/workspace, so it can contain that user’s other-context history and omits stored workspaceId. Preserve the original submission context and do not treat listing as a workspace-isolated authorization or audit certificate.
-
For an interrupted/uncertain response, inspect current supported history and preserve any returned id and request details. Do not generate another request merely because a response was lost. If no unique match can be established, leave the effect unknown and ask the existing reviewer/support owner to reconcile before authorizing a new submission.
-
The published contract has no withdraw action for this request. A reviewer resolves it through their separately authorized workflow; do not invent a deletion, status update or inverse.
Change log
- 2026-10-21: Added exact submission identity, normalization, pending-versus-execution and duplicate/uncertain-response guidance, with complete synthetic unrun success and validation examples.