APIs: Concepts, Design, Requests, Responses, and Integration
API Proxy: Request Flow, Configuration, Security, and Troubleshooting
Learn how API proxies route, transform, secure, and observe HTTP requests between clients and upstream services.
An API proxy is an intermediary service that accepts an API request from a client, optionally changes it, forwards it to an upstream service, and returns the upstream response. The client may be a browser, mobile application, device, backend service, or command-line program.
Proxies are useful when you need to hide upstream details, protect credentials, apply security policies, route requests, translate incompatible interfaces, collect observability data, or provide a stable public API while backend services change.
Prerequisites
- HTTP request and response structure
- HTTP methods such as
GET,POST,PUT, andDELETE - URLs, paths, query parameters, headers, and JSON bodies
- Basic client-server architecture
- HTTPS and basic authentication concepts
How an API Proxy Works
A typical request follows this path:
- The client sends a request to a public proxy endpoint.
- The proxy matches the request against a route, which is a rule identifying its destination and handling behavior.
- The proxy validates the request and may add, remove, or replace headers, query parameters, or body fields.
- The proxy sends the resulting request to the upstream service, the backend API that handles the operation.
- The upstream returns an HTTP status code, headers, and possibly a response body.
- The proxy may filter, transform, cache, or otherwise process the response.
- The proxy returns a client-facing response.
Client
|
| GET /api/products?page=2
v
API proxy
| route match, validation, auth injection, logging
| GET https://catalog.internal/items?page=2
v
Upstream API
|
| 200 OK + JSON response
v
API proxy
|
| 200 OK + client-facing JSON response
v
Client
The proxy can forward a request transparently, meaning that its method, path, headers, query string, and body are preserved as much as possible. It can also transform the request or response to create a different client-facing contract.
Parts of a Proxied HTTP Request
| Part | Purpose | Possible proxy behavior |
|---|---|---|
| URL and path | Identify the endpoint and resource | Map /api/products to /catalog/items |
| HTTP method | Describe the operation | Usually preserve it; restrict unsupported methods |
| Headers | Carry metadata, credentials, content information, and tracing data | Add, remove, replace, or allowlist headers |
| Query parameters | Modify filtering, pagination, sorting, or selection | Rename, validate, add, or remove parameters |
| Body | Carry submitted data, commonly JSON | Validate or convert fields and formats |
| Status code | Describe the result of the request | Pass through or map upstream failures |
| Response body | Return data or error details | Filter fields, compose results, or normalize errors |
Why Use an API Proxy?
- Abstraction: clients use a stable endpoint while the upstream host, path, or implementation changes.
- Security: server-side credentials can remain outside browser and mobile code.
- Routing: one public hostname can direct requests to multiple services.
- Compatibility: the proxy can translate between different paths, headers, payloads, or response formats.
- Observability: centralized logging, metrics, correlation IDs, and tracing can cover many services.
- Traffic policy: rate limits, caching, timeouts, retries, and access rules can be applied consistently.
- Aggregation: one client request can produce a response composed from several backend services.
A proxy is not automatically valuable. If it only adds a network hop and performs no useful policy, security, routing, compatibility, or observability work, it may increase latency and operational complexity without a meaningful benefit.
Proxy Types
| Component | Position in request path | Primary user | Typical responsibilities | Common use cases |
|---|---|---|---|---|
| Forward proxy | Between clients and external servers | Clients or client networks | Outbound access control, filtering, privacy, and egress policy | Corporate internet access and controlled service-to-service egress |
| Reverse proxy | In front of servers and backend services | Applications and API clients | Receive public traffic, terminate TLS, route requests, and protect backends | Web applications, APIs, load balancing, and service entry points |
| API gateway | Usually at the API edge, often as a reverse proxy | API consumers and platform teams | Routing, authentication, policy enforcement, analytics, documentation, and lifecycle management | Managed API products and multi-team API platforms |
An API proxy is commonly a focused reverse proxy for API traffic. An API gateway is a broader API-management entry point. The terms can overlap, but a gateway generally includes more product, policy, analytics, and lifecycle capabilities than a simple proxy.
Common Proxy Styles
- Pass-through proxy: forwards requests and responses with minimal changes.
- Routing proxy: selects one upstream based on path, host, method, tenant, or other request properties.
- Transformation proxy: changes headers, query parameters, payloads, or responses.
- Aggregation proxy: calls multiple upstream services and composes one client-oriented response.
Routing, Rewriting, and Transformation
A route matches an incoming request and determines what happens next. A route can match a path such as /api/products, a host such as api.example.test, an HTTP method, or a combination of conditions.
route:
match:
path: /api/products/{remainder}
methods: [GET, POST]
upstream:
base_url: https://catalog.internal
rewrite:
/api/products/{remainder} -> /items/{remainder}
forward_headers:
- Accept
- Content-Type
- X-Correlation-ID
timeout: 5s
In this conceptual configuration, a request for /api/products/42 becomes an upstream request for /items/42. The public path is isolated from the upstream path, so the backend can change without requiring every client to change immediately.
Common Transformations
- Path rewrite: change the path before forwarding it.
- Header addition: add a correlation ID, service identity, or content-negotiation header.
- Header removal: remove client-supplied internal or sensitive headers.
- Header replacement: replace a client credential with a server-managed credential.
- Query transformation: rename, validate, default, or remove query parameters.
- Payload transformation: convert field names, versions, formats, or envelopes.
- Response filtering: remove internal fields before returning data to a client.
- Response composition: combine profile and order data into one response.
Transformations require clear ownership and tests. Document whether the proxy preserves an upstream response exactly or defines its own public contract.
Conceptual Client Request
POST https://app.example.test/api/orders HTTP/1.1
Content-Type: application/json
Accept: application/json
X-Correlation-ID: 7f2c1a90
{
"productId": "p-42",
"quantity": 2
}
The browser calls the proxy's same-origin endpoint rather than exposing a third-party upstream URL or secret. The proxy can validate the JSON, add a server-side authorization header, and send a different request to the upstream order service.
Core Capabilities
| Capability | Purpose | Important consideration |
|---|---|---|
| Host and protocol handling | Connect to the correct upstream scheme and host | Use HTTPS and define expected host-header behavior |
| Routing | Send requests to one or more services | Specify precedence when routes overlap |
| Load balancing | Distribute traffic among healthy upstream instances | Use health checks and preserve required session behavior |
| Timeouts | Bound connection and response waiting time | Choose values based on service behavior and user needs |
| Retries | Recover from transient failures | Retry only when duplicate work is safe |
| Rate limiting | Restrict request volume over time | Define the identity and response for limited clients |
| Caching | Reuse eligible responses | Respect authorization, freshness, and privacy requirements |
| Response transformation | Return a stable or smaller client response | Do not accidentally remove required fields or error context |
Authentication and Security
Keep client-facing credentials separate from upstream credentials. A browser may authenticate to the proxy with a session cookie or user token, while the proxy uses a server-side credential to call a third-party API. The upstream secret must be stored in a protected server-side secret store or environment-managed secret, never in browser JavaScript, public configuration, or a response.
security:
require_https: true
upstream_secret: SECRET_REF_CATALOG_API
client_headers:
remove:
- Authorization
- X-Upstream-Api-Key
allow:
- Accept
- Content-Type
- X-Correlation-ID
upstream_headers:
set:
Authorization: "Bearer ${SECRET_REF_CATALOG_API}"
X-Service-Name: "orders-proxy"
The exact policy depends on the authentication model. A proxy may forward a validated user token, exchange it for another token, inject an API key, or use its own service identity. Do not blindly forward every client header: headers such as Host, Authorization, and internal routing headers may require explicit treatment.
HTTPS and CORS
- Use HTTPS from the client to the proxy to protect credentials and request data in transit.
- Use HTTPS from the proxy to the upstream when the network is not fully trusted or when the upstream requires it.
- Validate upstream certificates and avoid disabling certificate verification as a convenience.
- For browser clients, configure CORS for specific allowed origins rather than broadly allowing every origin.
- Handle the browser's
OPTIONSpreflight request when required. - Return appropriate CORS headers on relevant error responses as well as successful responses.
cors:
allowed_origins:
- https://app.example.test
allowed_methods: [GET, POST, OPTIONS]
allowed_headers: [Content-Type, Authorization, X-Correlation-ID]
handle_preflight: true
allow_credentials: true
CORS is enforced by browsers; it is not an authentication mechanism. A CORS allowlist controls which browser origins may read responses, while authentication and authorization control who may perform an operation.
Additional Controls
- Validate paths, methods, query parameters, headers, and JSON schemas.
- Use upstream host and URL allowlists to prevent server-side request forgery.
- Set request body and header-size limits.
- Apply rate limits and abuse detection appropriate to the endpoint.
- Prevent log injection and redact tokens, cookies, API keys, and sensitive body fields.
- Reject unexpected client-supplied internal headers.
Error Handling and Reliability
Distinguish an error produced by the proxy from an error returned by the upstream. A proxy-generated 502 or 504 usually indicates a connectivity or timing problem between the proxy and upstream. An upstream-generated 401, 404, or 422 may describe the request as understood by the upstream.
| Condition | Likely HTTP response category | Recommended client-facing behavior | Diagnostic information to log |
|---|---|---|---|
| Invalid client input | 4xx, commonly 400 or 422 | Return a clear validation error without calling upstream | Route, validation reason, and correlation ID |
| Client is unauthenticated or forbidden | 401 or 403 | Follow the public authentication contract | Auth policy result, never raw credentials |
| Upstream rejects a validly forwarded request | Pass through or map to 4xx | Return a stable, safe error format | Upstream status, route, and redacted response details |
| Upstream connection or DNS failure | 502 or another gateway error | Use a generic temporary-service message | Resolved host, connection error class, and correlation ID |
| Upstream exceeds timeout | 504 | Tell the client the service did not respond in time | Timeout phase, duration, and upstream target |
| Proxy is overloaded | 429 or 503 | Provide retry guidance where appropriate | Limit state, capacity metrics, and queue information |
Use a consistent public error shape, for example:
{
"error": {
"code": "UPSTREAM_TIMEOUT",
"message": "The service did not respond in time.",
"correlationId": "7f2c1a90"
}
}
Do not expose internal hostnames, stack traces, secret values, or detailed network errors to clients. Keep those details in protected logs.
Timeouts, Retries, and Idempotency
A timeout can occur while connecting, sending the request, or waiting for response data. A timeout does not always mean the upstream did no work: it may have accepted and processed the request before the proxy stopped waiting.
Retries are safer for idempotent operations such as many GET requests, but even those may have side effects in poorly designed systems. Automatically retrying a POST can create duplicate records or charges. For retryable write operations, use an idempotency key and ensure the upstream honors it. Also account for a client retry combined with a proxy retry.
Observability and Operations
- Logs: record method, route, status, duration, upstream target, and outcome. Redact authorization headers, cookies, API keys, and sensitive body fields.
- Correlation IDs: accept a trusted incoming identifier or generate one, return it to the client, and propagate it upstream.
- Metrics: measure request volume, latency percentiles, status-code counts, timeout counts, retry counts, rate-limit events, and upstream health.
- Tracing: create or propagate trace context so a request can be followed through the proxy and backend services.
- Health checks: monitor proxy process health separately from upstream readiness, and check dependencies without creating harmful traffic.
Use route-level metrics where possible. An overall success rate can hide a failing upstream if several healthy routes dominate the traffic.
Aggregation Example
A client may request a dashboard from one proxy endpoint. The proxy calls a profile service and an order service, then returns a client-oriented response:
GET /api/dashboard/42
{
"user": { "id": "42", "name": "Sam" },
"recentOrders": [
{ "id": "o-100", "total": 24.50 }
]
}
Aggregation reduces client round trips and hides backend topology, but it can increase proxy latency and failure complexity. Decide whether calls should run in parallel, whether partial results are acceptable, and how the proxy reports one failed dependency.
Design Considerations
- Define and document the public endpoint, authentication contract, status codes, error format, limits, and versioning policy.
- Assign ownership for route behavior, upstream credentials, dashboards, alerts, and incident response.
- Keep public contracts stable when upstream APIs change; use versioned routes or transformations when necessary.
- Measure the cost of buffering large bodies, parsing and transforming JSON, caching, aggregation, and additional network hops.
- Stream large responses when safe and supported, rather than buffering the entire response in memory.
- Make cache keys account for method, path, query parameters, authorization context, and relevant headers.
- Do not cache private or user-specific responses unless the cache policy is explicitly safe.
- Test route precedence, trailing slashes, encoded paths, query strings, headers, preflight requests, and upstream failures.
Troubleshooting
The Client Receives 502 or 504
- Check proxy and upstream logs using the correlation ID.
- Verify that the upstream is reachable from the proxy's actual network environment.
- Check DNS resolution, firewall rules, TLS validation, and the configured upstream host.
- Confirm the route and path-rewrite rules.
- Compare upstream latency with connection and response timeout values.
The Upstream Returns an Authentication Error
- Confirm that the proxy's credential reference resolves in the correct environment.
- Inspect redacted forwarded-header logs without printing secret values.
- Check whether the proxy removed or replaced the intended
Authorizationheader. - Verify the upstream's required token type, scope, audience, or API-key location.
A Browser Request Is Blocked by CORS
- Inspect the browser network panel for the
OPTIONSpreflight request. - Compare the configured origin, method, and request headers with the browser's request.
- Ensure the proxy handles preflight before authentication rules reject it when appropriate.
- Verify that suitable CORS headers appear on error responses as well as successful responses.
The Upstream Receives an Unexpected Path or Host
- Log the resolved upstream URL and the selected route.
- Test representative paths with and without trailing slashes and with query strings.
- Review route matching precedence and path-rewrite expressions.
- Check whether the upstream expects its own host in the
Hostheader or another forwarded-host header.
Requests Are Duplicated
- Review retry policies by HTTP method and status condition.
- Check for both client retries and proxy retries.
- Use idempotency keys for operations that can safely support them.
- Trace request IDs across the client, proxy, and upstream to determine whether the first request completed after the timeout.
Summary
- An API proxy sits between a client and one or more upstream services.
- It can forward requests transparently or transform paths, headers, query parameters, bodies, and responses.
- Reverse proxies serve backend-facing entry-point roles; forward proxies serve clients; API gateways add broader API-management features.
- Secure proxies protect upstream credentials, require suitable HTTPS, validate input, control CORS, and limit abuse.
- Reliable proxies use explicit timeouts, careful retry rules, consistent errors, correlation IDs, metrics, logs, and health checks.
- A proxy should provide measurable value rather than adding an unnecessary network hop.
For related API concepts, see API, GraphQL, Fetch, and Credentials.