Web Services & APIs — Reference
Look-up facts for web API work: specification and RFC versions, tooling versions, protocol comparison, HTTP methods, status codes and headers, gRPC and WebSocket codes, OpenAPI feature matrix, security checklists, and tool matrices. For why things work the way they do, see Explanation. For step-by-step tasks, see How-to Guides.
Snapshot date
Versions and statuses on this page were checked on 2026-09-25 against the spec repositories, IETF/RFC Editor listings, and the npm/PyPI registries. Drafts (IETF Internet-Drafts, GraphQL Foundation stage 0-2 specs) can change without notice.
Specification and Standard Versions
| Specification |
Latest |
Released |
Status / Notes |
| OpenAPI (OAS) |
3.2.1 |
2026-09-10 |
Patch of 3.2.0 (2025-09-19). Other maintained lines: 3.1.2 (2025-09-19), 3.0.4 (2024-10-24). Apache-2.0, OpenAPI Initiative (Linux Foundation) |
| Arazzo (API workflows) |
1.1.0 |
2026-05-17 |
OAI spec for multi-step API call sequences. 1.0.0 was 2024-05-29 |
| Overlay |
1.1.0 |
2026-01-14 |
OAI spec for repeatable patches to OpenAPI documents. 1.0.0 was 2024-10-17 |
| AsyncAPI |
3.1.0 |
2026-01-31 |
Minor, non-breaking. Adds the ROS 2 protocol binding. 3.0.0 was Dec 2023 |
| JSON Schema |
2020-12 |
2020-12 |
Still the current published version (json-schema.org, checked 2026-09). OAS 3.1+ uses it as the default dialect |
| GraphQL |
September 2025 edition |
2025-09 |
First edition since October 2021. Adds OneOf input objects, schema coordinates, descriptions on executable documents, full Unicode grammar |
| GraphQL over HTTP |
Draft |
— |
GraphQL Foundation, Stage 2: Draft. Defines application/graphql-response+json |
| GraphQL Composite Schemas (open Federation spec) |
Preliminary |
— |
GraphQL Foundation working group, Stage 0: Preliminary (checked 2026-09). Apollo Federation 2 remains the de facto standard |
| Protocol Buffers |
Edition 2024 |
— |
Latest released edition. Editions replace syntax = "proto2"/"proto3". Latest protoc line is v36.x (Python protobuf 7.36.2, 2026-09-17) |
| WSDL / SOAP |
WSDL 2.0, SOAP 1.2 |
2007 |
W3C Recommendations. Most deployed services still use WSDL 1.1 + SOAP 1.1/1.2 |
HTTP and Transport RFCs
| Standard |
Number |
Published |
Notes |
| HTTP Semantics |
RFC 9110 |
2022-06 |
Methods, status codes, headers. Obsoletes RFC 7231 and friends |
| HTTP Caching |
RFC 9111 |
2022-06 |
Cache-Control, freshness, validation |
| HTTP/1.1 |
RFC 9112 |
2022-06 |
Message syntax |
| HTTP/2 |
RFC 9113 |
2022-06 |
Obsoletes RFC 7540 (2015). Deprecates the RFC 7540 priority scheme |
| HTTP/3 |
RFC 9114 |
2022-06 |
HTTP over QUIC. Header compression by QPACK (RFC 9204) |
| QUIC |
RFC 9000 |
2021-05 |
With RFC 9001 (TLS) and RFC 9002 (loss recovery) |
| HTTP QUERY method |
RFC 10008 |
2026-06 |
Safe, idempotent request with a body. First new standard method since PATCH (RFC 5789, 2010) |
| PATCH method |
RFC 5789 |
2010-03 |
|
| JSON Patch |
RFC 6902 |
2013-04 |
application/json-patch+json |
| JSON Merge Patch |
RFC 7396 |
2014-10 |
application/merge-patch+json |
| Problem Details |
RFC 9457 |
2023-07 |
application/problem+json. Obsoletes RFC 7807 |
| Deprecation header |
RFC 9745 |
2025-03 |
Structured Field Date value, for example Deprecation: @1767225600 |
| Sunset header |
RFC 8594 |
2019-05 |
HTTP-date value |
| RateLimit / RateLimit-Policy headers |
draft-ietf-httpapi-ratelimit-headers-11 |
2026-05-23 |
Internet-Draft, not an RFC. Syntax can still change |
| Idempotency-Key header |
draft-ietf-httpapi-idempotency-key-header-07 |
2025-10-15 |
Internet-Draft, not an RFC |
| WebSocket |
RFC 6455 |
2011-12 |
ws:// / wss:// |
| WebSocket over HTTP/2 |
RFC 8441 |
2018-09 |
Extended CONNECT |
| WebSocket over HTTP/3 |
RFC 9220 |
2022-06 |
|
| Server-Sent Events |
WHATWG HTML Living Standard |
living |
EventSource interface. Not an IETF RFC |
| WebTransport |
W3C API + draft-ietf-webtrans-http3 |
draft |
IETF protocol still an Internet-Draft (2026-09). Browser API in Chrome 97+, Firefox 114+, Safari 26.4+ (MDN browser-compat-data) |
| Trace Context |
W3C Recommendation |
— |
traceparent / tracestate headers used by OpenTelemetry |
Security and Identity Standards
| Standard |
Number |
Published |
Notes |
| OAuth 2.0 |
RFC 6749 |
2012-10 |
Bearer usage in RFC 6750 |
| OAuth 2.1 |
draft-ietf-oauth-v2-1-16 |
2026-09-03 |
Still an Internet-Draft (IETF datatracker, 2026-09). Will obsolete RFC 6749 and RFC 6750 |
| OAuth 2.0 Security BCP |
RFC 9700 |
2025-01 |
Current best practice: PKCE, no implicit grant, no ROPC, sender-constrained tokens |
| PKCE |
RFC 7636 |
2015-09 |
|
| DPoP (sender-constrained tokens) |
RFC 9449 |
2023-09 |
|
| Device Authorization Grant |
RFC 8628 |
2019-08 |
Supported in OAS 3.2 deviceAuthorization flow |
| Authorization Server Metadata |
RFC 8414 |
2018-06 |
Referenced by OAS 3.2 oauth2MetadataUrl |
| Protected Resource Metadata |
RFC 9728 |
2025-04 |
|
| JWT |
RFC 7519 |
2015-05 |
|
| JWT Best Current Practices |
RFC 8725 |
2020-02 |
Algorithm allowlisting, alg: none rejection |
| OWASP API Security Top 10 |
2023 edition |
2023 |
Still the latest edition (editions: 2019, 2023) |
| CloudEvents |
1.0.x |
— |
CNCF graduated 2024-01-25 |
| Standard Webhooks |
community spec |
— |
webhook-id, webhook-timestamp, webhook-signature: v1,<base64> |
Web PKI changes that affect APIs
- Let's Encrypt turned off its OCSP responders on 2025-08-06. OCSP stapling does nothing for Let's Encrypt certificates now. Revocation is by CRL.
- CA/Browser Forum Baseline Requirements cut the maximum TLS certificate lifetime to 200 days from 2026-03-15, 100 days from 2027-03-15, and 47 days from 2029-03-15. Automate renewal (ACME, cert-manager) and avoid leaf-certificate pinning.
Registry snapshot, 2026-09-25 (npm / PyPI latest tags, GitHub release listings).
| Tool |
Latest |
Date |
Notes |
| gRPC core (C++/Python/Ruby/C#) |
1.84.0 |
2026-09-11 |
grpcio 1.84.0 on PyPI 2026-09-14 |
| grpc-js (Node.js) |
1.14.5 |
2026-09-17 |
@grpc/grpc-js |
Connect for ES (@connectrpc/connect) |
2.2.0 |
2026-09-07 |
Connect RPC is a CNCF sandbox project (accepted 2024-04-13) |
| buf CLI |
1.73.0 |
2026-09-11 |
@bufbuild/buf on npm |
| graphql-js |
17.0.2 |
2026-07-03 |
v17.0.0 GA 2026-06-15 |
| Apollo Server |
5.5.1 |
2026-05-05 |
Apollo Server 4 end-of-life since 2026-01-26 |
| Apollo Router (GraphOS Router) |
2.17.0 |
2026-07-24 |
Elastic License 2.0 (source-available) |
| Apollo Federation composition |
2.14.4 |
2026-08-18 |
@apollo/gateway / composition-js |
| GraphQL Yoga |
5.24.1 |
2026-09-17 |
|
| GraphQL Code Generator CLI |
7.4.3 |
2026-09-24 |
@graphql-codegen/cli |
| tRPC |
11.19.0 |
2026-09-16 |
v11.0.0 GA 2025-03-21 |
| Spectral CLI |
6.16.3 |
2026-08-03 |
@stoplight/spectral-cli |
| Prism CLI |
5.16.0 |
2026-07-17 |
@stoplight/prism-cli |
| openapi-generator-cli (npm wrapper) |
2.41.0 |
2026-08-24 |
Wrapper version, not the generator JAR version |
| Redocly CLI |
2.54.3 |
2026-09-25 |
@redocly/cli |
| Swagger UI |
5.33.0 |
2026-09-16 |
swagger-ui-dist |
| Scalar Express reference |
0.10.23 |
2026-09-25 |
@scalar/express-api-reference |
| AsyncAPI CLI |
6.2.0 |
2026-09-22 |
@asyncapi/cli |
| Pact JS |
17.1.4 |
2026-09-07 |
CLI tools in @pact-foundation/pact-cli 18.1.2 |
| Grafana k6 |
2.3.0 |
2026-09 |
k6 v1.0 shipped in 2025, v2 removed deprecated APIs |
| Kong Gateway (OSS repo) |
3.9.3 |
— |
Latest entry in the public Kong/kong CHANGELOG (checked 2026-09) |
Protocol Comparison
| Protocol |
Transport |
Format |
Direction |
Browser native |
Best for |
| REST |
HTTP/1.1, HTTP/2, HTTP/3 |
JSON (typically) |
Request/response |
Yes |
Public APIs, CRUD, resource modeling |
| GraphQL |
HTTP (queries, mutations); WebSocket or SSE (subscriptions) |
JSON |
Request/response + subscription |
Yes |
Complex frontends, data aggregation |
| gRPC |
HTTP/2 (HTTP/3 only in grpc-dotnet, gRFC G2) |
Protocol Buffers (binary) |
Unary + 3 streaming modes |
No (needs gRPC-Web or Connect) |
Internal microservices, high throughput |
| Connect RPC |
HTTP/1.1, HTTP/2 |
Protobuf or JSON |
Unary + streaming |
Yes (Connect protocol) |
gRPC-compatible APIs that browsers can call |
| SOAP |
HTTP, SMTP, TCP |
XML |
Request/response |
Yes |
Legacy enterprise, financial services |
| WebSocket |
TCP via HTTP/1.1 Upgrade (RFC 6455), HTTP/2 (RFC 8441), HTTP/3 (RFC 9220) |
Text or binary frames |
Full-duplex |
Yes |
Chat, gaming, collaboration |
| SSE |
HTTP/1.1, HTTP/2, HTTP/3 |
UTF-8 text |
Server to client |
Yes (EventSource) |
Feeds, notifications, LLM token streaming |
| WebTransport |
HTTP/3 (QUIC) |
Streams + datagrams |
Bidirectional, multiplexed |
Chrome 97+, Firefox 114+, Safari 26.4+ |
Low-latency media, games, unreliable datagrams |
| Webhooks |
HTTP POST |
JSON (typically) |
Server to server push |
N/A |
Event-driven integrations |
| tRPC |
HTTP; SSE or WebSocket for subscriptions |
JSON |
Request/response + subscription |
Yes (TypeScript client) |
TypeScript full-stack monorepos |
HTTP Methods and Idempotency
| Method |
Semantics |
Safe |
Idempotent |
Request body |
Defined in |
| GET |
Retrieve a representation |
Yes |
Yes |
No defined semantics |
RFC 9110 |
| HEAD |
GET without the response body |
Yes |
Yes |
No defined semantics |
RFC 9110 |
| QUERY |
Process the enclosed query and return the result |
Yes |
Yes |
Yes |
RFC 10008 (2026) |
| POST |
Process the enclosed content (create, submit, trigger) |
No |
No |
Yes |
RFC 9110 |
| PUT |
Create or replace the target resource |
No |
Yes |
Yes |
RFC 9110 |
| PATCH |
Apply a partial modification |
No |
No (can be designed to be) |
Yes |
RFC 5789 |
| DELETE |
Remove the target resource |
No |
Yes |
No defined semantics |
RFC 9110 |
| OPTIONS |
Describe communication options (CORS preflight) |
Yes |
Yes |
Optional |
RFC 9110 |
| TRACE |
Loop-back diagnostic |
Yes |
Yes |
No |
RFC 9110 — disable on API servers |
| CONNECT |
Establish a tunnel |
No |
No |
— |
RFC 9110 |
Safe means the client does not request a state change (read-only). Idempotent means N identical requests have the same intended effect as one. Clients and proxies may retry idempotent requests automatically.
QUERY in practice
QUERY replaces the "POST /search" workaround for complex read queries while keeping the request cacheable and retry-safe. OpenAPI 3.2 has a query operation field for it. Check that your proxies, CDNs, and frameworks pass unknown methods through before you adopt it.
HTTP Status Codes
Names follow RFC 9110 (2022), which renamed some codes (for example, 413 and 422).
| Code |
Name |
Typical API use |
| 200 |
OK |
Successful GET/PUT/PATCH/QUERY with a body |
| 201 |
Created |
Resource created. Return Location |
| 202 |
Accepted |
Async job accepted. Return a status URL |
| 204 |
No Content |
Successful DELETE or update without a body |
| 206 |
Partial Content |
Range requests (downloads) |
| 301 / 308 |
Moved Permanently / Permanent Redirect |
308 keeps the method and body |
| 302 / 307 |
Found / Temporary Redirect |
307 keeps the method and body |
| 304 |
Not Modified |
Conditional GET matched (If-None-Match) |
| 400 |
Bad Request |
Malformed syntax, invalid framing |
| 401 |
Unauthorized |
Missing or invalid credentials. Send WWW-Authenticate |
| 403 |
Forbidden |
Authenticated but not allowed |
| 404 |
Not Found |
No such resource (also used to hide existence from unauthorized callers) |
| 405 |
Method Not Allowed |
Send Allow |
| 406 |
Not Acceptable |
Content negotiation failed |
| 408 |
Request Timeout |
Server timed out waiting for the request |
| 409 |
Conflict |
State conflict, duplicate, idempotency key in flight |
| 410 |
Gone |
Resource or API version permanently removed (after Sunset) |
| 412 |
Precondition Failed |
If-Match ETag mismatch (optimistic concurrency) |
| 413 |
Content Too Large |
Body exceeds limit (formerly "Payload Too Large") |
| 415 |
Unsupported Media Type |
Wrong Content-Type (gRPC servers also use it for non-application/grpc) |
| 422 |
Unprocessable Content |
Well-formed but semantically invalid (formerly "Unprocessable Entity") |
| 425 |
Too Early |
Server refuses to process replayable TLS 1.3 / QUIC 0-RTT data (RFC 8470) |
| 428 |
Precondition Required |
Server requires If-Match for updates |
| 429 |
Too Many Requests |
Rate limited. Send Retry-After (RFC 6585) |
| 431 |
Request Header Fields Too Large |
Oversized headers or cookies |
| 500 |
Internal Server Error |
Unhandled server error |
| 501 |
Not Implemented |
Method not supported by the server |
| 502 |
Bad Gateway |
Invalid upstream response |
| 503 |
Service Unavailable |
Overload or maintenance. Send Retry-After |
| 504 |
Gateway Timeout |
Upstream timed out |
Common status code mistakes
- Never return
200 OK with an error in the body. Clients then have to parse every body to detect errors.
- Use
401 for unauthenticated and 403 for authenticated but unauthorized.
- Use
422 for a syntactically valid request with semantically wrong values (for example, an invalid field value). Keep 400 for malformed requests.
404 means "resource not found". Do not use it as a catch-all.
- Error bodies should use Problem Details (
application/problem+json, RFC 9457). See How-to Guides.
Retry guidance per status code is in How-to Guides — Which Errors to Retry.
| Header |
Direction |
Purpose |
Standard |
Authorization |
Request |
Credentials (Bearer, DPoP, Basic) |
RFC 9110, RFC 6750, RFC 9449 |
Accept / Content-Type |
Both |
Content negotiation, body media type |
RFC 9110 |
Cache-Control |
Both |
Caching directives |
RFC 9111 |
ETag / If-None-Match / If-Match |
Both |
Validation and optimistic concurrency |
RFC 9110 |
Vary |
Response |
Request headers that change the representation (cache key) |
RFC 9110 |
Location |
Response |
New resource URL (201) or job status URL (202) |
RFC 9110 |
Retry-After |
Response |
Seconds or HTTP-date before retry (429, 503) |
RFC 9110 |
Deprecation |
Response |
When the resource was or will be deprecated: @<unix-seconds> |
RFC 9745 |
Sunset |
Response |
When the resource stops working: HTTP-date |
RFC 8594 |
Link (rel="deprecation", rel="sunset", rel="successor-version") |
Response |
Migration documentation |
RFC 8288, RFC 9745, RFC 8594 |
RateLimit-Policy / RateLimit |
Response |
Quota policy and remaining quota |
IETF draft (not final) |
X-RateLimit-Limit / -Remaining / -Reset |
Response |
De facto rate-limit headers (GitHub, many gateways) |
None (convention) |
Idempotency-Key |
Request |
Make POST/PATCH retries safe |
IETF draft; Stripe convention |
traceparent / tracestate |
Request |
Distributed trace propagation |
W3C Trace Context |
Origin / Access-Control-* |
Both |
CORS |
WHATWG Fetch |
Strict-Transport-Security |
Response |
Force HTTPS |
RFC 6797 |
Cache-Control Directives
| Directive |
Meaning |
Standard |
max-age=N |
Fresh for N seconds in any cache |
RFC 9111 |
s-maxage=N |
Overrides max-age for shared caches (CDN) |
RFC 9111 |
public / private |
Shared caches may / may not store |
RFC 9111 |
no-cache |
Store, but revalidate before every reuse |
RFC 9111 |
no-store |
Never store (use for sensitive responses) |
RFC 9111 |
must-revalidate |
Do not serve stale after expiry |
RFC 9111 |
immutable |
Body never changes during freshness |
RFC 8246 |
stale-while-revalidate=N |
Serve stale up to N seconds while refreshing in the background |
RFC 5861 |
stale-if-error=N |
Serve stale up to N seconds when the origin errors |
RFC 5861 |
gRPC Status Codes
gRPC returns a status code in the grpc-status trailer. The HTTP mapping below is the one Google APIs and gRPC-JSON transcoding use (google/rpc/code.proto).
| Code |
Number |
Meaning |
HTTP mapping |
Retry? |
| OK |
0 |
Success |
200 |
— |
| CANCELLED |
1 |
Cancelled, usually by the caller |
499 |
No |
| UNKNOWN |
2 |
Unknown error |
500 |
Maybe |
| INVALID_ARGUMENT |
3 |
Bad argument regardless of system state |
400 |
No |
| DEADLINE_EXCEEDED |
4 |
Deadline expired (operation may have completed) |
504 |
Only if idempotent |
| NOT_FOUND |
5 |
Entity not found |
404 |
No |
| ALREADY_EXISTS |
6 |
Entity already exists |
409 |
No |
| PERMISSION_DENIED |
7 |
Caller identified but not allowed |
403 |
No |
| RESOURCE_EXHAUSTED |
8 |
Quota or resource exhausted |
429 |
With backoff |
| FAILED_PRECONDITION |
9 |
System not in the required state |
400 |
No (fix state first) |
| ABORTED |
10 |
Concurrency conflict, transaction abort |
409 |
At a higher level |
| OUT_OF_RANGE |
11 |
Past the valid range |
400 |
No |
| UNIMPLEMENTED |
12 |
Method not implemented |
501 |
No |
| INTERNAL |
13 |
Invariant broken |
500 |
No |
| UNAVAILABLE |
14 |
Transient unavailability |
503 |
Yes, with backoff |
| DATA_LOSS |
15 |
Unrecoverable data loss |
500 |
No |
| UNAUTHENTICATED |
16 |
No valid credentials |
401 |
After refreshing credentials |
gRPC Wire Protocol and Defaults
| Item |
Value |
| Transport |
HTTP/2 (PROTOCOL-HTTP2.md). HTTP/3 is specified in gRFC G2 and implemented only in grpc-dotnet |
| Request path |
/{package}.{Service}/{Method} |
| Content type |
application/grpc, application/grpc+proto, application/grpc+json |
| Deadline header |
grpc-timeout (for example grpc-timeout: 1S) |
| Status |
grpc-status and grpc-message in HTTP/2 trailers. HTTP status is 200 even for RPC errors |
| Default max receive message size |
4 MiB (grpc-go defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4). Send size unlimited by default |
| Health checking service |
grpc.health.v1.Health (Check, Watch) |
| Server reflection service |
grpc.reflection.v1.ServerReflection (older v1alpha still widely served) |
| Kubernetes gRPC probes |
Stable since Kubernetes v1.27. TLS mode (GRPCContainerProbeTLS) is alpha since v1.37 |
| gRPC-Web |
application/grpc-web, application/grpc-web-text. Unary and server streaming only |
| CNCF status |
Incubating since 2017-02-16 |
WebSocket Frames and Close Codes
| Opcode |
Frame |
0x0 |
Continuation |
0x1 |
Text (UTF-8) |
0x2 |
Binary |
0x8 |
Close |
0x9 |
Ping (either endpoint may send) |
0xA |
Pong |
| Close code |
Meaning |
| 1000 |
Normal closure |
| 1001 |
Going away (server shutdown, page navigation) |
| 1002 |
Protocol error |
| 1003 |
Unsupported data type |
| 1006 |
Abnormal closure (no close frame; never sent on the wire) |
| 1007 |
Invalid payload data (for example, non-UTF-8 text) |
| 1008 |
Policy violation |
| 1009 |
Message too big |
| 1011 |
Internal server error |
| 4000–4999 |
Application-defined |
OpenAPI 3.x Feature Matrix
| Feature |
3.0.x |
3.1.x |
3.2.x |
| Schema dialect |
Extended subset of JSON Schema draft-05 |
Full JSON Schema 2020-12 (jsonSchemaDialect, per-schema $schema) |
Same as 3.1 |
nullable: true |
Yes |
Removed. Use type: [string, "null"] |
Removed |
exclusiveMinimum / exclusiveMaximum |
Boolean modifiers |
Numeric values |
Numeric values |
Top-level webhooks |
No |
Yes |
Yes |
paths optional |
No |
Yes |
Yes |
info.summary, license.identifier (SPDX) |
No |
Yes |
Yes |
QUERY method (query field) |
No |
No |
Yes |
Other methods (additionalOperations) |
No |
No |
Yes |
Streaming media (itemSchema, itemEncoding) for SSE, JSON Lines, multipart |
No |
No |
Yes |
Hierarchical tags (summary, parent, kind) |
No |
No |
Yes |
Document base URI ($self) |
No |
No |
Yes |
Whole query string parameter (in: querystring) |
No |
No |
Yes |
OAuth 2.0 Device Authorization flow, oauth2MetadataUrl |
No |
No |
Yes |
OWASP API Security Top 10 (2023) Summary
| ID |
Risk |
Details |
| API1:2023 |
Broken Object Level Authorization (BOLA) |
Explanation |
| API2:2023 |
Broken Authentication |
Explanation |
| API3:2023 |
Broken Object Property Level Authorization |
Explanation |
| API4:2023 |
Unrestricted Resource Consumption |
Explanation |
| API5:2023 |
Broken Function Level Authorization (BFLA) |
Explanation |
| API6:2023 |
Unrestricted Access to Sensitive Business Flows |
Explanation |
| API7:2023 |
Server-Side Request Forgery (SSRF) |
Explanation |
| API8:2023 |
Security Misconfiguration |
Explanation |
| API9:2023 |
Improper Inventory Management |
Explanation |
| API10:2023 |
Unsafe Consumption of APIs |
Explanation |
Hardening Checklists
SSRF Deny-List
Block these targets for any server-side fetch of a user-supplied URL (webhook URLs, image fetchers, import-from-URL). Resolve the hostname first and check the resolved IP, and re-check after every redirect.
| Target |
IP / domain |
| AWS IMDS |
169.254.169.254, fd00:ec2::254 (IPv6 IMDS) |
| GCP metadata |
metadata.google.internal, 169.254.169.254 |
| Azure IMDS |
169.254.169.254 |
| Loopback / "this host" |
127.0.0.0/8, 0.0.0.0/8, ::1/128 |
| Private networks (RFC 1918) |
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
| IPv6 unique local |
fc00::/7 |
| Link-local |
169.254.0.0/16, fe80::/10 |
| Carrier-grade NAT |
100.64.0.0/10 |
Security Misconfiguration Checklist
| Configuration |
Secure setting |
| TLS |
TLS 1.2+ only. Disable SSLv3, TLS 1.0, TLS 1.1 |
| CORS |
Explicit origin allowlist. Never reflect arbitrary origins with credentials |
| Error responses |
Generic messages. Never expose stack traces, SQL errors, or internal paths |
| HTTP methods |
Disable unused methods (TRACE, TRACK) |
| Security headers |
See Security Response Headers |
| Default credentials |
Remove all defaults. Rotate secrets on deployment |
| Debug endpoints |
Remove /debug, /metrics, and internal health details from public routes, or protect them |
| API documentation |
Disable Swagger UI, GraphiQL, introspection, and gRPC reflection in production unless intentionally public |
Headers every JSON API should set (OWASP REST Security Cheat Sheet):
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Cache-Control: no-store
Content-Security-Policy: default-src 'none'; frame-ancestors 'none'
TLS Hardening Checklist
- TLS 1.2 minimum, TLS 1.3 preferred (1-RTT handshake, forward secrecy built in).
- Disable SSLv3, TLS 1.0, and TLS 1.1.
- HSTS with a long
max-age, includeSubDomains, and preload.
- Automate certificate issuance and rotation (ACME, cert-manager). Lifetimes drop to 200 days in 2026 and 47 days by 2029.
- OCSP stapling helps only for CAs that still run OCSP. Let's Encrypt stopped OCSP on 2025-08-06.
- Monitor Certificate Transparency logs for mis-issued certificates.
- Use the Mozilla SSL Configuration Generator "intermediate" profile as the baseline. A config example is in How-to Guides — TLS Configuration.
gRPC Security Checklist
- All methods enforce authentication and authorization (interceptors, not per-handler code).
- Input validation runs on all message fields (protovalidate).
- Rate limiting and message size limits are set (
MaxRecvMsgSize, concurrent streams).
- TLS or mTLS is on. No
insecure.NewCredentials() outside local development.
- Error messages use gRPC status codes and do not leak stack traces.
- Server reflection and health details are not exposed to untrusted callers.
| Tool |
Type |
Target |
| ZAP (formerly OWASP ZAP) |
DAST (dynamic) |
REST, GraphQL, OpenAPI import |
| Burp Suite |
DAST (proxy-based) |
REST, GraphQL, WebSocket |
| Nuclei |
Template-based scanner |
Any HTTP API |
| Semgrep |
SAST (static) |
Source code patterns |
| Schemathesis |
Property-based API fuzzing |
OpenAPI, GraphQL |
| GraphQL Cop |
GraphQL-specific |
Introspection, batching, DoS vectors |
| grpcurl |
gRPC CLI |
Manual auth and reflection checks |
A curl-based manual test checklist is in How-to Guides — API Security Testing.
API Gateway Comparison
| Gateway |
Deployment |
Config model |
Rate limiting algorithm |
Best for |
| Kong Gateway |
Self-hosted / Konnect (SaaS) |
Declarative YAML (decK) / Admin API |
OSS rate-limiting: fixed windows. Enterprise rate-limiting-advanced: sliding window |
Plugin ecosystem, large teams |
| Envoy |
Self-hosted (edge or sidecar) |
xDS (dynamic) / static YAML |
Local token bucket; global via external rate limit service |
Service mesh, Kubernetes |
| AWS API Gateway |
Managed |
Console / CDK / SAM |
Token bucket (per account, stage, method) |
AWS-native serverless |
| NGINX |
Self-hosted |
Imperative config |
Leaky bucket (limit_req) |
Simple reverse proxy |
| Traefik |
Self-hosted |
Auto-discovery (Kubernetes, Docker) |
Token bucket middleware |
Kubernetes ingress |
| Azure API Management |
Managed |
Portal / ARM / Bicep |
Policy-based (rate-limit, quota) |
Azure-native |
See also Envoy Gateway for the Kubernetes Gateway API implementation of Envoy.
| Format |
Ecosystem |
Codegen |
Mock server |
Linting |
Breaking-change check |
| OpenAPI 3.x |
REST / HTTP |
openapi-generator, oapi-codegen, openapi-typescript |
Prism, WireMock, Microcks |
Spectral, Vacuum, Redocly CLI |
oasdiff, openapi-diff, Optic |
| AsyncAPI 3.x |
Event-driven |
AsyncAPI Generator |
Microcks |
Spectral (spectral:asyncapi), AsyncAPI CLI |
AsyncAPI CLI diff |
| GraphQL SDL |
GraphQL |
graphql-codegen |
graphql-tools mocks, Apollo mocks |
graphql-eslint |
GraphQL Inspector, GraphOS schema checks |
| Protobuf |
gRPC / Connect |
buf generate, protoc |
grpc-mock servers, Connect test servers |
buf lint |
buf breaking |
| WSDL |
SOAP |
JAX-WS, .NET dotnet-svcutil, zeep (Python) |
SoapUI |
SoapUI |
— |
| Category |
Tools |
| API spec editors |
Stoplight Studio, Swagger Editor, Redocly |
| Linting |
Spectral (OpenAPI/AsyncAPI), Vacuum, buf lint (Protobuf) |
| Mock servers |
Prism, WireMock, Microcks |
| Client testing |
Postman, Insomnia, Bruno, HTTPie |
| CLI testing |
curl, httpie, grpcurl, wscat, mqtt-cli |
| Load testing |
Grafana k6, Gatling, Locust, Apache JMeter |
| Contract testing |
Pact, Dredd, Schemathesis |
| Documentation |
Redoc, Swagger UI, Scalar, Mintlify |
| API gateways |
Kong, Envoy, AWS API Gateway, Traefik |
| Service mesh |
Istio, Linkerd, Consul |
| Code generation |
openapi-generator, oapi-codegen, buf generate, graphql-codegen |
| Monitoring |
OpenTelemetry, Grafana + Prometheus, Datadog APM, New Relic |
Illustrative, not measured
The figures below are order-of-magnitude rules of thumb carried over from earlier versions of this note. No single benchmark with published test conditions backs them. Treat them as TBD until you measure your own payloads. Real results depend on payload shape, serializer, compression, network, and implementation.
| Metric |
REST (JSON/HTTP/2) |
GraphQL (JSON/HTTP/2) |
gRPC (Protobuf/HTTP/2) |
| Serialization size (1 KB logical payload) |
~1.2 KB |
~1.0 KB (no over-fetching) |
~0.4 KB |
| Serialization time |
1x baseline |
~1x |
~0.1–0.3x (binary) |
| Latency (unary, same DC) |
~1–5 ms |
~2–8 ms (resolver overhead) |
~0.5–2 ms |
| Throughput (single connection) |
Limited by HTTP/1.1 head-of-line blocking; better on HTTP/2 |
Same as REST |
Higher (multiplexed, binary) |
| Browser support |
Native |
Native |
gRPC-Web or Connect required |
| Streaming |
SSE for server push |
Subscriptions (WebSocket or SSE) |
4 RPC types |
When performance matters less
For most CRUD APIs, the difference between REST and gRPC latency is small compared to database query time. Choose the paradigm based on developer experience and client requirements, not raw protocol speed. Raw protocol speed matters for low-latency trading systems or millions of internal RPCs per second.
Sources
- OpenAPI Specification v3.2.1 and OAI/OpenAPI-Specification releases
- Announcing OpenAPI v3.2 — OpenAPI Initiative
- AsyncAPI 3.1.0 release notes
- JSON Schema specification
- GraphQL September 2025 edition announcement and spec
- GraphQL over HTTP spec and Composite Schemas spec
- Protobuf Editions overview
- gRPC status codes, gRPC over HTTP/2, gRFC G2: gRPC over HTTP/3
- RFC 9110 HTTP Semantics, RFC 9113 HTTP/2, RFC 9114 HTTP/3
- RFC 10008 The HTTP QUERY Method
- RFC 9457 Problem Details, RFC 9745 Deprecation header, RFC 8594 Sunset header
- RateLimit header fields draft, Idempotency-Key header draft
- OAuth 2.1 draft
- OWASP API Security Top 10 2023 and OWASP REST Security Cheat Sheet
- Standard Webhooks specification
- WebTransport — W3C and draft-ietf-webtrans-http3
- Kubernetes: Configure Liveness, Readiness and Startup Probes
- Let's Encrypt: Ending OCSP Support in 2025
- CA/Browser Forum Baseline Requirements
- Apollo Server previous versions (EOL dates)
- CNCF landscape data (gRPC, Connect RPC, CloudEvents maturity)