From a single endpoint to hypermedia: how to assess, evolve, and govern HTTP APIs without confusing adoption levels with complete architectural compliance
In-depth edition - study material and professional reference
By João Ricardo Dutra••Complete material
Interface evolution according to the
Overview - Single , capabilities, , and form a cumulative progression of observable capabilities.
Each level adds a drawing ability; the model does not certify complete compliance with REST.
Chapter presentation
The , commonly abbreviated as , organizes service interfaces into four levels: a message-oriented entry point, identifiable resources, semantic use of HTTP, and controls. The model was proposed by Leonard Richardson and popularized by Martin Fowler as a didactic way to decompose some central elements of a REST approach. Its value is in allowing teams to look at concrete capabilities of the interface without relying solely on the “RESTful” label.
The model, however, is not a certification standard and does not replace the architectural constraints described by Roy Fielding. An API can reach level 2 by using HTTP resources, methods, and code consistently and still maintain a conversational session on the server, prevent caching, expose implementation details, or create strong temporal coupling. Likewise, an interface can adopt links without its clients actually navigating through the transitions offered. Therefore, level and quality are not automatic synonyms.
In this chapter, each level will be analyzed in depth, with examples of fictional corporate and banking APIs. The effects on contracts, consumers, API Gateways, retries, , caching, authorization, observability and evolution will be studied. The objective is not to advocate that every API must reach level 3, but to provide criteria for consciously choosing how far to advance and what properties to obtain.
The analysis will also show that cross-tier migration is not just an exchange of URLs. It requires identifying resources, separating commands from representations, assigning correct semantics to methods and responses, defining relationships, planning for compatibility, and adjusting gateway policies. In environments with many consumers, the evolution sequence needs to be measurable and reversible.
How to Study This Chapter Use the same business operation when going through all levels. Compare the way of addressing, the intention expressed by the method, the codes returned, the possibility of caching, the retry rules and the knowledge required from the client. Comparison better reveals what each level adds.
Learning Objectives
Explain the origin, purpose and limits of the .
Differentiate levels 0, 1, 2 and 3 by observable properties of the interface.
Recognize RPC patterns and imperative messages concentrated on an .
Model stable resources without confusing , table, DTO and operation.
Apply HTTP methods, codes, headers, cache and preconditions at level 2.
Design links and actions that represent permitted transitions.
Compare with REST architectural constraints and with OpenAPI.
Evaluate existing APIs without turning the analysis into a superficial score.
Plan incremental migration, governance and troubleshooting on API Gateways.
Chapter structure
11.1 Origin and purpose of the model
11.2 What measures - and what it doesn't measure
11.3 Overview of the four levels
11.4 Level 0: The Swamp
11.5 Level 0 operational standards and risks
11.6 Transition from level 0 to level 1
11.7 Level 1: Resources
11.8 Identity, granularity and lifecycle
11.9 Level 1 Limitations
11.10 Transition to level 2
11.11 Level 2: HTTP methods and semantics
11.12 Status, headers, cache and preconditions
11.13 , retries and errors
11.14 Level 2 in API Gateways
11.15 Level 3: Controls
11.16 Relationships, links and actions
11.17 Types of media and contracts
11.18 Transition-driven clients
11.19 Benefits, costs and pitfalls of level 3
11.20 versus Fielding's REST
11.21 , OpenAPI and governance
11.22 Evaluation matrix
11.23 Migration strategy
11.24 Observability and troubleshooting
11.25 Case studies and labs
Summary, checklist, exercises, glossary and references
11.1 Origin and purpose of the model
Leonard Richardson formulated the model as a way to classify web service styles by the progressive adoption of web features. Martin Fowler popularized it in 2010 with the image of a ladder: at level 0 there is a single message-oriented entry point; at level 1 resources appear; at level 2 the interface uses HTTP methods and responses; at level 3 the representations offer controls. The simplicity of this decomposition has made useful in training, architecture reviews, and modernization discussions.
The word maturity can lead to a misinterpretation. Higher level does not necessarily mean that the product, team, or domain is “more mature” in every aspect. The model describes a specific dimension of the interface. Security, availability, governance, documentation, performance, privacy, consistency and developer experience need their own assessments. A Level 2 API can be highly reliable and context-appropriate; a level 3 API may be insecure or poorly operated.
The model works best as a diagnostic language. Instead of just asking “is this API REST?”, the team can ask: are there identifiable resources? Do methods express intent? Does the response use coherent statuses and headers? Does the consumer discover transitions through ? These questions produce evolving evidence and decisions.
Responsible use of the term maturity Use the level to describe interface capabilities, not to classify people or determine total quality. Separately record attributes such as security, compatibility, SLOs, documentation, governance and operational cost.
11.2 What measures - and what it doesn't measure
mainly observes three moves: decomposing a generic operation into identifiable resources, taking advantage of HTTP's standardized semantics, and making transitions visible in the itself. These moves reduce some of the coupling between consumer and server because they transfer knowledge to shared Web elements: URIs, methods, codes, headers, links and relations.
The model does not check all REST constraints. Client-server, stateless, cache, layered system and code on demand do not appear as independent steps. Level 2 touches on caching and uniform interface, and Level 3 approaches as an application state driver, but full evaluation of REST requires broader architectural analysis. Therefore, Fowler describes level 3 as a step toward “REST glory,” not automatic proof of compliance.
There is also no universal test to decide the level when the API mixes styles. A platform may have query endpoints at level 2, legacy commands at level 0 and a specific flow with . In these cases, classifying the entire API by a single number hides information. The analysis must be done by surface, or business journey, recording exceptions.
11.3 Overview of the four levels
Figure 1 - organizes interface capabilities into four cumulative levels, but does not measure all attributes of an API platform.
Table 1 - Capabilities, dependencies and risks associated with each level.
Level
Added element
Core client knowledge
Characteristic risk
0
Messages about an endpoint
Operations and proprietary format
Central dispatcher, little shared semantics
1
Resources and identifiers
What resources exist and how to address them
Resources treated only as command envelopes
2
HTTP methods, status and headers
Protocol semantics and resource contract
Decorative use of inconsistent verbs or codes
3
Hypermedia Controls
Media relationships and types
Links without semantics or clients that continue to encode the flow
11.4 Level 0: The Swamp
At level 0, the service typically publishes a single and uses the message body to indicate which operation should be performed. stands for “Plain Old XML”, a historical expression for XML messages without taking advantage of richer Web resources; In current practice, the same structure may appear with JSON, Protobuf, or another format. The decisive aspect is not the format, but the concentration of intentions in a generic interface.
A payments service could always receive POST /service-payments and distinguish operations by a field like operation. Check balance, create transfer, cancel appointment and issue statement share the same address and method. The server acts as a dispatcher: it interprets the command and forwards it to the corresponding routine. Many SOAP services, RPC over HTTP, and legacy integrations approach this level.
Figure 2 - At level 0, the protocol carries a proprietary message and the body concentrates the intention of the operation.
Level 0 is not synonymous with bad implementation. In closed scenarios, command queues, binary protocols, highly specialized operations, or compatibility with legacy systems, RPC may be a valid decision. The problem arises when the organization expects Web properties - caching, uniform semantics, visibility through intermediaries and decoupled evolution - without exposing elements that allow them to be obtained.
11.5 Level 0 operational standards and risks
The main consequence is that intermediate components see little difference between operations. An API Gateway observes multiple POSTs for the same path, and the real distinction is hidden in the body. Authorization rules, quotas, caching, metrics, and routing need to inspect content or trust proprietary fields. This increases policy costs, reduces performance and makes it difficult to correlate with tools that aggregate metrics by method and route.
Retries also become risky. The POST method does not tell you whether an operation is repeatable, and the same can contain queries, idempotent commands, and non-idempotent commands. A timeout leaves the client without knowing whether the server performed the action. The solution often requires correlation identifiers, keys, or processing status, but these mechanisms need to be defined outside the basic semantics of the protocol.
Errors often return 200 with an envelope containing success=false or internal codes. This practice prevents load balancers, gateways, SDKs, and observability from using the HTTP status class as a signal. It also creates ambiguity between transport failure, gateway rejection and business error. The consumer needs to interpret the body before classifying any result.
Level 0 Signal If the documentation starts with a list of accepted operations in an action, command, operation, or serviceName field and almost everything uses POST in the same path, the interface is probably at level 0, even when the messages are JSON and the product is called a REST API.
Table 2 - Typical effects of an interface concentrated at level 0.
Symptom
Impact on the gateway
Impact on the consumer
One URI for everything
Policies depend on body inspection
SDK needs to know dispatcher and internal codes
200 for success and error
Status metrics become misleading
Error handling depends on the envelope
POST for reading and writing
Cache and security cannot infer intent
Retry requires specific rule per operation
Extensive core contract
Changes affect large surface
Versioning and testing become monolithic
11.6 Transition from level 0 to level 1
The first transition consists of making explicit the entities or concepts that have an identity and life cycle. Instead of sending all messages to /service, the interface now addresses customers, accounts, transfers, appointments and statements. This change requires understanding the domain: a transfer is not just a function; it can be created, validated, confirmed, rejected, canceled and consulted over time.
The migration must start with inventory. Each dispatcher operation is classified as query, create, change, command, process, or integration. Next, the team identifies which objects need a stable address, which are subordinate to others, and which represent processes. The goal is not to turn every table into an , but to find units of meaning that consumers can reference.
Compatibility can be preserved with an adaptation layer. The legacy continues to accept messages and internally calls the new -oriented services. New consumers adopt the new surface, while metrics measure the reduction in use of the old contract. This strategy avoids a “big bang” migration and allows you to validate the modeling before removing the dispatcher.
Modeling Question What needs to be identified, queried, or referenced after the operation is complete? The answer often reveals a . A transfer request, for example, continues to exist as an auditable entity even after the initial response.
11.7 Level 1: Resources
At level 1, the interface publishes multiple resources with their own identifiers. The consumer no longer knows just a generic gateway and starts interacting with addresses that represent parts of the domain. The URI serves as an identifier, not as a complete description of the implementation. /transfers/abc can remain valid even if the service changes bank, language or topology.
The model does not require level 1 to correctly use all HTTP methods. The API can continue sending POST to /customers/483/view, /transfers/abc/cancel or /accounts/991/statement. There has been progress in identification, but the intention is still partially encoded in path verbs or in the body. This characteristic explains why resources are necessary but insufficient for a semantically rich HTTP interface.
Figure 3 - Distinctive capabilities make identity and scope visible, although operations may still remain imperative.
11.8 Identity, granularity and lifecycle
A is an identifiable abstraction, not necessarily a database row. It can represent a durable entity, a collection, a projection, a document, a process, or the result of a calculation. /limits-operacional/customer-483 may be a calculated view; /transfer-requests/abc can represent a process; /statements/account-991/2026-07 can represent a document produced for a period.
Granularity should reflect cohesion and access patterns. Excessively large resources force consumers to transfer and update irrelevant data. Very fragmented resources increase round trips and composition complexity. In corporate systems, the boundary also needs to consider authorization, ownership, transactional consistency and capacity for independent evolution.
Public identifiers should not expose internal keys unnecessarily. A sequential number can facilitate enumeration and reveal volume; a table key can change during migrations. The API can use opaque identifiers, business aliases, or stable URIs. The important thing is to define uniqueness, scope, permanence and behavior when the is removed or replaced.
Table 3 - Questions to model resources at level 1.
Decision
Technical question
Example
Identity
Does the resource need to be referenced later?
/transferences/{id}
Scope
Is identity global or subordinate?
/accounts/{account}/schedules/{id}
Granularity
What data changes and is authorized together?
separate registration preferences
Life cycle
What states and transitions are there?
PENDING -> CONFIRMED -> SETTLED
Permanence
Does the identifier survive internal migrations?
opaque public ID
11.9 Level 1 Limitations
Separating resources improves observability and organization, but does not alone resolve the semantics of operations. Endpoints such as POST /transfers/abc/view and POST /transfers/abc/remove still hide properties known by HTTP. The gateway cannot infer that querying is safe or that removing should produce a certain response class. The client depends on conventions specific to each API.
Another risk is creating “fake resources” just to accommodate verbs. Paths such as /createTransfer, /executePayment or /getCustomers use multiple addresses, but continue modeling functions. This interface may be clear and functional, but progress toward a uniform interface is limited. Analysis should look at the meaning of the identifier, not just count URLs.
At level 1, collections and relationships can also be inconsistent. One team can use /customer/483/account and another /viewContasPorCliente?id=483. Without standards for naming, cardinality, pagination, and errors, expansion increases surface area without generating predictability. Governance remains necessary.
11.10 Transition to level 2
The second transition is to map intentions to . Queries use GET or HEAD; creation usually uses POST in the collection; idempotent substitution can use PUT; removal uses DELETE; Partial updates can use PATCH when their format and semantics are defined. The method stops being just a transport field and starts communicating properties to clients and intermediaries.
This migration also requires reviewing responses. Creation may return 201 Created with Location; asynchronous processing can use 202 Accepted; unsatisfied precondition may produce 412; state conflict may produce 409; validation can use . Headers such as ETag, Cache-Control, Allow, Retry-After and Vary become part of the contract.
It is not enough to replace POST with different verbs. Behavior needs to respect security, and semantics. A GET that cancels a schedule is still dangerous, even if the path appears -oriented. A PUT that creates additional effects on each repetition is not idempotent. Level 2 relies on observable behavior, not syntactic decoration.
Example of reading with
GET /transfers/abc HTTP/1.1
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "v7"
{ "id": "abc", "status": "PENDING", "amount": 120.00 }
Transition criteria For each operation, record: target , method, security property, , success response, errors, headers, cacheability, and retry policy. The table highlights where changing the verb requires a real change in behavior.
11.11 Level 2: HTTP methods and semantics
At level 2, the interface uses the HTTP vocabulary to express intentions. The semantics are shared across browsers, libraries, proxies, gateways, and observability tools. GET is safe and should not request a change of state; PUT and DELETE are idempotent; POST is flexible and normally non-idempotent; HEAD has the same semantics as GET without response content. PATCH depends on the type of patch document used.
The benefit is not just aesthetic. A gateway can apply different rules for reading and writing, caches can reuse responses, SDKs can classify results by status, clients can implement retries of idempotent operations more safely, and SRE teams can group metrics by method and route. The interface becomes more visible to components that do not know the domain.
Figure 4 - Standardized methods and responses allow generic components to understand interaction properties.
11.12 Status, headers, cache and preconditions
Status codes classify the result of attempting to process the request. They do not replace domain details, but provide an interoperable first layer. 2xx indicates successful processing; 3xx advises redirection or reuse; 4xx indicates that the request cannot be met under the conditions presented; 5xx points to a server or intermediary failure. The choice should reflect who produced the response and the observed state.
Headers expand semantics. Location identifies the created or the relevant location; ETag represents a version of the ; If-Match and If-None-Match express preconditions; Cache-Control controls reuse; Retry-After guides retry; Allow reports supported methods; Vary describes which fields in the request influence the response. Ignoring these elements reduces level 2 to a table of verbs.
Preconditions are especially important in enterprise APIs. Two consumers can read the v7 version of a and attempt to update it. Without control, the last writing overwrites the previous one. With ETag and If-Match, the server performs the change only if the version still matches. If the state has changed, it returns 412 Precondition Failed, allowing the client to reload and reconcile.
Table 4 - Protocol elements that make the interface more operable.
HTTP Element
Use at level 2
Common fault
201 + Location
Confirm creation and inform identifier
Return 200 without reference to new resource
202 + monitor
Accept process not yet completed
Treating acceptance as ultimate success
ETag/If-Match
Prevents lost updates
Generate ETag without validating preconditions
Cache-Control
Defines reuse and revalidation
Cache sensitive response without explicit policy
Retry-After
Guide new attempt
Reply 429/503 without window or strategy
11.13 , retries and errors
means that repeating the same request produces the same intended effect on the server, although the of the response may vary. PUT and DELETE are defined as idempotent; POST does not receive this guarantee by default. In distributed systems, timeout does not prove that the operation failed. The client may lose the response after the server completes the command, creating a risk of duplication.
For non-idempotent operations, an key can associate equivalent attempts with a single result. The server needs to define scope, expiration, payload comparison, persistence and concurrent behavior. The gateway may require the header and limit format, but business deduplication generally belongs to the service that knows the operation and its transaction.
Errors must combine HTTP status and a stable . , currently defined by RFC 9457, provides fields such as type, title, status, detail and instance, as well as extensions. The status classifies the result; the type identifies a problem category; extensions carry structured data. Internal messages, stack traces and sensitive data must not be exposed.
Structured error at level 2
HTTP/1.1 409 Conflict
Content-Type: application/problem+json
{
"type": "https://api.example/problems/invalid-state",
"title": "Transition not allowed",
"status": 409,
"detail": "The transfer has already been settled.",
"instance": "/transfers/abc"
}
Retry is not just client configuration The strategy depends on method, , failure phase and deduplication capability. Automatically repeating a financial POST after timeout without an key can duplicate effects.
11.14 Level 2 in API Gateways
API Gateways benefit directly from level 2 semantics. Policies can separate reading and writing per method, apply quotas per operation, block unpublished methods, validate Content-Type and Accept, propagate correlation IDs, produce 405 when the method is not allowed, and normalize infrastructure errors. Metrics by route template and status become more representative.
The gateway, however, does not transform an API into level 2 just by rewriting paths or methods. If it receives GET and internally calls a command that changes state, the security property has been violated. If you convert every backend error into 200, you destroy semantics. If you add ETag without ensuring that the version represents the state, you create a false precondition. Responsibility needs to be shared with the service.
In multi-hop architectures, you must record where each response was created. A 429 can come from the quota gateway, a 503 from the balancer, a 409 from the domain, and a 401 from the identity provider. Standardization helps the consumer, but logs and correlation headers need to preserve the source for troubleshooting.
Figure 5 - The gateway reinforces the interface and applies cross-cutting policies; the domain semantics still belong to the API.
Table 5 - Use of level 2 in gateway policies.
Politics
Adequate responsibility
Antipattern
Authentication
Validate credential and context
Invent thin authorization without domain data
Routing
Map contract to upstream
Mask incompatible routes without observability
Rate limiting
Protect capacity and plans
Use the same limit for light read and expensive command
Validation
Reject invalid form of contract
Accept payload and silently change meaning
Error transformation
Normalize infrastructure and format
Convert all errors to 200 or 500
11.15 Level 3: Controls
Level 3 adds controls to representations. In addition to returning data, the server reports relationships and transitions available in the current state. A pending transfer may offer self, confirm, and cancel links; a settled transfer can only offer self and receipt. The client does not need to construct all the URLs or maintain a complete table of states to know which actions are enabled.
This approach is related to the principle: as the engine of application state. “Application state” refers to the client's progress through a sequence of interactions, guided by incoming controls. The server continues to control the state of resources, while the describes possible paths. The Web works this way when a browser receives links and forms.
Figure 6 - The of a pending transfer exposes only the transitions allowed at that time.
A useful link has a destination and a semantic relationship. The self relation indicates the canonical identification of the ; next and prev can navigate pages; collection points to the collection; item relates collection and member. Relationships registered with IANA allow shared meaning, while specific relationships can use their own URIs. The field name alone should not be the only semantic definition.
Actions require more information than a href. The client may need method, content type, fields, constraints and documentation. Different formats represent this information in different ways. There is no single mandatory format for REST; the contract must define the type of media, the relationships and how to interpret controls.
Controls need to reflect authorization and status, but their absence does not replace enforcement. The server must validate every action again. A client can fabricate a request or reuse an old link. guides the experience and reduces invalid attempts; authorization and validation remain mandatory.
Table 6 - Relationships must have stable and documented meaning.
Relationship
Possible meaning
Note
self
Current representation identifier
Help caching, correlation and updating
collection
Collection the item belongs to
Can guide navigation and creation
next/prev
Pagination or sequence
Prefer full links to cursor reconstruction
confirm
Specific domain transition
Define relationship by URI or media contract
describedby
Document describing the resource
Does not replace executable controls
11.17 Types of media and contracts
depends on a convention that the client understands. application/json, alone, only defines the JSON syntax; it does not tell you that _links contain relationships, that actions describe forms or how URI templates should be expanded. The API can adopt a known media type, profile, or organization-specific type. The important thing is that the meaning is explicit and versionable.
Specific media types can enable independent evolution of URLs, but also increase governance and tooling. SDKs, validators, gateways, and documentation need to know the format. In organizations with many teams, an internal specification must define mandatory fields, registered relationships, templates, actions, errors, compatibility and security rules.
Web Linking, defined by RFC 8288, allows you to transport links in headers and representations. URI Templates, defined by RFC 6570, allow describing parameterized destinations. These patterns can compose a solution, but they do not alone provide a complete model of actions. The choice must consider consumers’ real capabilities.
JSON does not have by default A field called links is just data until the contract defines relationships, targets, cardinality, templates, and client behavior. The maturity is in the shared semantics, not the object name.
11.18 Transition-driven clients
A -driven client starts with a small set of known points and navigates through relationships. It looks for rel=confirm, instead of concatenating /confirmation; interprets an available action, rather than coding that PENDING always allows confirmation. This reduces coupling to the topology and part of the flow rules.
The reduction is not absolute. The client still knows relationships, media types, and domain semantics. Changing the meaning of confirm is breaking change. Removing a relationship may change functionality. shifts the coupling of URLs and rigid sequences to vocabularies and affordances, which need governance.
Clients generated exclusively from OpenAPI tend to call static operations. To explore level 3, the runtime needs to analyze representations and choose transitions. It is possible to combine the approaches: OpenAPI describes operations and schemas, while relationships in the responses guide availability and navigation. Tests must verify both.
Relationship-driven client pseudocode
transfer = GET(entrypoint).follow("transfer-by-id", id="abc")
if transfer.has_relation("confirm"):
result = transfer.follow("confirm", body={"otp": "..."})
else:
show_message("Confirmation is not available in the current state")
11.19 Benefits, costs and pitfalls of level 3
The main benefit is that it allows the server to communicate valid transitions and change certain destinations without requiring clients to reconstruct URLs. This can improve discoverability, reduce invalid calls, facilitate long streams, and make state more explicit. In domains with relevant state machines - onboarding, payments, orders, approvals - dynamic controls can bring concrete value.
The cost appears in design, documentation, libraries and testing. The team needs to define relationship vocabularies, represent actions, maintain media types and educate consumers. Enterprise tools are more mature for OpenAPI and static SDKs than for generic clients. If consumers ignore links and continue concatenating paths, the cost is paid without getting the benefit.
A common pitfall is to return all possible links, regardless of status or authorization. This turns into a static catalog and can expose unnecessary information. Another is to use undefined relations, such as action1 or execute. It is also inappropriate to believe that links eliminate versioning: schemas, relationships and semantics continue to evolve.
Table 7 - The decision to adopt hypermedia depends on the domain and ecosystem.
Situation
Level 3 tends to help
Level 3 may not pay off
Business flow
Multiple states and dynamic transitions
Simple and stable CRUD
Consumers
Clients capable of interpreting relationships
Strict batch integrations and generated SDKs
Topology
Destinies and actions evolve frequently
Few operations and stable URLs
Governance
Shared vocabulary and media type
Each team invents its own format
Operation
Telemetry of relationships and transitions
Links are not observed or tested
11.20 versus Fielding's REST
The is a didactic decomposition of some elements; REST is an architectural style made up of constraints. Level 1 relates to identification. Level 2 comes closest to uniform interface and the use of . Level 3 emphasizes controls. However, the model does not have explicit steps for client-server, stateless, cache, layered system and code on demand.
An API can be at level 3 and still rely on session affinity in an instance, disable caching on all responses, expose persistence details, and require simultaneous coordination between client and server with each change. In this situation, the interface uses , but the architecture does not achieve several expected REST properties.
The reverse also requires nuance. An API at level 2 can apply client-server, stateless, cache and layers in a robust way, remaining far from the full use of . Calling it “immature” without considering context may be less useful than recording exactly what constraints and properties are present.
Table 8 - RMM and REST answer related but different questions.
Appearance
Richardson Maturity Model
Fielding REST
Purpose
Classify visible interface capabilities
Define architectural style and emergent properties
Structure
Four cumulative levels
Combined Constraint Set
Focus
Resources, HTTP and hypermedia
Components, connectors, data, and constraints
Result
Evaluation and evolution language
Analysis of architectural properties
Limit
Does not measure total quality or all constraints
Does not prescribe a single endpoint design
11.21 , OpenAPI and governance
OpenAPI describes HTTP operations, parameters, schemas, responses and security mechanisms. It is excellent for contract design, documentation, client generation, mocking, and testing. However, a valid description can represent any level: a single POST with operation field, multiple resources still handled by POST, a level 2 interface, or operations whose responses include .
Governance can use automatic rules to detect signs of levels: excessive concentration of POST, verbs in paths, lack of 4xx responses, creation without Location, methods incompatible with security, lack of error schemas and operations without tags. These rules are heuristics. The actual semantics, idempotent behavior, and quality of relationships require human review and testing.
In enterprise pipelines, analysis should combine contract lint, contract testing, behavior testing, and telemetry. OpenAPI reports what has been declared; tests verify what the runtime executes; the gateway shows how consumers actually use the interface. An API can document PUT and implement non-idempotent effect; only behavior reveals the divergence.
Contract is not behavior OpenAPI can declare correct methods and responses while the implementation returns 200 for all errors or changes state on GET. Maturity needs to be verified by operational testing and evidence.
11.22 Evaluation matrix
A useful review avoids reducing the interface to a grade. For each journey, record evidence, impact, and recommended action. The level can be informed, but must be accompanied by observations about REST, security and operation. The following table provides minimum questions that can be applied to an API or set of endpoints.
The team must also consider weight and context. The absence of can have low impact on an internal API with two stable consumers, while non-idempotent POST without deduplication can pose critical risk. Priority for improvement should be determined by risk and value, not just distance to level 3.
Table 9 - Evidence-based assessment matrix.
Dimension
Evidence question
Clue
Endpoint
Do intents converge on a single generic URI?
Level 0
Resources
Do entities and processes have a stable identity?
Level 1
Methods
Do GET, POST, PUT, PATCH and DELETE respect semantics?
Level 2
Responses
Statuses and headers allow generic interpretation?
Level 2
Hypermedia
Do representations expose current relationships and transitions?
Level 3
Stateless
Does the request depend on a previous local session?
REST Constraint
Cache
Do reusable responses have explicit policy?
REST Constraint
Layers
Does the client depend on the internal topology?
REST Constraint
Operation
Do logs distinguish gateway, API and domain?
Operational quality
Assessment Conclusion Example
Journey: consultation and cancellation of appointment. Evidence: resources identified by /appointments/{id}; reading uses GET; cancellation uses POST /cancel; errors use 200 with envelope. Classification: level 1 with partial level 2 elements. Risk: inconsistent observability and retry handling. Next action: adopt DELETE or cancellation according to domain semantics, HTTP status and , maintaining old route during migration.
11.23 Migration strategy
Migration must start with a journey of value and not with a total rewrite of the catalog. Select operations with high support costs, risk of duplication or difficulty in evolution. Inventory gateway consumers, volumes, payload dependencies, internal codes, and policies. Define success metrics before publishing the new interface.
The new surface can coexist with the old one. An adapter translates level 0 messages to level 2 resources and methods; Old responses are preserved for legacy clients. Contracts have dates, deprecation policies and usage telemetry. Irreversible changes only occur after evidence of migration.
should be added when there is a use case. Starting with self, next, prev and process relations links allows you to test tooling and consumers. Dynamic actions can be introduced into flows with relevant states. The team avoids creating a broad framework before demonstrating benefit.
Figure 7 - Evolution between levels can be incremental, compatible and risk-driven.
11.24 Observability and troubleshooting
Interface maturity changes the quality of operational signals. At level 0, metrics per POST /service aggregate all intents; It is necessary to extract operation from the body or add a business attribute. At level 1, routes distinguish resources, but actions can remain hidden. At level 2, method, route template and status offer standardized dimensions. At level 3, followed relationships can reveal transitions and journeys.
Logs must record method, route template, status, latency, response source, correlation ID, consumer and identifier when allowed. Avoid using the concrete URI as a metric label, as high cardinality IDs degrade observability systems. Use /transfers/{id} as a dimension and preserve the identifier only in protected logs or traces.
Troubleshooting needs to separate contract and transport. A timeout occurs before any classification; a 405 indicates that an HTTP component responded; a 409 could represent domain conflict; a 200 with internal error suggests level 0 contract or poor fit. For gateways, confirm whether the response was produced by the proxy, the policy, or the backend.
Table 10 - Useful symptoms when investigating interfaces at different levels.
Symptom
Hypothesis
Evidence to collect
Everything appears as a route
Level 0 Generic Endpoint
operation field, extraction policy and trace
GET changes state
Level 2 semantics violated
domain logs and repeated tests
Retry duplicates operation
POST without deduplication
idempotency key and transactional records
Link exists but fails
Outdated or unauthorized control
representation, status and authorization decision
405 on gateway
Blocked or unpublished method
Allow, route and upstream configuration
200 with problem
Legacy envelope or transformation
body, policy chain and backend status
11.25 Case studies and labs
The following exercises use a fictitious transfer domain. Run only in lab or mock environments. The objective is to observe differences in contracts and behavior; it's not reproducing real data or integrations.
Case study 1 - dispatcher modernization
An API receives POST /transactions with action=CONSULT, action=CREATE and action=CANCEL. All results use 200. Propose resources, methods, and answers. Consider how to preserve old consumers, how to correlate the new transfer, and how to handle timeout after creation. Compare before and after metrics.
Case study 2 - asynchronous process
A transfer may remain under review. Model the request as a , return 202 when processing has not yet finished, and provide a monitor. Then add self, cancel and receipt relationships depending on the state. Verify that the server rejects unauthorized actions even when the link is fabricated.
Laboratory 1 - classification by evidence
List all endpoints for a test API and group by journey.
Identify operations focused on body or verbs in the path.
Rate each journey, not just the entire API.
Record evidence of resources, methods, status, headers and .
Produce recommendations prioritized by risk and value.
Lab 2 - Test
Run GET repeatedly and confirm that there is no requested effect on the domain.
Repeat PUT and DELETE and observe the desired effect.
Simulate concurrent update with ETag and If-Match.
Cause validation, conflict, absence and unavailability; compare status and .
Inspect gateway and backend to find out which component produced each response.
Lab 3 - client
Start at an entry point and look for relationships, without concatenating paths.
Only perform actions present in the .
Change the target of a relationship on the server without modifying the client.
Remove a state change transition and observe the behavior.
Capture metrics of followed relationships and transition failures.
Chapter summary
The describes evolution at four levels. Level 0 focuses operations on messages sent to a generic . Level 1 introduces resources and identifiers. Level 2 uses through methods, status, headers, cache and preconditions. Level 3 adds controls that guide transitions in the current state.
The model is useful for diagnosis and planning, but does not measure all attributes of a platform. Security, reliability, governance, performance, documentation and compatibility require their own analysis. It also does not replace the REST constraints described by Fielding. An interface can reach level 3 without obtaining all of the style's architectural properties.
Evolution must be driven by risk and value. Stable resources improve identity; improve interoperability and operation; can reduce coupling to URLs and flow rules. Each step has costs and depends on the consumer ecosystem. The goal is not to achieve a score, but to build predictable, evolving and observable interfaces.
Assessment checklist
Are operations concentrated on an and differentiated by body?
Do domain concepts have stable resources and identifiers?
Do URIs represent resources rather than function names?
Do methods respect security and ?
Do status codes correctly identify success, client error, and server failure?
Do creations, asynchronous processes, and preconditions use appropriate headers?
Do errors have a structured format and do not expose sensitive data?
Do retries consider and deduplication?
Do representations expose links and actions with defined relationships?
Do clients really interpret relationships or continue to encode URLs?
Does evaluation separate , REST constraints, and quality attributes?
Do gateway, backend and domain preserve the same semantics?
Do metrics use route templates and distinguish origin from response?
Does the migration have consumer inventory, telemetry and a deprecation plan?
Review exercises
Explain why using JSON and POST does not determine the level of an API.
Classify an interface with multiple paths, all handled by POST, and justify.
Model retrieval, creation and cancellation of transfers at levels 0, 1 and 2.
Describe a situation where an API level 2 is adequate and level 3 is not suitable.
Explain how ETag and If-Match contribute to a level 2 interface.
Propose relationships for a four-state approval process.
Differentiate between absence of link and lack of authorization on the server.
Compare to stateless and REST cache constraints.
Explain why OpenAPI does not certify idempotent behavior.
Create a migration plan for a single used by five consumers.
Describe a troubleshooting script for 200 containing internal error.
Build an evidence matrix to evaluate an API at the gateway and backend.
Glossary
Essential chapter glossary.
Term
Definition
Affordance
Indication of a possible action and how to execute it in the context of a representation.
Endpoint
Point of interaction exposed by an API, normally associated with URI and method.
HATEOAS
Use of hypermedia to guide application state and upcoming transitions.
Hypermedia
Media that contains controls, relationships or links capable of guiding navigation and actions.
Idempotency
Property by which equivalent repetitions produce the same intended effect.
Link relationship
Relationship that defines the meaning of a link between the context and the target.
POX
Plain Old XML; in RMM, it represents proprietary messages carried by a generic endpoint, even when the modern format is JSON.
Problem Details
Standardized format for representing Problem Detailss in HTTP APIs.
Resource
Identifiable abstraction that can have server-controlled representations and state.
Representation
Transferred data that describes the current or intended state of a resource.
Richardson Maturity Model
Four-level model to observe capability adoption, HTTP semantics, and hypermedia.
RMM
Acronym for Richardson Maturity Model.
HTTP Semantics
Shared meaning of methods, codes, headers, and other protocol elements.
URI Template
Syntax for expressing parameterized URIs that can be expanded by clients.
WebLinking
Standardized model for expressing links and relationships in web messages.
Technical references
The references below should be read together. Fowler's article presents the model; Fielding's dissertation provides the architectural basis of REST; the RFCs define the interoperable semantics used in the examples.
[1] FOWLER, Martin. : steps toward the glory of REST. 2010. Available at: martinfowler.com/articles/richardsonMaturityModel.html.
[2] FIELDING, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. University of California, Irvine, 2000. Chapter 5: Representational State Transfer.
[3] IETF. RFC 9110 - . 2022.
[4] IETF. RFC 9111 - HTTP Caching. 2022.
[5] IETF. RFC 8288 - Web Linking. 2017.
[6] IETF. RFC 6570 - . 2012.
[7] IETF. RFC 9457 - for HTTP APIs. 2023.
[8] IANA. Link Relations Registry. Register of standardized relationships for links.
[9] OpenAPI Initiative. OpenAPI Specification. Specification for describing HTTP APIs.
[12] IETF. RFC 7232 - Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests. 2014. Obsolete as an aggregate document, but historically relevant; the current semantics are consolidated in RFC 9110.
End of the chapter The next step of the course is to delve deeper into the description and governance of API contracts, connecting HTTP modeling, OpenAPI, validation, compatibility and pipeline automation.