← Blog

Claude API Lambda Function Integration Tutorial

2026-10-01 · 5 min read · SubToAPI Team

What this tutorial covers

If you're trying to call Claude from an AWS Lambda function, the core challenge isn't the API call itself — it's handling Lambda's execution model correctly: cold starts, timeout limits, environment variables, and how to structure the handler so retries and streaming don't break your function. This tutorial walks through a working Node.js Lambda function that calls Claude, from zero to a deployed, invokable endpoint.

By the end you'll have a Lambda function that accepts a prompt via an event payload, calls the Claude API, and returns the model's response as JSON — plus notes on timeout configuration, error handling, and an easier path if you don't want to manage raw API keys and retry logic yourself.

Prerequisites

Step 1: Create the Lambda function

Using the AWS CLI, create a new function with the Node.js 18.x runtime:

aws lambda create-function \
  --function-name claude-chat-handler \
  --runtime nodejs18.x \
  --role arn:aws:iam::<account-id>:role/lambda-basic-execution \
  --handler index.handler \
  --zip-file fileb://function.zip \
  --timeout 30

The --timeout 30 flag matters: the default Lambda timeout is 3 seconds, which is nowhere near enough for an LLM call that can take 5–20 seconds depending on output length. Set it to at least 30, and higher if you expect long completions.

Step 2: Store your API key securely

Never hardcode the key in your function code. Use Lambda environment variables, ideally encrypted with KMS, or pull from AWS Secrets Manager at cold start:

aws lambda update-function-configuration \
  --function-name claude-chat-handler \
  --environment "Variables={CLAUDE_API_KEY=sk-ant-xxxx}"

If you're using SubToAPI, the same pattern applies — store your sub_live_... key as SUBTOAPI_KEY instead.

Step 3: Write the handler

Here's a minimal handler that accepts a prompt from the event payload and returns Claude's response:

// index.mjs
export const handler = async (event) => {
  const { prompt } = JSON.parse(event.body || "{}");

  if (!prompt) {
    return {
      statusCode: 400,
      body: JSON.stringify({ error: "Missing 'prompt' in request body" }),
    };
  }

  try {
    const response = await fetch("https://api.anthropic.com/v1/messages", {
      method: "POST",
      headers: {
        "content-type": "application/json",
        "x-api-key": process.env.CLAUDE_API_KEY,
        "anthropic-version": "2023-06-01",
      },
      body: JSON.stringify({
        model: "claude-sonnet-4-5",
        max_tokens: 1024,
        messages: [{ role: "user", content: prompt }],
      }),
    });

    if (!response.ok) {
      const errText = await response.text();
      return { statusCode: response.status, body: errText };
    }

    const data = await response.json();
    return {
      statusCode: 200,
      body: JSON.stringify({ reply: data.content[0].text }),
    };
  } catch (err) {
    return {
      statusCode: 502,
      body: JSON.stringify({ error: err.message }),
    };
  }
};

This uses the native fetch available in Node.js 18+ runtimes, so you don't need to bundle an HTTP client. Package index.mjs into a zip and deploy it as the function code.

Step 4: Test the function locally and in AWS

Before deploying, test the logic locally with a plain Node script by importing the handler and calling it with a mock event. Once it works, invoke the deployed function directly:

aws lambda invoke \
  --function-name claude-chat-handler \
  --payload '{"body":"{\"prompt\":\"Explain Lambda cold starts in one sentence\"}"}' \
  response.json

cat response.json

Check CloudWatch Logs for the function if something fails — timeouts, missing permissions, and malformed JSON payloads are the three most common first-deploy issues.

Step 5: Expose it through API Gateway

To call this from a frontend or another service over HTTPS, attach it to an API Gateway HTTP API. Create a route (e.g. POST /chat) and point it at your Lambda's integration ARN. API Gateway handles request routing; your Lambda handles the Claude call. Keep the API Gateway timeout in sync with your Lambda timeout — API Gateway caps at 29 seconds for REST APIs, which is tight if Claude is generating a long response.

Handling streaming and long responses

Lambda's traditional invocation model buffers the full response before returning, which doesn't play well with Claude's streaming API. If you need token-by-token streaming to the client, use Lambda response streaming (awslambda.streamifyResponse) with a Function URL, or move streaming to a container-based service instead of a classic Lambda function. For most backend integrations — generating a response and writing it to a database, triggering a downstream workflow — the non-streaming pattern above is simpler and sufficient.

Why some teams skip the raw API setup

The pattern above works, but it means you're managing retry logic, rate limit backoff, and API key rotation yourself inside every Lambda function that talks to Claude. SubToAPI turns your existing Claude access into an HTTPS API with scoped sub_live_... keys, so your Lambda function just calls one stable endpoint instead of handling Anthropic auth and versioning directly:

curl https://api.subtoapi.app/v1/messages \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-5","max_tokens":1024,"messages":[{"role":"user","content":"Hello"}]}'

This is useful when multiple Lambda functions or team members need Claude access without sharing a single raw key — you issue separate application keys per function from the dashboard, with usage visible per key. See the quickstart and messages docs for the full request format, or check pricing if you're evaluating it for a team.

FAQ

Does Lambda support Claude's streaming responses out of the box? Not with standard invocation. You need Lambda response streaming with a Function URL, or a separate container/EC2 service, since classic Lambda buffers the full response before returning.

What Lambda timeout should I set for Claude API calls? Start at 30 seconds and increase if you expect long completions or large max_tokens values. Match your API Gateway timeout to the same value to avoid gateway-level cutoffs.

Can I call Claude from Lambda without managing an Anthropic key directly? Yes — tools like SubToAPI let you generate scoped application keys per function or service, so you're not distributing one shared API key across your Lambda functions.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →