A contract covers success and failure

  1. 01RequestIntent and data
  2. 02BoundaryPermissions and limits
  3. 03ResponseResult or error
  4. 04RetryCompatibility and effect
A protocol provides mechanisms. The contract defines system behaviour.

Across many integration reviews, I have seen the same cluster of choices: POST for reads and deletes, 200 OK for every outcome, field definitions in a separate spreadsheet, and no compatibility policy.

This is a composite example, but a recognisable one:

POST /api/client/get
POST /api/client/delete
POST /api/client/getStatus

Using POST is not forbidden. The problem is a contract that fails to explain intent, retry behaviour, errors, and the data lifecycle. Those were the parts I emphasised when teaching systems analysis.

API does not mean REST

ApproachInteraction modelContractUseful whenMain cost
HTTP resource APIResources and HTTP semanticsOpenAPI is a common choicePublic and internal web-facing integrationsConsistent conventions and evolution rules
SOAPXML messages and operationsWSDL and XSDEstablished enterprise and WS-* ecosystemsSpecification and tooling complexity
GraphQLQueries over a typed graphGraphQL schemaClients need different views of the same dataResolver cost, query controls, governance
JSON-RPCMethod calls with parametersConvention or external schemaCompact RPC interfaces and internal utilitiesLittle built-in discovery or evolution
gRPCTyped remote procedures.protoInternal services, streaming, generated clientsBinary tooling and code-generation workflow

REST is an architectural style, not a data encoding. Many production interfaces are more accurately described as JSON-over-HTTP APIs: they use HTTP methods, URIs, and status codes without implementing every REST constraint. That is fine when the contract is explicit.

HTTP semantics without shortcuts

HTTP is stateless in the sense that each request can be understood in isolation. A server can still store resources, sessions, and application state; it must not depend on hidden context associated with a particular connection.

Methods communicate intent:

  • GET retrieves a representation and has safe, idempotent semantics;
  • POST submits data to a resource for processing — creation is common but not its only use;
  • PUT creates or replaces the state of the target resource and is idempotent by intended effect;
  • PATCH applies a partial change and is not inherently idempotent;
  • DELETE removes the association with a resource and is idempotent by intended effect.

Do not force every procedure into a fake resource model. POST /risk-assessments can reasonably create an assessment result. A genuinely procedural interface may be clearer as JSON-RPC or gRPC.

Status codes are part of the contract as well:

  • 200 OK: the request succeeded;
  • 201 Created: a resource was created, usually with a Location;
  • 204 No Content: success with no response body;
  • 400 Bad Request: the request cannot be processed as submitted;
  • 401 Unauthorized: valid authentication credentials are missing;
  • 403 Forbidden: the server understood the request but refuses access;
  • 404 Not Found: the target resource was not found or is not disclosed;
  • 409 Conflict: the request conflicts with current state;
  • 500 Internal Server Error: the server encountered an unexpected condition.

Returning 200 for a processing failure that the contract defines as an HTTP error removes a standard signal from gateways, monitoring, and clients. A negative business outcome is different: a completed assessment can return 200 with a “not approved” decision in its body. The contract must distinguish successful execution from the business decision it produces. GraphQL has separate partial-response semantics and may return both data and errors; that convention should not be copied blindly into every JSON API.

SOAP is a messaging framework, not an automatic transaction

SOAP defines an XML envelope and message-processing model. WSDL and XSD provide mature operation and type contracts, which remains valuable where that ecosystem is already the integration standard.

WS-Security, WS-ReliableMessaging, and transaction-related extensions are separate specifications and profiles. SOAP alone does not switch on encryption, guaranteed delivery, or a distributed transaction. Those properties depend on the selected extensions, binding, implementation, and end-to-end design.

Choose SOAP for interoperability with an existing landscape or a specific WS-* requirement, not because “SOAP is reliable” in the abstract.

GraphQL trades client flexibility for governance

A GraphQL service publishes a typed schema, while each client selects the fields it needs. This works well when web, mobile, and internal applications require different views of the same entities.

The server takes on new responsibilities:

  • resolvers can create N+1 query patterns;
  • query depth and cost need limits;
  • authorisation belongs at the business-object and field boundary;
  • schema changes need a deprecation policy;
  • performance cannot be judged by HTTP request count alone.

GraphQL commonly uses HTTP and JSON, but the language specification does not mandate one transport. Query operations can use GET, which enables HTTP caching, and persisted documents are another option. “GraphQL cannot be cached” is therefore too broad.

gRPC provides contracts and streaming, not magic latency

gRPC defines services and messages in .proto files, generates client and server code, and supports unary, client-streaming, server-streaming, and bidirectional-streaming calls. The common stack uses HTTP/2 and Protobuf by default, while the framework can support other content types.

It suits typed internal interfaces, provided the design covers deadlines, cancellation, retries, and schema evolution. The binary payload is less convenient to inspect directly, but tools such as grpcurl and server reflection make diagnosis practical.

No protocol guarantees a fixed latency improvement. Benchmark the real payload, libraries, network path, and call pattern. A browser-facing API also needs a decision about gRPC-Web or a gateway and must account for the capabilities of intermediaries.

How I choose an approach

Instead of ranking protocols, I answer these questions:

  1. Who consumes the API, and what can they support?
  2. Is the interaction naturally a resource operation, procedure call, or graph query?
  3. Is streaming or bidirectional exchange required?
  4. How will the contract evolve, and how many versions must coexist?
  5. Which proxies, gateways, and diagnostic tools sit on the path?
  6. What do measurements say about latency, payload size, and throughput?
  7. Who owns the interface after release?

Reliability is not selected by protocol name. Timeouts, retries, idempotency, backpressure, and data consistency require their own design.

Seven checks for an API specification

1. Operations and semantics

Is each operation clearly a read, command, or resource creation? Can a client retry safely after a timeout?

2. Errors

Does the response include stable machine codes, a useful message, a correlation ID, and a clear distinction between client and server failures?

3. Compatibility

A version in the URL is only one option. Media types, headers, or compatible evolution of one contract can also work. The important part is a policy for breaking changes and deprecation.

4. Pagination and limits

Large collections need bounds. Offset pagination is simple; a cursor over a stable ordering key can avoid some skips and duplicates as data changes. A cursor alone does not guarantee a consistent snapshot. Define maximum page size, deterministic tie-breaking and behaviour when data changes between requests.

5. Failure and retry behaviour

Specify timeouts, retry rules, idempotency keys for non-idempotent operations, and partial-success behaviour.

6. Data security

Document authentication, authorisation, sensitive fields, and rules that keep secrets out of URLs and logs.

7. Observability

Agree on request or correlation IDs, error and latency metrics, and ownership of alerts before production.

A practical Telegram bot exercise

In my course, students built a small Telegram bot with Flask. A webhook delivers a JSON POST; the application validates the update and sends a response through the Telegram Bot API.

That compact exercise covers methods, JSON, token handling, timeouts, errors, and repeat delivery of an update. API theory becomes concrete because every assumption is exercised by a real request.

A systems analyst does not need to memorise a technology catalogue. The essential skill is reading a specification and finding ambiguity before implementation. Date formats, nullable fields, page limits, and timeout retries look minor only until the first incompatible client ships.

For authoritative semantics, use RFC 9110, SOAP 1.2, GraphQL over HTTP, and the gRPC core concepts.


Original article: API From A to Z on Habr

Yours, DPUPP

Related Articles