Every API makes an implicit promise through its response format. A JSON response says "I'm modern, easy to integrate, and you already have a parser." An XML response says "I'm enterprise-grade, schema-validated, and probably part of a system that predates your career." A Protobuf response says "I'm optimized for speed and you'll need our SDK."

The response format shapes everything: client complexity, debugging ease, bandwidth costs, documentation requirements, and the developer experience of everyone who integrates with your API. This guide covers the major API response formats, when each is appropriate, and the practical details that matter for implementation.

REST + JSON: The Default

JSON over HTTP is the de facto standard for web APIs. GitHub, Stripe, Twilio, AWS (most services), and virtually every SaaS product expose JSON REST APIs. The format is universally parseable — JSON.parse() in JavaScript, json.loads() in Python, json.Unmarshal() in Go — without special libraries or SDKs.

A typical JSON API response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "id": "usr_12345",
    "name": "Alice Johnson",
    "email": "alice@example.com",
    "created_at": "2026-03-19T14:30:00Z"
  },
  "meta": {
    "request_id": "req_abc123"
  }
}

Common JSON API Conventions

No specification mandates JSON API structure, but conventions have emerged:

  • Envelope pattern: Wrap data in {"data": ..., "meta": ..., "errors": ...}. Stripe, many others.
  • Flat pattern: Return the resource directly: {"id": "...", "name": "..."}. GitHub, simpler APIs.
  • JSON:API spec: Formal specification for JSON response structure including relationships, pagination, and sparse fieldsets. Used by Ember.js ecosystem.
  • Pagination: Cursor-based ("next_cursor": "abc"), offset-based ("page": 2, "per_page": 20), or Link header-based (GitHub).
  • Dates: ISO 8601 strings ("2026-03-19T14:30:00Z") are the overwhelming convention. Unix timestamps are a minority.
  • Null vs absent: Some APIs omit null fields entirely; others include them explicitly. Neither is wrong, but be consistent.

Error Response Formats

Error responses vary widely across APIs, but common patterns include:

// Stripe-style (structured)
{"error": {"type": "card_error", "code": "card_declined", "message": "Your card was declined."}}

// RFC 7807 Problem Details (IETF standard)
{"type": "https://api.example.com/errors/not-found", "title": "Not Found", "status": 404, "detail": "User usr_999 does not exist."}

// Simple
{"error": "Not found", "status": 404}

RFC 7807 (Problem Details for HTTP APIs) is gaining adoption as a standard error format. It uses Content-Type: application/problem+json and defines fields for type, title, status, detail, and instance. Stripe, FastAPI, and Spring Boot support it.

SOAP + XML: Enterprise Standard

SOAP (Simple Object Access Protocol) is an XML-based protocol for structured API communication. It's verbose, complex, and still the backbone of enterprise systems, banking APIs, healthcare interfaces, and government services.

HTTP/1.1 200 OK
Content-Type: application/soap+xml

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <GetUserResponse xmlns="http://example.com/api">
      <User>
        <Id>12345</Id>
        <Name>Alice Johnson</Name>
        <Email>alice@example.com</Email>
      </User>
    </GetUserResponse>
  </soap:Body>
</soap:Envelope>

SOAP's advantages over REST+JSON:

  • WSDL contracts: A WSDL (Web Services Description Language) file formally defines every operation, parameter, and type. Clients can auto-generate code from the WSDL. JSON APIs rely on documentation that may be incomplete.
  • Built-in error handling: SOAP faults have a standard structure with fault codes, fault strings, and detail elements.
  • WS-Security: Standard for message-level encryption and signing. REST has no equivalent standard (relies on transport-level TLS).
  • Schema validation: XSD schemas validate every message before processing.

SOAP's disadvantages: 3-5x larger payloads than JSON, complex tooling, steep learning curve, poor browser support. For new APIs, SOAP is almost never the right choice. For integrating with existing enterprise systems, it's often the only choice.

When converting between SOAP and REST formats, XML to JSON conversion handles the data but loses the envelope structure, namespace information, and schema validation.

GraphQL: Client-Controlled Responses

GraphQL (developed by Facebook, 2015) is a query language that lets clients specify exactly which fields they want. Instead of the server deciding the response shape (REST), the client sends a query:

// Request
POST /graphql
{"query": "{ user(id: \"12345\") { name email orders { total status } } }"}

// Response (JSON)
{"data": {"user": {"name": "Alice Johnson", "email": "alice@example.com", "orders": [{"total": 99.50, "status": "shipped"}, {"total": 42.00, "status": "delivered"}]}}}

GraphQL responses are always JSON. The format itself is JSON — GraphQL defines the query language and the server behavior, not a new serialization format.

When GraphQL Wins

  • No over-fetching: Clients request only the fields they need. A mobile client can request {user{name}} while a dashboard requests {user{name email orders{total}}}.
  • No under-fetching: A single GraphQL query can fetch data that would require 3-5 REST API calls (user + orders + order items), eliminating client-side join logic.
  • Strong typing: The GraphQL schema defines types, relationships, and field nullability. Introspection lets clients discover the schema programmatically.
  • Versioning: Instead of API versions (v1, v2), GraphQL adds new fields and deprecates old ones. Clients that don't request deprecated fields aren't affected.

GraphQL's Real Costs

  • Caching is hard. REST endpoints have natural cache keys (URL + params). GraphQL sends different queries to the same endpoint, making HTTP caching nearly impossible. You need application-level caching (Apollo, Relay).
  • N+1 query problem. A naive GraphQL resolver for users{orders{items}} can trigger thousands of database queries. Dataloader or equivalent batching is required.
  • Complexity budget. A malicious client can craft deeply nested queries that consume excessive server resources. Query complexity analysis and depth limiting are necessary.
  • Learning curve. Developers must learn the query language, schema definition language, resolver patterns, and at least one GraphQL client library.

gRPC + Protocol Buffers: High-Performance APIs

gRPC (Google Remote Procedure Call) uses Protocol Buffers for serialization and HTTP/2 for transport. It's the standard for inter-service communication in microservice architectures at Google, Netflix, Square, Lyft, and most large-scale systems.

// Service definition (user.proto)
service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (stream User);
}

message GetUserRequest {
  string id = 1;
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
}

gRPC advantages:

  • Performance: Protobuf serialization is 5-10x faster than JSON. HTTP/2 multiplexing eliminates head-of-line blocking.
  • Streaming: Server-side, client-side, and bidirectional streaming are built in. REST has no standard streaming model.
  • Code generation: protoc generates type-safe client and server code in 10+ languages from a single .proto file.
  • Deadlines: gRPC has built-in deadline propagation — if a downstream call exceeds its deadline, the entire chain cancels.

gRPC is not suited for browser-to-server communication (gRPC-Web is a partial workaround) or public APIs consumed by diverse clients. It excels between services you control.

Content Negotiation: Serving Multiple Formats

Some APIs support multiple response formats. The HTTP Accept header lets clients specify their preference:

# Request JSON
Accept: application/json

# Request XML
Accept: application/xml

# Request with priority
Accept: application/json, application/xml;q=0.9, */*;q=0.1

The server reads the Accept header and returns the requested format (or 406 Not Acceptable if it can't). Most modern APIs only support JSON and return Content-Type: application/json regardless of the Accept header. APIs that support XML typically also support JSON, providing a migration path from SOAP-era integrations.

Implementing content negotiation: add the Accept header check to your API middleware. Serialize the same internal data structure to JSON (default), XML, or other formats based on the request. Libraries like fast-xml-parser make JSON to XML conversion trivial for response formatting.

Pagination Patterns by Format

PatternFormatExampleBest For
Cursor-basedJSON (REST)"next_cursor": "eyJpZCI6MTIzfQ"Real-time data, large datasets, stable pagination
Offset-basedJSON (REST)"page": 2, "per_page": 20, "total": 1000Simple datasets, UI with page numbers
Link headerJSON (REST)Link: </users?page=3>; rel="next"Hypermedia APIs (GitHub)
ConnectionGraphQLedges { node { ... } cursor } pageInfo { hasNextPage }Relay-style GraphQL (cursor + edges + pageInfo)
SOAP pagingXML (SOAP)Custom elements per serviceEnterprise APIs (no standard pagination)

Cursor-based pagination is the recommended default for new APIs. It's stable under insertions/deletions (offset-based pagination breaks when items are added or removed between pages) and works well with streaming.

Choosing Your API Format

Use CaseFormatWhy
Public web APIREST + JSONUniversal support, easy to integrate, self-documenting with OpenAPI
Mobile app APIGraphQL or REST + JSONGraphQL reduces over/under-fetching on bandwidth-constrained networks
Microservice-to-microservicegRPC + ProtobufPerformance, streaming, code generation, deadline propagation
Enterprise integrationSOAP + XMLSchema validation, WSDL contracts, WS-Security (if required by partner)
Real-time data feedsWebSocket + JSON or ProtobufBidirectional, low-latency. JSON for simplicity, Protobuf for bandwidth.
File-based data exchangeJSONL or CSVBulk exports, data pipeline ingestion. JSONL for structure, CSV for spreadsheets.

The API format decision is usually straightforward: use JSON for public APIs, gRPC for internal microservices, and whatever the enterprise partner requires for B2B integrations. GraphQL is worth evaluating when your mobile or frontend clients have complex data requirements and you want to eliminate multiple round trips.

Don't over-optimize format choice. A well-designed JSON API with good documentation, consistent error handling, and sensible pagination will outperform a poorly designed gRPC API in every way that matters to consumers. The format is the packaging — the API design is the product.