API Gateway can’t directly invoke a Lambda function in a different AWS account without a little help.

Let’s see how this looks in practice. Imagine you have an API Gateway in Account A that needs to trigger a Lambda in Account B.

Here’s a common setup:

Account A (API Gateway)

  • API Gateway: my-cross-account-api
  • Resource: /users
  • HTTP Method: GET
  • Integration Type: Lambda Function
  • Lambda Function: arn:aws:lambda:us-east-1:111111111111:function:account-b-lambda

Account B (Lambda Function)

  • Lambda Function: account-b-lambda
  • Runtime: Python 3.9
  • Handler: index.handler
  • Permissions: Needs to allow invocation from Account A’s API Gateway.

The key here is setting up the correct permissions and the integration in API Gateway.

Here’s a simplified index.py for the Lambda in Account B:

import json

def handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Hello from Account B Lambda!',
            'event_received': event # Show what API Gateway sent
        })
    }

Now, let’s configure the API Gateway in Account A. When you set up the Lambda integration, you’ll specify the ARN of the Lambda in Account B.

Crucially, the IAM role that API Gateway uses in Account A needs lambda:InvokeFunction permission for the Lambda in Account B. This is often overlooked.

The Missing Piece: Resource-Based Policy on the Lambda

The most common reason this fails is that the Lambda function in Account B doesn’t have a resource-based policy that explicitly grants invocation permission to the API Gateway in Account A.

Here’s how you’d add that policy to your Lambda function in Account B using the AWS CLI:

aws lambda add-permission \
    --function-name account-b-lambda \
    --statement-id "apigateway-invoke-from-account-a" \
    --action "lambda:InvokeFunction" \
    --principal "arn:aws:iam::222222222222:root" \
    --source-arn "arn:aws:execute-api:us-east-1:222222222222:api-id/stage/*/*"
  • --function-name: The name of your Lambda function in Account B.
  • --statement-id: A unique identifier for this permission statement.
  • --action: The specific Lambda API action being allowed.
  • --principal: This is critical. It should be the AWS account ID of Account A (where API Gateway resides). Use arn:aws:iam::<account-a-id>:root or the specific ARN of the API Gateway service principal if you want to be more granular. For simplicity and common use cases, root is often used.
  • --source-arn: This is a wildcarded ARN for the API Gateway in Account A. Replace api-id with your actual API Gateway ID and stage with your deployment stage name (e.g., prod, dev). The wildcards allow any resource within that API Gateway to invoke the function.

Why this works: AWS services often use IAM roles for cross-account access. However, when a service initiates an invocation (like API Gateway calling Lambda), the target service (Lambda) needs to explicitly allow that invocation. This is done via the resource-based policy on the Lambda function itself. The --principal specifies who is allowed to invoke, and the --source-arn further restricts from which specific resource they can invoke.

Other Common Pitfalls:

  1. Incorrect Lambda ARN in API Gateway: Double-check that the ARN in the API Gateway integration settings in Account A precisely matches the Lambda ARN in Account B. A typo here is a frequent offender.
  2. API Gateway Execution Role Permissions: The IAM role that API Gateway uses in Account A needs lambda:InvokeFunction permission. Make sure this role’s policy includes an entry like:
    {
        "Effect": "Allow",
        "Action": "lambda:InvokeFunction",
        "Resource": "arn:aws:lambda:us-east-1:111111111111:function:account-b-lambda"
    }
    
  3. VPC Configuration: If the Lambda in Account B is in a VPC, ensure that API Gateway can reach it. This might involve NAT gateways or VPC endpoints for Lambda, depending on your network setup. For simple cross-account invocation without VPC, this isn’t an issue.
  4. Region Mismatch: Ensure both API Gateway and the Lambda function are in the same AWS region. While cross-region invocation is possible, it adds complexity and isn’t the default scenario for this problem.
  5. API Gateway Stage and Resource Paths: Verify that the API Gateway stage name and the resource path (/users in our example) are correctly configured and deployed.

After applying the resource-based policy on the Lambda in Account B and ensuring the API Gateway execution role in Account A has the necessary permissions, you should be able to invoke the cross-account Lambda.

The next error you’ll likely encounter is a 502 Bad Gateway if the Lambda function itself has a runtime error or returns an unexpected response.

Want structured learning?

Take the full Apigateway course →