3. Request & Response Identification#

In production, the hardest bugs are the ones you can’t trace. JsonDispatch enforces consistent tracing identifiers on every response so developers can connect logs, monitor latency, and debug across distributed systems — automatically.

3.1 X-Request-Id – server-generated trace ID#

Every response must include a globally unique request identifier generated by the server. Clients do not send this header.

Rules

  • Generated once per inbound request (UUID v4, ULID, or equivalent unique token).

  • Must be a string.

  • Included in all responses, including errors.

  • Logged internally for correlation in monitoring and debugging.

Example

Client → Server:

GET /articles
Accept: application/vnd.infocyph.jd.v1+json
X-Api-Version: 1.4.0

Server → Client#

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: 7e0e7b45-1e89-4a7f-bbd3-f7ac73fae951

Tip

When a user reports an issue, the X-Request-Id from the response can be searched in logs to reconstruct the full execution path.

3.3 Distributed tracing (traceparent, tracestate)#

For systems instrumented with distributed-tracing tools such as OpenTelemetry, Jaeger, or Zipkin, JsonDispatch is compatible with the W3C Trace Context.

These headers complement (not replace) JsonDispatch identifiers:

  • ``traceparent`` — carries trace ID and span ID.

  • ``tracestate`` — vendor-specific trace metadata.

Example

Request

GET /profile
Accept: application/vnd.infocyph.jd.v1+json
X-Api-Version: 1.4.0
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
tracestate: congo=t61rcWkgMzE

Response#

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: 1b0c9d4b-eaa2-40d0-8715-fc93e6fefb99
X-Correlation-Id: session-998877
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
tracestate: congo=t61rcWkgMzE

Summary

Header

Direction

Purpose

Required

X-Request-Id

Response →

Unique server-generated request trace ID

✅ Yes

X-Correlation-Id

Both ↔

Link related requests in a workflow

⚪ Optional

X-Api-Version

Request →

Requested JsonDispatch API version

✅ Yes

X-Api-Version-Selected

Response →

Server JsonDispatch version identifier

✅ Yes

traceparent

Both ↔

Distributed tracing (W3C)

⚪ Optional

tracestate

Both ↔

Vendor-specific tracing metadata

⚪ Optional

3.4 Rate limiting#

To protect API resources and ensure fair usage, JsonDispatch recommends standard rate limiting headers that inform clients about their current usage and limits.

Include these headers in all successful responses (and optionally in error responses).

Standard approach (X-prefixed headers)

Header

Description

Example

X-RateLimit-Limit

Maximum requests allowed in the current window

1000

X-RateLimit-Remaining

Requests remaining in the current window

987

X-RateLimit-Reset

Unix timestamp when the rate limit resets

1698249600

X-RateLimit-Window (optional)

Duration of the rate limit window

3600 (1h)

Example response with rate limit headers

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: 9b7f3c2a-4e1d-4f8c-a3b2-1e5d6c8f9a0b
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1698249600

IETF Draft Standard (optional alternative)

JsonDispatch also supports the IETF RateLimit Header Fields draft which uses non-prefixed headers:

Header

Description

Example

RateLimit-Limit

Maximum requests allowed in the current window

1000

RateLimit-Remaining

Requests remaining in the current window

987

RateLimit-Reset

Seconds until the rate limit resets

3600

RateLimit-Policy

Rate limit policy definition

1000;w=3600

Example response with IETF Draft headers

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: 9b7f3c2a-4e1d-4f8c-a3b2-1e5d6c8f9a0b
RateLimit-Limit: 1000
RateLimit-Remaining: 987
RateLimit-Reset: 3600
RateLimit-Policy: 1000;w=3600

Note

The main difference is that RateLimit-Reset uses seconds (delta) while X-RateLimit-Reset uses a Unix timestamp. Choose one approach consistently across your API.

Policy format

  • 1000;w=3600 = 1000 requests per 3600 seconds (1 hour)

  • 100;w=60 = 100 requests per 60 seconds (1 minute)

  • 10000;w=86400 = 10000 requests per 86400 seconds (24 hours)

Combined approach (maximum compatibility)

For maximum compatibility, you may send both header styles:

Response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: 9b7f3c2a-4e1d-4f8c-a3b2-1e5d6c8f9a0b
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1698249600
RateLimit-Limit: 1000
RateLimit-Remaining: 987
RateLimit-Reset: 3600
RateLimit-Policy: 1000;w=3600

Tip

If you’re building a new API, prefer the IETF Draft headers as they are likely to become a standard. For existing APIs, continue with X-prefixed headers for backward compatibility.

When a client exceeds their rate limit, return ``429 Too Many Requests`` with a fail status:

Response

HTTP/1.1 429 Too Many Requests
Content-Type: application/json; charset=utf-8
X-Api-Version-Selected: 1.4.0
X-Request-Id: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1698249600
Retry-After: 3600
{
  "status": "fail",
  "message": "Rate limit exceeded",
  "data": {
    "errors": [
      {
        "code": "RATE_LIMIT_EXCEEDED",
        "message": "You have exceeded the rate limit of 1000 requests per hour"
      }
    ]
  },
  "_properties": {
    "rate_limit": {
      "limit": 1000,
      "remaining": 0,
      "reset_at": "2025-10-22T16:00:00Z",
      "retry_after_seconds": 3600
    }
  },
  "_links": {
    "upgrade": "https://example.com/pricing",
    "docs": "https://docs.example.com/rate-limits"
  }
}

Note

Include the Retry-After header (in seconds) to tell clients when they can retry.

JsonDispatch supports various rate limiting strategies:

Per-user rate limiting

Rate limits tied to authenticated user accounts:

X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4872
X-RateLimit-Reset: 1698253200

Per-API-key rate limiting

Different limits for different API keys or service tiers:

X-RateLimit-Limit: 100000
X-RateLimit-Remaining: 99234
X-RateLimit-Reset: 1698253200

Per-endpoint rate limiting

Some endpoints may have stricter limits than others. Use _properties to communicate this:

{
  "status": "success",
  "data": { "...": "..." },
  "_properties": {
    "rate_limit": {
      "endpoint_limit": 100,
      "endpoint_remaining": 87,
      "endpoint_window": "60s"
    }
  }
}

Tip

Always log rate limit violations with X-Request-Id to identify abusive patterns and help legitimate users understand their usage.