Single Resource
Status:
stableCategory:catalogAdded:2026-04-20Last reviewed:2026-04-21
Summary
Returns one resource — identified by ?name=, optionally narrowed by
?category= — with its operations and metadata. Use this when you
already know which resource you want.
When ?category= is omitted, lookup is a single pass through the
catalog: top-level resources first, then category-scoped resources in
declaration order, returning the first match. If a resource name were
to exist in more than one category, that ambiguity is resolved by
catalog order — there is no 400 for ambiguity. Callers who care
which category a shared-name resource came from should pass
?category= explicitly.
Endpoint
| Field | Value |
|---|---|
| Method | GET |
| Path | /api/catalog/resource |
| Full URL | https://engine.tripod-health.com/api/catalog/resource |
| Authentication | API key (required) |
| Request body | none |
| Response body | application/json |
| Idempotent | Yes |
| Rate-limited | Yes |
Purpose
- Direct lookup when you know the resource name. One response, one resource, with operations and metadata attached.
- Disambiguating a shared resource name. When the same resource
name is registered in two places (for example, a hypothetical
future
pain/recoveryalongsidertw_belief/recovery), pass?category=to pin the match. - Verifying a resource exists before building URLs that depend on it.
Authentication
Send a valid API key in the apikey header. See
authentication.md.
Request
Headers
| Header | Required | Description |
|---|---|---|
apikey | Yes | Consumer API key. |
X-Request-ID | No | Optional correlation ID. Echoed in the X-Request-ID response header. |
Path parameters
None.
Query parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | — | Resource name (for example "orebro", "cdri"). Exact case-sensitive match. |
category | string | No | any | Category name to narrow the lookup. When omitted, Trinity searches top-level resources first, then every category in declaration order, returning the first match. |
audience | string | No | none | One of employee, employer, provider. Replaces the resource's (and its operations') display_name with the audience alias, falling back to canonical labels. |
Body
None.
Response
Success — 200 OK
The response is a single resource object, matching the resource shape
inside /api/catalog/categories (no
top-level category field or path_prefix — those are
list-formatting additions in
/api/catalog/resources).
{
"name": "orebro",
"display_name": "Orebro Musculoskeletal Pain Screening",
"aliases": {
"employee": "Pain Screening Questionnaire",
"employer": "Musculoskeletal Pain Screening",
"provider": "Orebro"
},
"description": "Orebro Musculoskeletal Pain Screening Questionnaire (OMPSQ): multi-item screening that returns a total score and a risk profile.",
"version": "0.1.0",
"last_updated": "2026-04-17",
"operations": [
{ "name": "questions", "display_name": "Questions", "aliases": {}, "description": "Return the instrument's items, ordering, and answer choices so the caller can render or present them.", "version": "0.1.0", "last_updated": "2026-04-17", "http_method": "GET" },
{ "name": "score", "display_name": "Score", "aliases": {}, "description": "Submit responses to the instrument and receive its score (and profile, where the instrument supports classification).", "version": "0.1.0", "last_updated": "2026-04-17", "http_method": "POST" }
]
}
Response fields
| Field | Type | Always present | Description |
|---|---|---|---|
name | string | Yes | Resource identifier used in paths. |
display_name | string | Yes | Canonical label, or audience alias when ?audience= was set. |
aliases | object | Yes | Audience-to-label map. May be {}. |
description | string | Yes | One-sentence description. |
version | string (SemVer) | Yes | Resource-level version. |
last_updated | string (ISO date) | Yes | Last structural change. |
operations | array | Yes | Operations on this resource. Each entry has name, display_name, aliases, description, version, last_updated, and http_method ("GET" or "POST"). |
Status codes
| Code | Meaning | When |
|---|---|---|
200 | OK | Resource returned. |
400 | ValidationError | name was not provided, or audience was not one of the allowed values. field names the offender. |
401 | Unauthenticated | Missing or invalid API key. |
404 | NotFound | No resource with that name is registered (or not registered in the named category when ?category= was passed). |
429 | RateLimited | Per-consumer rate limit exceeded. |
Examples
The language-specific invocations below assume the call() helper (or
its equivalent) from quickstart.md.
1. Canonical request and response
Send:
GET /api/catalog/resource?name=orebro HTTP/1.1
Host: engine.tripod-health.com
apikey: $ENGINE_API_KEY
X-Request-ID: docs-catalog-resource-canonical
Receive (200 OK):
{
"name": "orebro",
"display_name": "Orebro Musculoskeletal Pain Screening",
"aliases": {
"employee": "Pain Screening Questionnaire",
"employer": "Musculoskeletal Pain Screening",
"provider": "Orebro"
},
"description": "Orebro Musculoskeletal Pain Screening Questionnaire (OMPSQ): multi-item screening that returns a total score and a risk profile.",
"version": "0.1.0",
"last_updated": "2026-04-17",
"operations": [
{
"name": "questions",
"display_name": "Questions",
"aliases": {},
"description": "Return the instrument's items, ordering, and answer choices so the caller can render or present them.",
"version": "0.1.0",
"last_updated": "2026-04-17",
"http_method": "GET"
},
{
"name": "score",
"display_name": "Score",
"aliases": {},
"description": "Submit responses to the instrument and receive its score (and profile, where the instrument supports classification).",
"version": "0.1.0",
"last_updated": "2026-04-17",
"http_method": "POST"
}
]
}
2. Calling the endpoint in your language
curl
# Unscoped
curl -sS "https://engine.tripod-health.com/api/catalog/resource?name=orebro" \
-H "apikey: $ENGINE_API_KEY"
# Scoped to a category (same response when the name is unique)
curl -sS "https://engine.tripod-health.com/api/catalog/resource?name=orebro&category=pain" \
-H "apikey: $ENGINE_API_KEY"
# Top-level resource (no ?category= is valid here)
curl -sS "https://engine.tripod-health.com/api/catalog/resource?name=cdri" \
-H "apikey: $ENGINE_API_KEY"
Python (requests)
# Uses the call() + EngineError from quickstart.md.
def load_resource(name: str, category: str | None = None) -> dict | None:
query = f"?name={name}" + (f"&category={category}" if category else "")
try:
return call("GET", f"/api/catalog/resource{query}")
except EngineError as e:
if e.status == 404:
return None
raise
res = load_resource("orebro", "pain")
if res is None:
raise RuntimeError("orebro/pain is not registered in this deploy")
Node.js (native fetch)
// Uses the call() + EngineError from quickstart.md.
async function loadResource(name, category) {
const query = `?name=${encodeURIComponent(name)}` +
(category ? `&category=${encodeURIComponent(category)}` : "");
try {
return await call("GET", `/api/catalog/resource${query}`);
} catch (e) {
if (e.status === 404) return null;
throw e;
}
}
const res = await loadResource("oswestry", "function");
TypeScript
// Uses the typed call<T>() helper from quickstart.md.
// CatalogResource is the same type shown in catalog-categories.md.
const resource = await call<CatalogResource>(
"GET",
"/api/catalog/resource?name=oswestry&category=function&audience=provider",
);
Go
// Uses the call() helper from quickstart.md.
res, err := call("GET", "/api/catalog/resource?name=orebro&category=pain", nil, 3)
if err != nil {
if ee, ok := err.(*EngineError); ok && ee.Status == 404 {
return nil
}
panic(err)
}
fmt.Println(res["display_name"])
Java
// Uses the call() helper from quickstart.md.
try {
String res = call("GET", "/api/catalog/resource?name=orebro", null, 3);
System.out.println(extract(res, "display_name"));
} catch (EngineException e) {
if (e.status == 404) { /* not registered */ }
else throw e;
}
C# (.NET HttpClient)
// Uses the Call() helper from quickstart.md.
try
{
var res = await Call(HttpMethod.Get, "/api/catalog/resource?name=orebro&category=pain");
Console.WriteLine(res.GetProperty("display_name").GetString());
}
catch (HttpRequestException ex) when (ex.Message.Contains("404"))
{
Console.Error.WriteLine("orebro/pain not registered");
}
PowerShell
# Uses the Invoke-Engine helper from quickstart.md.
try {
$res = Invoke-Engine -Method Get -Path "/api/catalog/resource?name=orebro&category=pain"
$res.display_name
} catch {
if ($_.Exception.Message -match "404") { Write-Warning "not registered" }
else { throw }
}
3. Error scenarios
Wrong category
Send:
curl -sS "https://engine.tripod-health.com/api/catalog/resource?name=orebro&category=function" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-catalog-resource-wrong-category" \
-w "\nHTTP %{http_code}\n"
Receive (404):
{
"timestamp": "2026-04-21T23:06:47.019Z",
"error": "NotFound",
"message": "Resource 'orebro' is not registered in category 'function'",
"request_id": "docs-catalog-resource-wrong-category"
}
Unknown resource at any scope
Send:
curl -sS "https://engine.tripod-health.com/api/catalog/resource?name=frobnitz" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-catalog-resource-unknown" \
-w "\nHTTP %{http_code}\n"
Receive (404):
{
"timestamp": "2026-04-21T23:06:47.414Z",
"error": "NotFound",
"message": "Resource 'frobnitz' is not registered at any scope",
"request_id": "docs-catalog-resource-unknown"
}
Missing name
Send:
curl -sS "https://engine.tripod-health.com/api/catalog/resource" \
-H "apikey: $ENGINE_API_KEY" \
-H "X-Request-ID: docs-catalog-resource-missing-name" \
-w "\nHTTP %{http_code}\n"
Receive (400):
{
"timestamp": "2026-04-21T23:06:47.787Z",
"error": "ValidationError",
"message": "Query parameter 'name' is required",
"field": "name",
"request_id": "docs-catalog-resource-missing-name"
}
Intended use
- Validating a resource before constructing URLs that depend on
it. A
200confirms the resource exists. - Fetching a single resource's details without reading the whole catalog — lighter payload, fewer fields to walk.
- Pinning a lookup to a specific category when you know where the resource lives.
Mistaken use
- Do not pass
?name=with the resource'sdisplay_namevalue. The lookup is on the canonicalnamefield (URL-safe identifier like"orebro","quick_dash"), not the human-readable label. - Do not assume ambiguity is an error. If two categories
registered the same resource name, an unscoped
?name=lookup returns the first match in catalog order — silently and deterministically. Pass?category=when you need to pin down which one. - Do not pass
?category=with a top-level resource name. A top-level resource (cdri,phenotype,screen,naics,health,version,catalog,debug) is not inside any category; scoping the lookup to a category name guarantees404. - Do not use this to discover which resources exist. Use
/api/catalog/resourcesfor that — a flat enumeration withpath_prefixon every entry.
Debugging
- Capture the
X-Request-IDresponse header. 400 ValidationErrorwithfield: "name"— you did not include?name=in the query string, or it was empty.400 ValidationErrorwithfield: "audience"—audiencewas set to an unknown value.404 NotFound— either the resource name is not registered at all, or it is registered but not in the?category=you passed. Compare with/api/catalog/resourcesto see what is actually registered in this deploy.- Got a resource you did not expect. An unscoped
?name=lookup resolves by catalog declaration order when multiple matches exist. Pass?category=to disambiguate. operations[]is missing an operation you expected. The operation is not registered on that resource in this deploy. Cross-reference with/api/catalog/operations.
Rate limits
See rate-limits.md.
Related endpoints
GET /api/catalog/get— full catalog tree.GET /api/catalog/resources— flat resource list withpath_prefixfor each; the surface codegen should read.GET /api/catalog/category— single category with all its resources.GET /api/catalog/operations— flat(method, path, version)tuples.
Change history
| Date | Change |
|---|---|
| 2026-04-20 | Initial publication. |