API Gateway can invoke any AWS service directly without needing a Lambda function in between.

Let’s see this in action. Imagine you want to trigger an SQS queue when a specific API endpoint is hit. Normally, you might think: API Gateway -> Lambda -> SQS. But we can skip the Lambda.

Here’s a simplified API Gateway configuration for a POST request to /send-message that directly sends a message to an SQS queue named my-test-queue.

# Example AWS SAM template snippet
Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: dev
      DefinitionBody:
        swagger: '2.0'
        info:
          title: Direct Invocation API
          version: '1.0'
        paths:
          /send-message:
            post:
              summary: Send message to SQS directly
              consumes:
                - application/json
              produces:
                - application/json
              parameters:
                - name: body
                  in: body
                  required: true
                  schema:
                    type: object
                    properties:
                      message:
                        type: string
              x-amazon-apigateway-integration:
                type: aws
                uri: arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/services/sqs/actions/sendMessage
                httpMethod: POST
                credentials: arn:aws:iam::123456789012:role/APIGatewayInvokeSQSRole
                requestParameters:
                  integration.request.header.Content-Type: "'application/x-www-form-urlencoded'"
                requestTemplates:
                  application/json: |
                    {
                      "QueueUrl": "https://sqs.us-east-1.amazonaws.com/123456789012/my-test-queue",
                      "MessageBody": "$input.json('$.message')"
                    }

In this example, the x-amazon-apigateway-integration block is key.

  • type: aws tells API Gateway this is a direct AWS service integration.
  • uri points to the specific SQS action (sendMessage). The lambda part in the URI is a bit of a historical artifact for these service integrations; it doesn’t mean Lambda is involved.
  • credentials specifies an IAM role that API Gateway will assume to perform the SQS action. This role needs sqs:SendMessage permissions on arn:aws:sqs:us-east-1:123456789012:my-test-queue.
  • requestParameters sets the Content-Type header for the backend call.
  • requestTemplates is where you map the incoming API request body to the format expected by the SQS sendMessage API. Here, we extract the message field from the JSON input and use it as the MessageBody.

When a client sends a POST request to /send-message with a JSON body like {"message": "Hello SQS!"}, API Gateway will:

  1. Assume the APIGatewayInvokeSQSRole.
  2. Construct an SQS sendMessage API call using the QueueUrl and MessageBody defined in the requestTemplates.
  3. Execute that SQS API call.
  4. Return the SQS API response (or an error) back to the client.

This pattern isn’t limited to SQS. You can integrate directly with many AWS services including DynamoDB, SNS, Kinesis, Step Functions, and even other API Gateways. The general structure involves setting the type to aws and providing a uri that specifies the target service and action, along with appropriate IAM credentials and request/response mappings.

The uri format for AWS service integrations is typically arn:aws:apigateway:<region>:<service_namespace>:path/YYYY-MM-DD/services/<service_name>/actions/<action_name>. For example, for DynamoDB’s PutItem, it might look like arn:aws:apigateway:us-east-1:dynamodb:path/2015-03-31/actions/putItem. The service_namespace is often lambda even though Lambda isn’t used.

The requestTemplates are crucial for transforming the incoming request payload into the structure the target AWS service expects. For DynamoDB PutItem, you’d map fields like TableName, Item, ConditionExpression, etc. For SNS Publish, you’d map TopicArn and Message.

The IAM role needs to be carefully crafted with the minimum necessary permissions. For the SQS example, it would be:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sqs:SendMessage",
            "Resource": "arn:aws:sqs:us-east-1:123456789012:my-test-queue"
        }
    ]
}

The most surprising thing is how infrequently this direct integration is used, often leading developers to build unnecessary Lambda functions that add latency, cost, and operational overhead for simple request-to-service-action mappings.

The x-amazon-apigateway-integration passthroughBehavior property controls how API Gateway handles requests when the requestTemplates don’t explicitly map all incoming parameters. The default is WHEN_NO_MATCH, which means if a parameter isn’t mapped, it’s passed through. NEVER will drop unmapped parameters, and WHEN_NO_TEMPLATES will pass through the entire request body if no templates are defined.

Once you’ve successfully integrated with a service, the next logical step is to handle the response from that service, often by mapping it back to the client or using it to trigger subsequent actions.

Want structured learning?

Take the full Apigateway course →