# AWS API Gateway

- Canonical URL: https://docs.fairvisor.com/docs/gateway/aws-api-gateway/
- Section: docs
- Last updated: n/a
> Integrating Fairvisor Edge with AWS API Gateway using Lambda authorizer decision checks.


For AWS, the canonical pattern is API Gateway with a Lambda authorizer that calls Fairvisor `POST /v1/decision`.

## Architecture

```text
Client -> API Gateway -> Lambda authorizer -> Fairvisor /v1/decision
                                  | allow
                                  v
                               Backend integration
                                  | reject
                                  v
                              429 to client
```

## Authorizer request mapping

Your authorizer should pass to Fairvisor:

- `X-Original-Method` from incoming method
- `X-Original-URI` from path + query
- `Authorization` from request headers (if present)
- `X-Forwarded-For` from request context source IP

## Lambda authorizer sketch (Node.js)

```js
export const handler = async (event) => {
  const method = event.requestContext?.http?.method || event.httpMethod || "GET";
  const path = event.rawPath || event.path || "/";
  const query = event.rawQueryString ? `?${event.rawQueryString}` : "";
  const originalUri = `${path}${query}`;

  const headers = {
    "X-Original-Method": method,
    "X-Original-URI": originalUri,
  };

  const auth = event.headers?.authorization || event.headers?.Authorization;
  if (auth) headers.Authorization = auth;

  const ip = event.requestContext?.http?.sourceIp || event.requestContext?.identity?.sourceIp;
  if (ip) headers["X-Forwarded-For"] = ip;

  const res = await fetch(`${process.env.FAIRVISOR_EDGE_URL}/v1/decision`, {
    method: "POST",
    headers,
  });

  if (res.status === 429) {
    return {
      isAuthorized: false,
      context: {
        fairvisor_reason: res.headers.get("x-fairvisor-reason") || "rate_limited",
        retry_after: res.headers.get("retry-after") || "1",
      },
    };
  }

  if (!res.ok) {
    // choose route policy: fail-open or fail-closed
    return { isAuthorized: false };
  }

  return { isAuthorized: true };
};
```

## Gateway response mapping

Configure API Gateway deny responses to preserve `429` semantics and surface:

- `Retry-After`
- `X-Fairvisor-Reason`

If your authorizer path can only return generic deny, add integration response mapping so client still sees meaningful rate-limit metadata.

## Failure policy

Decide explicitly per route class:

- write/admin routes: fail-closed
- public/read routes: fail-open only with alerting

Reference: [Gateway Failure Policy](/docs/reference/gateway-failure-policy/).

## Timeout guidance

- authorizer->Fairvisor timeout: 200-500 ms target
- avoid retries in authorizer hot path
- monitor p95/p99 authorizer latency

## Security notes

- Do not expose Fairvisor publicly; keep it in private network path
- Trust `X-Original-*` only from the authorizer boundary
- Keep `FAIRVISOR_EDGE_URL` in secure runtime config

## Verification checklist

1. Confirm allow path succeeds through API Gateway
2. Trigger limit and verify client receives `429`
3. Confirm `Retry-After` and `X-Fairvisor-Reason` propagation
4. Simulate Fairvisor outage and validate fail-open/closed behavior

See [Decision API](/docs/reference/api/) for contract details.

