Action: app_topolo_developers.placements.get.
Outcome
Read a stored live placement by id while preserving organization, consumer access and stale-status limits.
GET /api/developer-console/placements/{placementId}
Audience and access
This public guide documents a customer-facing read of private organization placement data. Use a person session in the intended active organization with app_topolo_developers.connections:read. The current descriptor declares static authorization, allowedServices:[] and no principalAccess override; that metadata does not grant a service, API key or workspace bypass.
The handler derives organizationId from the verified user; none of these action inputs accepts an organizationId. Authentication delegates to native verifyRequest and resolves the Developers app identity. An API-key workspace header is passed to native Auth for validation, never treated locally as a grant. The placement access check calls listAccessibleWorkspaces with the original request and organization. Published recovery recommends a person session when Auth cannot answer workspace membership.
Consumer workspace access at read or higher is sufficient for these three stored reads. They do not check a current provider-workspace grant, provider resource permission, active connection, workspace link or reference declaration. Those additional checks belong to separately authorized placement creation/refresh/provider actions. A returned provider reference is not permission to fetch its target.
Selected placement handlers do not call resolveWorkspaceContext or create a developer profile, and contain no placement/store mutations. Native authentication/app identity/workspace helpers remain separate dependencies; this source packet does not certify them as globally zero-write or authorize cleanup of any profile/mirror. Do not infer rollback or delete state after an authentication failure.
Exact published input schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"placementId": {
"type": "string",
"pattern": "^plc_[A-Za-z0-9-]{1,80}$"
}
},
"required": [
"placementId"
],
"additionalProperties": false
}
Exact published output schema
{
"type": "object",
"required": [
"success",
"data"
],
"properties": {
"success": {
"type": "boolean"
},
"message": {
"type": "string"
},
"data": {
"type": "object",
"additionalProperties": true
}
},
"additionalProperties": true
}
Current complete wire and read behavior
| Field | Current wire meaning |
|---|---|
id, organizationId | Stored placement and owning organization identifiers. |
consumer | Full object: appId, workspaceId, kind, id, all strings. |
slot | String or null. |
reference | Full object: app, workspace, type, id; optional numeric version, omitted when absent. |
referenceString | Canonical formatted reference including its optional pinned version. |
label | Stored string or null; not fetched again. |
status | Stored ready, changed, unavailable, removed or access_removed. |
statusReason | Stored string or null; no closed enum is promised. |
lastCheckedAt | Stored string or null; no freshness limit is imposed by these reads. |
createdBy, createdAt, updatedAt | Stored actor id and lifecycle timestamps. |
removedBy, removedAt | Nullable stored values. Returned live rows have removedAt:null. |
Actual selected success is HTTP200 with the complete envelope {success:true,message:"OK",data:{...}}. There is no top-level timestamp. The published outputSchema stays deliberately open; the field inventory below describes the current source mapper without replacing the native schema with an invented closed contract. OK is the exact English key developers.api.messages.ok, associated by the accepted connection3 packet at the same immutable revision; do not branch on localized message text.
Each PlacementRecord has id,organizationId,consumer:{appId,workspaceId,kind,id},slot,reference:{app,workspace,type,id,version?},referenceString,label,status,statusReason,lastCheckedAt,createdBy,createdAt,updatedAt,removedBy,removedAt. slot,label,statusReason,lastCheckedAt,removedBy,removedAt are nullable. reference.version is omitted for a null/falsy stored reference_version and otherwise Number-converted; it is not emitted as version:null. referenceString is formatReference(reference). Stored timestamps and nullable fields are mapped without freshness or date normalization. Malformed stored values are not revalidated by this mapper.
Status is the stored snapshot ready|changed|unavailable|removed|access_removed. ready is not current provider health or access proof; changed can describe a pinned-version mismatch from a previous check. lastCheckedAt may be null or old and is not restamped by these reads. statusReason is an arbitrary stored string or null, not a new closed reason enum. createdAt/updatedAt are stored lifecycle timestamps, not native provider observation generations.
The stored status removed can describe a still-live placement whose provider resource was previously missing. It is distinct from soft deletion: all returned rows have removedAt:null; rows with non-null removed_at are excluded. removedBy remains a nullable mapped stored field and must not be used alone to infer deletion.
These selected service paths read the control database and call Auth workspace lookup with the caller context. They do not call caller.readAction, a provider action, catalog hydration, entitlement fetch, action partitions, Notify or any placement mutation. defaultPlacementDeps constructs those available adapters, but these reads do not invoke them. Workspace promises are cached per app only within the created caller context; database rows and Auth responses are sequential, not a single cross-system transaction or a current provider check.
Error responses are {success:false,error:{message,code?,details?}}; absent code/details are omitted rather than forced null. Native metadata error codes are recovery guidance and do not guarantee that every shared authentication/permission exception includes that code: the outer ApiError path forwards optional code/details and unexpected failures return HTTP500 with a message only. Preserve actual status/code/details/request correlation rather than inventing a complete success or a missing code.
All examples are complete source-derived SYNTHETIC UNRUN carriers with fictional identifiers, users, labels and timestamps. No private/customer/provider resource was read. Only native action metadata was fetched. Matching sourceRevision identifies source applicability; deployed serving code, runtime behavior and UI adoption were not independently tested.
The only input is required placementId, matching ^plc_[A-Za-z0-9-]{1,80}$. The path supplies the same id; conflicting query/path ids or any undeclared field produce invalid_input before selected service work. There is no organization, workspace, provider, status or version override.
data is exactly {placement:PlacementRecord}. The successful body never uses placement:null or a nullable success result. Unknown, cross-organization, soft-deleted and consumer-workspace-inaccessible rows all produce the same HTTP404 placement_not_found. Do not use that refusal to distinguish private existence.
The service first reads the placement by exact organization+id. A missing or soft-deleted row returns404 without a consumer workspace lookup. Otherwise Auth must confirm the exact consumer app/workspace at read or higher. Auth unavailable/null produces503 workspace_access_unavailable; a confirmed list lacking the workspace deliberately becomes404, not the list action’s403. A prior visible row is not a current grant.
This is one stored-row lookup with no pagination. No provider get action, current connection/link/declaration check or status refresh is performed. Even unavailable/removed/access_removed status can be returned for a live visible row. Stored ready does not prove the provider currently exists, and status freshness cannot be inferred from the successful read.
Errors and recovery
The following current metadata entries describe recovery. Raw shared authentication failures may omit their catalog code; preserve the actual response.
[
{
"status": 401,
"code": "authentication_required",
"recovery": "Authenticate again in the intended Topolo environment."
},
{
"status": 403,
"code": "permission_denied",
"recovery": "Use a principal holding the Developers connections permission this action declares."
},
{
"status": 403,
"code": "organization_required",
"recovery": "Select the organization whose connections you manage; connections always act for the active organization."
},
{
"status": 422,
"code": "invalid_input",
"recovery": "Use canonical application ids (app_<owner>_<name>) and only the fields in inputSchema."
},
{
"status": 403,
"code": "workspace_access_required",
"recovery": "You cannot use that workspace (error.details.appId, workspaceId). Use a workspace you belong to, or ask its admin for access."
},
{
"status": 503,
"code": "workspace_access_unavailable",
"recovery": "Topolo Auth could not confirm your workspaces. Retry later; nothing was changed. API keys cannot answer workspace membership: use a person session."
},
{
"status": 404,
"code": "placement_not_found",
"recovery": "No live placement with this id in a consumer workspace you can use. Read placements.list."
}
]
No selected placement mutation to undo. Correct only invalid inputs; reauthenticate/select the intended organization or restore genuinely authorized consumer access through supported controls as appropriate. Preserve404 concealment,503 uncertainty and used_in silent omission. No automatic grant expansion, refresh/provider call, placement create/delete, source/runtime effect or profile cleanup follows from this guide.
Verification
- Require success:true and a complete data.placement, then match the requested id and original organization/consumer tuple.
- Do not distinguish missing from hidden/deleted on404; do not substitute stale local data as current success.
- Read lastCheckedAt/statusReason as nullable stored snapshot fields; this read does not verify the provider or a current connection.
Complete synthetic UNRUN carriers
Complete visible placement with unknown check time
COMPLETE SYNTHETIC UNRUN HTTP200. All mapped fields are present; the unversioned reference omits version. label,slot,statusReason,lastCheckedAt and removal fields are null. unavailable is a stored state rather than a provider request made by this read.
Request input:
{
"placementId": "plc_docs-example-b"
}
Complete response body:
{
"success": true,
"message": "OK",
"data": {
"placement": {
"id": "plc_docs-example-b",
"organizationId": "org_docs_fixture",
"consumer": {
"appId": "app_example_consumer",
"workspaceId": "ws_consumer_example",
"kind": "example.page",
"id": "page_other"
},
"slot": null,
"reference": {
"app": "app_example_provider",
"workspace": "ws_provider_example",
"type": "example.item",
"id": "item_example"
},
"referenceString": "topolo:app_example_provider/ws_provider_example/example.item/item_example",
"label": null,
"status": "unavailable",
"statusReason": null,
"lastCheckedAt": null,
"createdBy": "user_docs_fixture",
"createdAt": "2026-10-20T10:00:00.000Z",
"updatedAt": "2026-10-20T10:00:00.000Z",
"removedBy": null,
"removedAt": null
}
}
}
Use the exact stored reference and consumer tuple, preserve unknown check time and nullable values, and avoid inferring current provider failure or access.
The id has no visible live placement
COMPLETE SYNTHETIC UNRUN HTTP404 shared by absent, cross-org, deleted and consumer-workspace-inaccessible placements. No successful placement:null body is returned.
Request input:
{
"placementId": "plc_docs-example-b"
}
Complete response body:
{
"success": false,
"error": {
"message": "No placement plc_docs-example-b you can see in this organization",
"code": "placement_not_found"
}
}
RECOVERY UNRUN: retain the original context and use the separately authorized placements.list with a genuinely accessible consumer app/workspace to rediscover a visible id. Retry get only for the id actually returned; if that id is plc_docs-example-b, the exact retry input is the same object above. The success carrier is illustrative, not a claim that access was restored. Do not probe another organization or recreate a deleted placement.
Provenance and changelog
Source applicability: TopoloDevelopers@7b89bd3b39092cdc29f87540847bf99a243f0a40. Current production descriptors for these three actions were read on2026-10-22 and still name this source revision. Handler/store/caller/native-auth boundaries were read as immutable Git objects; no mutable checkout body was used. The current checkout HEAD differs and is not treated as the serving revision. Exact English success copy OK reuses the accepted connection3 source association at the same revision.
2026-10-22: first placement3 paired human/typed source guide; added complete wire/nullability, consumer access and provider boundary, bounded query/visibility semantics, stale-state limits and synthetic success/refusal/recovery carriers. Source association does not prove served runtime or UI behavior.