A response that includes userId but no information about how to fetch the user forces every consumer to hardcode the URL pattern /api/v1/users/{userId}. When that pattern changes, every consumer breaks — and there is no machine-readable artifact that could have warned them. iso-25010:2011 compatibility.interoperability is the direct gap: the API returns foreign keys but not the means to navigate them, making the API partially self-describing at best and requiring consumers to maintain their own URL construction knowledge.
Info because missing resource links are a navigability improvement rather than a functional defect — consumers can work around the gap by hardcoding URL patterns, but it makes the API less self-documenting.
Add basic resource linking to make responses partially self-describing. Even just self URLs are a meaningful improvement over bare IDs:
// Before -- ID only, consumer must know URL pattern:
{
"id": "order-123",
"userId": "user-456"
}
// After -- with links:
{
"id": "order-123",
"userId": "user-456",
"_links": {
"self": "/api/v1/orders/order-123",
"user": "/api/v1/users/user-456"
}
}
Start with self links on every resource — that alone lets consumers build shareable URLs and canonical references. Add related resource links for the two or three relationships consumers navigate most frequently.
ID: api-design.developer-ergonomics.resource-linking
Severity: info
What to look for: Check whether API responses include links or references to related resources that consumers commonly need to navigate to. Look for: HATEOAS-style _links objects, url fields pointing to related endpoints, id fields for related resources that consumers can use to construct URLs. The question is: can a consumer navigate the API starting from any response, or do they need to hardcode URL patterns? This is aspirational for most APIs -- full HATEOAS is rare, but basic linking (e.g., including a self URL or related resource URLs) improves ergonomics significantly.
Pass criteria: Count all resource relationships across responses (foreign key IDs referencing other resources). Responses include at least 1 form of basic resource linking -- either self URLs on resources, URLs for related resources, or consistent ID fields that follow a documented URL pattern consumers can construct.
Fail criteria: Responses include no linking information. Related resource IDs are present but the URL pattern to fetch them is not documented (e.g., { "userId": "abc" } with no way to know the URL is /api/v1/users/abc). Consumers must hardcode URL construction for every resource relationship.
Skip (N/A) when: The API has 3 or fewer endpoints with no resource relationships. Also skip for GraphQL (relationships navigated via query structure, not links) and gRPC (links are not a convention).
Detail on fail: Note what's missing (e.g., "Order response includes userId but no URL to fetch the user. Product responses include categoryId but the pattern to fetch a category is not documented anywhere. No self URLs on any resource."). Max 500 chars.
Remediation: Add basic resource linking to improve API navigability:
// Before -- ID only, consumer must know URL pattern:
{
"id": "order-123",
"userId": "user-456",
"items": [{ "productId": "prod-789" }]
}
// After -- with links:
{
"id": "order-123",
"userId": "user-456",
"items": [{ "productId": "prod-789" }],
"_links": {
"self": "/api/v1/orders/order-123",
"user": "/api/v1/users/user-456",
"items": "/api/v1/orders/order-123/items"
}
}
Even partial linking (just self URLs) is a significant improvement.