Topolo Docs Topolo Platform
Open workspace

Submit a build request

Submit a community or company request for review and reconcile its exact pending identity without duplicate retries or assuming a build has started.

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

  1. 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.

  2. 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.

  3. 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.

  4. 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.