> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sazabi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS API Gateway

> Send AWS API Gateway access and execution logs from CloudWatch Logs to Sazabi to see who calls which API, failed authorizations, and abusive clients.

[All AWS integration capabilities](https://docs.sazabi.com/catalogs/integrations/aws)

## About

API Gateway access logs record every request a stage handles: caller IP, authenticated identity, route, status, latency, and authorizer or WAF errors. In Sazabi they show who calls which API, which requests fail authorization, and which clients are throttled or abusive. REST APIs can also write execution logs with authorizer and integration detail.

API Gateway writes both kinds of log to CloudWatch Logs. Sazabi reads them through the same CloudWatch path as the [AWS CloudWatch](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/cloudwatch.md) source.

> [!TIP]
>
> Already connected your AWS account with the [native AWS CloudWatch source](https://docs.sazabi.com/catalogs/log-sources/connect-your-account/cloudwatch.md)? Turn on API Gateway logging (step 1), then pick the API Gateway log groups in that source's log group list. You don't need a collector.

## Prerequisites

* An API Gateway REST, HTTP, or WebSocket API
* An [OpenTelemetry Collector Contrib](https://github.com/open-telemetry/opentelemetry-collector-contrib) deployment, which ships the `awscloudwatch` receiver
* AWS credentials for the collector with `logs:DescribeLogGroups` and `logs:FilterLogEvents`
* Your Sazabi intake URL, shown above — open the log source and copy the **Intake URL** from its setup screen (the public key is embedded in the URL)

## Set up in the dashboard

**Step 1**

### Turn on API Gateway logging

For each API stage, turn on access logging, send it to a CloudWatch log group whose name starts with `API-Gateway-Access-Logs_`, and use a JSON format. This format captures the fields most useful for security:

```json title="Access log format" theme={"system"}
{
  "requestId": "$context.requestId",
  "requestTime": "$context.requestTimeEpoch",
  "ip": "$context.identity.sourceIp",
  "userAgent": "$context.identity.userAgent",
  "caller": "$context.identity.caller",
  "user": "$context.identity.user",
  "principalId": "$context.authorizer.principalId",
  "httpMethod": "$context.httpMethod",
  "resourcePath": "$context.resourcePath",
  "status": "$context.status",
  "responseLatency": "$context.responseLatency",
  "authorizerError": "$context.authorizer.error",
  "wafResponseCode": "$context.wafResponseCode",
  "integrationStatus": "$context.integration.status"
}
```

For HTTP and WebSocket APIs, use `$context.routeKey` in place of `$context.resourcePath`.

For REST APIs, also turn on execution logging at `ERROR` or `INFO` level on each stage. API Gateway writes execution logs to log groups whose names start with `API-Gateway-Execution-Logs_`. Execution logging needs a CloudWatch Logs role with the `AmazonAPIGatewayPushToCloudWatchLogs` policy, set once per region under API Gateway **Settings**.

**Step 2**

### Configure the collector

Add the `awscloudwatch` receiver and the Sazabi exporter to your collector configuration. Set `region` to the region your APIs run in; add one receiver per region.

```yaml title="otelcol.yaml" theme={"system"}
receivers:
  awscloudwatch/api-gateway:
    region: us-east-1
    logs:
      poll_interval: 1m
      groups:
        autodiscover:
          limit: 100
          prefix: API-Gateway-

exporters:
  otlphttp/sazabi:
    endpoint: <your intake URL>

service:
  pipelines:
    logs:
      receivers: [awscloudwatch/api-gateway]
      exporters: [otlphttp/sazabi]
```

If your access log groups use another name, list them under `groups.named` instead of `autodiscover`. The collector uses the standard AWS SDK credential chain; the credential stays with your collector and is never sent to Sazabi.

**Step 3**

### Deploy and send a request

Deploy the collector, then send a request to one of your APIs. Records appear after the next poll.

### Other API gateways

Kong and Apigee don't write to CloudWatch Logs. Send their logs to an [OpenTelemetry Collector](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/otel-collector.md) and connect that collector to Sazabi.

> [tab] Kong
>
> Turn on Kong's [OpenTelemetry plugin](https://developer.konghq.com/plugins/opentelemetry/) and point its `logs_endpoint` at the collector's OTLP/HTTP receiver. Kong Gateway 3.8 and later export request and plugin logs over OTLP.
>
> ```yaml title="kong.yaml" theme={"system"}
> plugins:
>   - name: opentelemetry
>     config:
>       logs_endpoint: http://otel-collector:4318/v1/logs
>       resource_attributes:
>         service.name: kong
> ```
>
> ```yaml title="otelcol.yaml" theme={"system"}
> receivers:
>   otlp:
>     protocols:
>       http:
>         endpoint: 0.0.0.0:4318
>
> service:
>   pipelines:
>     logs:
>       receivers: [otlp]
>       exporters: [otlphttp/sazabi]
> ```

> [tab] Apigee
>
> Add a [MessageLogging policy](https://cloud.google.com/apigee/docs/api-platform/reference/policies/message-logging-policy) to your API proxies that sends syslog over TCP to the collector, and receive it with the `syslog` receiver from the contrib distribution.
>
> ```xml title="MessageLogging policy" theme={"system"}
> <MessageLogging name="Log-To-Collector">
>   <Syslog>
>     <Message>{"requestId":"{messageid}","client":"{client.ip}","proxy":"{apiproxy.name}","verb":"{request.verb}","path":"{request.path}","status":"{response.status.code}"}</Message>
>     <Host>otel-collector.example.com</Host>
>     <Port>5514</Port>
>     <Protocol>TCP</Protocol>
>     <FormatMessage>true</FormatMessage>
>   </Syslog>
> </MessageLogging>
> ```
>
> ```yaml title="otelcol.yaml" theme={"system"}
> receivers:
>   syslog/apigee:
>     tcp:
>       listen_address: 0.0.0.0:5514
>     protocol: rfc5424
>
> service:
>   pipelines:
>     logs:
>       receivers: [syslog/apigee]
>       exporters: [otlphttp/sazabi]
> ```

## Set up with the CLI

```sh theme={"system"}
sazabi log-sources create aws_api_gateway
sazabi log-sources setup-instructions aws_api_gateway
```

The create command prints the intake URL for the collector's `otlphttp/sazabi` endpoint.

## Verify

Open the **Intake** page in the Sazabi dashboard and confirm records from the AWS API Gateway source appear within a few minutes. From the CLI, `sazabi logs ask "How many API Gateway access log lines arrived in the last 15 minutes, by status?"` confirms records are arriving. Search for `status` 401 or 403 to find failed authorizations, or 429 to find throttled clients.

## Troubleshooting

**No log groups in CloudWatch** — Access logging is set per stage. Check the stage's log settings, and for execution logs, the account-level CloudWatch Logs role.

**Collector logs `AccessDeniedException`** — The collector's AWS identity is missing `logs:FilterLogEvents` or `logs:DescribeLogGroups`.

**Collector runs but nothing arrives** — Check that your log group names start with `API-Gateway-` and that `region` matches where your APIs run.

## Further reading

> [card] [AWS CloudWatch](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/cloudwatch.md)
>
> Forward any CloudWatch log group to Sazabi.

> [card] [OpenTelemetry Collector](https://docs.sazabi.com/catalogs/log-sources/send-to-an-endpoint/otel-collector.md)
>
> Forward logs from any Collector receiver.

> [card] [Intake](https://docs.sazabi.com/guides/instrument/intake.md)
>
> See per-source ingestion volume and health.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.