Search provider references
Search a connected provider’s reference resources with the caller’s own access, then interpret normalized references and pagination.
Action and scope
app_topolo_developers.references.search
GET /api/developer-console/references/search
Required declared permission: app_topolo_developers.connections:read. Authorization mode: static.
Before you start
Use the intended Topolo environment, authenticated identity and active organization. Discover actual canonical app/workspace IDs; fixture IDs in these examples authorize no operation.
Use the current credential-scoped contract, its permission and any required transport resource binding. Keep that binding separate from action input.
All worked responses are source-derived synthetic UNRUN examples. No customer record, provider outcome, serving deployment or automatic Knowledge invocation is established by them.
These connection reads require app_topolo_developers.connections:read and the caller’s own consumer/provider workspace access. Use a person session whose memberships Auth can confirm. Credential extraction also recognizes API keys, but this guide does not certify API-key membership support or a workspace-access bypass.
Input fields
| Field | Required | Meaning and constraints |
|---|---|---|
consumerAppId | Yes | string; pattern: ^app_[a-z0-9]+(?:_[a-z0-9]+)+$ |
consumerWorkspaceId | Yes | string; pattern: ^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$ |
providerAppId | Yes | string; pattern: ^app_[a-z0-9]+(?:_[a-z0-9]+)+$ |
type | Yes | string; pattern: ^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$ |
providerWorkspaceId | No | string; pattern: ^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$ |
query | No | string; minLength: 1; maxLength: 200 |
cursor | No | string; minLength: 1; maxLength: 500 |
id | No | string; pattern: ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,255}$ |
The action input is closed: additional fields are refused by the declared contract.
Behavior and response
Successful reference reads use {success:true,message:"OK",data:...}. Search data contains providerWorkspaceId,type,references,nextCursor. Workspace discovery data contains workspaceScope and workspaces; each row contains workspace,linkStatus,linkId,usable. The declared data schema is open; source-qualified fields here explain these selected branches.
A nonremoved connection for the active organization is required; stored status active or degraded permits this search branch. Other statuses produce409. The consumer must declare this provider/reference type and the provider must still declare it. Consumer workspace access is checked before provider resolution.
For workspace-scoped types, an explicit provider workspace must be accessible and allowed by scope all or an active nonremoved link. Without an explicit choice, exactly one eligible workspace is required; zero is403 and multiple is422. Organization-wide types use the actor organization ID and no provider workspace binding; providerWorkspaceId is ignored for that branch.
id selects the provider get action with {id}; query and cursor are unused in that branch. Otherwise query is mapped only to the provided searchParam, cursor is forwarded, and the declared provider list action runs using the caller’s own credential. No consumer input becomes a new provider credential or grant.
Provider list extraction prefers root.items, root.results, root.data arrays, then nested data.items/results, then the first remaining array in data/root. Get extraction chooses an id-bearing data.<kind>,data,root.<kind>,or root object. Unsupported shapes yield no normalized items.
Valid string IDs and numeric IDs converted to strings are normalized into Topolo references; invalid reference IDs are dropped. Label uses the first nonblank label/name/title string, otherwise the id; status uses a nonempty status string, otherwise available. The first string updatedAt/updated_at is copied without date normalization. Positive safe-integer version becomes currentVersion; the returned reference itself is unpinned.
Cursor selection uses the first nonempty string among root.nextCursor,data.nextCursor,data.page.nextCursor,root.page.nextCursor. A get always has nextCursor:null. Provider401/403 becomes403 reference_access_denied; provider404 or a not_found error code becomes404 reference_not_found; other SDK failures become502 provider_unavailable.
Errors and recovery
HTTP 404 · connection_not_found — Read the current connection/capability state for the exact pair. Do not create a connection automatically.
HTTP 409 · connection_not_active — Retain actual stored status; any activation or approval requires separate owner authority.
HTTP 422 · reference_not_declared — Use a type the consumer declares from this provider; inspect the declared placement list.
HTTP 409 · provider_contract_missing — Resolve provider declaration currency; do not invent a type or action.
HTTP 403 · workspace_access_required — Use a workspace the caller can access in the original organization.
HTTP 503 · workspace_access_unavailable — Recover Auth membership availability. Do not interpret failure as an empty list.
HTTP 403 · workspace_link_required — Choose an allowed pair; creating or approving a link is a separate mutation.
HTTP 422 · provider_workspace_required — Select an intended returned eligible provider workspace explicitly.
HTTP 422 · search_not_supported — Remove query only for an intended unfiltered list; preserve type/identity.
HTTP 403 · reference_access_denied — Restore the caller’s intended provider read access; no connection or admin bypass.
HTTP 404 · reference_not_found — Check current provider action and resource identity; this mapping can include a missing provider action.
HTTP 502 · provider_unavailable — Retain actual provider failure context and use the provider owner; upstream statuses beyond401/403/404 are mapped here.
Error code labels above are source wire codes where explicitly shown in worked responses; shared authentication/permission labels are explanatory classifications when the actual upstream carrier differs. Common framework refusals may occur before these branches.
Worked examples — synthetic and unrun
Normalize a provider list and retain its cursor
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 200. Assume active linked connection, declared consumed/provided example.item, confirmed consumer access, and exactly one eligible provider workspace. The declaration supplies listAction items.list and searchParam search. The unrun provider response is data.items containing {id:item_fixture_1,name:Fixture item,status:published,updatedAt:2026-10-23T00:00:00.000Z,version:3}, {id:7,title:Numeric fixture,version:0}, and {id:invalid/id}; data.page.nextCursor is fixture_cursor_out. The invalid slash-containing id is dropped.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item",
"query": "fixture",
"cursor": "fixture_cursor_in"
}
Complete response body:
{
"success": true,
"message": "OK",
"data": {
"providerWorkspaceId": "ws_provider_fixture",
"type": "example.item",
"references": [
{
"reference": {
"app": "app_docs_provider",
"workspace": "ws_provider_fixture",
"type": "example.item",
"id": "item_fixture_1"
},
"referenceString": "topolo:app_docs_provider/ws_provider_fixture/example.item/item_fixture_1",
"label": "Fixture item",
"status": "published",
"updatedAt": "2026-10-23T00:00:00.000Z",
"currentVersion": 3
},
{
"reference": {
"app": "app_docs_provider",
"workspace": "ws_provider_fixture",
"type": "example.item",
"id": "7"
},
"referenceString": "topolo:app_docs_provider/ws_provider_fixture/example.item/7",
"label": "Numeric fixture",
"status": "available",
"updatedAt": null,
"currentVersion": null
}
],
"nextCursor": "fixture_cursor_out"
}
}
Provider input is {search:fixture,cursor:fixture_cursor_in}, bound to the selected provider workspace. Preserve currentVersion separately; these references contain no pinned version.
Get an organization-wide reference
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 200. Assume active connection and declared organization-wide reference type (workspaceScoped:false), consumer access, active actor organization org_docs_fixture, and a synthetic provider get result data.item={id:item_fixture_2,title:Organization fixture,version:2}.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item",
"id": "item_fixture_2",
"providerWorkspaceId": "ws_ignored_fixture",
"query": "ignored fixture query",
"cursor": "ignored_cursor"
}
Complete response body:
{
"success": true,
"message": "OK",
"data": {
"providerWorkspaceId": "org_docs_fixture",
"type": "example.item",
"references": [
{
"reference": {
"app": "app_docs_provider",
"workspace": "org_docs_fixture",
"type": "example.item",
"id": "item_fixture_2"
},
"referenceString": "topolo:app_docs_provider/org_docs_fixture/example.item/item_fixture_2",
"label": "Organization fixture",
"status": "available",
"updatedAt": null,
"currentVersion": 2
}
],
"nextCursor": null
}
}
The id branch calls items.get with {id:item_fixture_2}; query and cursor are unused. Organization-wide resolution ignores providerWorkspaceId and sends no provider workspace binding. Verify the returned organization identity.
A successful get body has no usable resource id
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 200. Assume all connection/declaration/workspace checks pass. The provider get completes with data.item={name:No id}, with no id-bearing data or root fallback.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item",
"id": "item_missing_fixture",
"providerWorkspaceId": "ws_provider_fixture"
}
Complete response body:
{
"success": true,
"message": "OK",
"data": {
"providerWorkspaceId": "ws_provider_fixture",
"type": "example.item",
"references": [],
"nextCursor": null
}
}
An empty normalized result is distinct from a provider 404. It does not prove global nonexistence or that every provider result shape was understood.
Several provider workspaces require a choice
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 422. Assume active connection, declared workspace-scoped type, consumer access, and two eligible provider workspaces in this exact iteration order.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item"
}
Complete response body:
{
"success": false,
"error": {
"message": "Several provider workspaces are available; pass providerWorkspaceId",
"code": "provider_workspace_required",
"details": {
"providerWorkspaceIds": [
"ws_provider_fixture_a",
"ws_provider_fixture_b"
]
}
}
}
Select an intended discovered workspace and plan a new read; do not choose one implicitly or create links as automatic recovery. No provider read is reached.
The provider type declares no search parameter
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 422. Assume all prior checks pass, no id is supplied, and the provided type has no searchParam.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item",
"query": "fixture",
"providerWorkspaceId": "ws_provider_fixture"
}
Complete response body:
{
"success": false,
"error": {
"message": "app_docs_provider declares no search parameter for example.item; list without query",
"code": "search_not_supported"
}
}
Omit query only when an unfiltered authorized list is intended. The provider action has not been called.
Provider access is refused
SOURCE-DERIVED SYNTHETIC UNRUN HTTP 403. Assume the selected provider list action is items.list and its SDK read rejects with status401 or403 after all local checks.
Input:
{
"consumerAppId": "app_docs_consumer",
"consumerWorkspaceId": "ws_consumer_fixture",
"providerAppId": "app_docs_provider",
"type": "example.item",
"providerWorkspaceId": "ws_provider_fixture"
}
Complete response body:
{
"success": false,
"error": {
"message": "The caller may not use app_docs_provider.items.list",
"code": "reference_access_denied"
}
}
Retain the denial. Restore the caller’s intended provider access through its owner; connection status or organization ownership is not a provider permission grant.
Verify the result
Compare providerWorkspaceId and type with the intended actual provider context; for organization-wide types verify the active organization id.
Inspect the normalized referenceString,id,label,status,currentVersion and cursor. Empty normalized results and positive currentVersion are not independent existence, permission or version-pin proofs.
Follow only a real returned nextCursor under the same provider/query context. An intended placement is a separately authorized action.
Recovery boundary
The selected route has no connection, workspace-link or placement mutation to undo. Preserve the actual context, error and request identifier. Correct invalid input or restore the original authorized dependency/access through its owner; a link, permission or connection change is a separate approved operation. Authentication and other transitive framework effects are outside this selected-handler review.
Related actions
app_topolo_developers.references.workspaces.listapp_topolo_developers.placements.create
Source provenance and limits
Source review uses Developers 7b89bd3b39092cdc29f87540847bf99a243f0a40 and the retained action declarations captured 2026-10-22T22:44:25.344421+00:00. It does not certify that this revision or the locked dependency versions are serving together. All examples are fictional and unrun. Automatic Knowledge invocation during relevant builds remains UNKNOWN.
Reference routing, normalization and error mappings follow the pinned placement service, store, caller context, HTTP envelope and locked app-manifest0.4.0. Transitive Auth/SDK/provider implementations are boundaries, not independently observed outcomes.
Change log
- 2026-10-23: Initial documentation of references.search with access/context requirements, source-qualified response handling and synthetic, unrun worked examples. No application behavior change is asserted.