Use Cases

Claude Code × AWS API Gateway Guía Completa | Diseño REST API hasta Automatización de Despliegue

Automatiza el diseño de endpoints de AWS API Gateway con Claude Code. Diseño de recursos, integración Lambda, autenticación y despliegue — con código real de la experiencia profesional de Masa.

Cómo el tiempo de diseño de API Gateway se redujo a un tercio

Soy Masa, administro claudecode-lab.com. Cuando trabajaba como desarrollador backend freelance, el diseño e implementación de AWS API Gateway encabezaba la lista de “tareas tediosas y que consumen tiempo”. Escribir documentos de especificación de endpoints, traducirlos a CloudFormation, conectar integraciones Lambda manualmente, configurar CORS — y cometer los mismos errores una y otra vez.

El punto de inflexión llegó hace unos seis meses, cuando pedí a Claude Code: “Diseña una REST API basada en este caso de uso e impleméntala en CDK.” El resultado fue sorprendentemente listo para producción, y desde entonces el tiempo de implementación de API Gateway se ha reducido a un tercio.

Errores de CORS, errores de permisos de Lambda, la trampa del timeout de 29 segundos — desde que Claude Code detecta estos problemas con anticipación, los hallazgos de revisión también han caído drásticamente.


Por qué Claude Code destaca en el diseño de API Gateway

El diseño de API Gateway tiene una característica distintiva: no requiere conocimientos profundos, pero implica mucho boilerplate repetitivo.

  • Convenciones de nomenclatura de endpoints (sustantivos en plural, estructura jerárquica)
  • Selección de métodos HTTP (GET/POST/PUT/PATCH/DELETE)
  • Definiciones de esquemas de request/response
  • Mapeo de variables de ruta en integración Lambda
  • Configuración de encabezados CORS (siempre olvidando algo)
  • Gestión de variables de stage (dev/staging/prod)

Paso 1: Delegando el diseño de endpoints REST API a Claude Code

Ejemplo de Prompt

Crea una especificación de endpoints de REST API basada en los siguientes casos de uso.

Casos de uso:
- App de gestión de tareas (usuarios gestionan proyectos y tareas)
- Autenticación de usuario requerida (Cognito)
- Los proyectos pueden tener miembros
- Las tareas soportan comentarios y archivos adjuntos

Formato de salida:
- Lista de endpoints (método, ruta, descripción)
- Esquemas JSON de request/response
- Marcar endpoints que requieren autenticación
- Señalar violaciones de principios REST

Paso 2: Auto-generando configuración de integración Lambda

Stack CDK generado (extracto)

import * as cdk from "aws-cdk-lib";
import * as apigateway from "aws-cdk-lib/aws-apigateway";
import * as nodejs from "aws-cdk-lib/aws-lambda-nodejs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import { Construct } from "constructs";

export class TaskApiStack extends cdk.Stack {
  public readonly api: apigateway.RestApi;

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // ===== Factory de funciones Lambda =====
    const createLambda = (name: string, handler: string) =>
      new nodejs.NodejsFunction(this, name, {
        entry: `src/handlers/${handler}.ts`,
        handler: "handler",
        runtime: lambda.Runtime.NODEJS_20_X,
        timeout: cdk.Duration.seconds(29), // Timeout máximo de API Gateway
        memorySize: 256,
        bundling: {
          minify: true,
          sourceMap: true,
          externalModules: ["@aws-sdk/*"],
        },
      });

    const listProjectsFn = createLambda("ListProjects", "projects/list");
    const createProjectFn = createLambda("CreateProject", "projects/create");
    const getProjectFn = createLambda("GetProject", "projects/get");
    const updateProjectFn = createLambda("UpdateProject", "projects/update");
    const deleteProjectFn = createLambda("DeleteProject", "projects/delete");

    // ===== Definición de REST API =====
    this.api = new apigateway.RestApi(this, "TaskApi", {
      restApiName: "task-management-api",
      defaultCorsPreflightOptions: {
        allowOrigins: apigateway.Cors.ALL_ORIGINS, // restringir en producción
        allowMethods: apigateway.Cors.ALL_METHODS,
        allowHeaders: ["Content-Type", "Authorization", "X-Api-Key"],
      },
      deployOptions: {
        stageName: "v1",
        loggingLevel: apigateway.MethodLoggingLevel.INFO,
        dataTraceEnabled: false,
      },
    });

    // ===== Recursos y métodos =====
    const projects = this.api.root.addResource("projects");
    projects.addMethod("GET", new apigateway.LambdaIntegration(listProjectsFn));
    projects.addMethod("POST", new apigateway.LambdaIntegration(createProjectFn));

    const project = projects.addResource("{id}");
    project.addMethod("GET", new apigateway.LambdaIntegration(getProjectFn));
    project.addMethod("PUT", new apigateway.LambdaIntegration(updateProjectFn));
    project.addMethod("DELETE", new apigateway.LambdaIntegration(deleteProjectFn));

    new cdk.CfnOutput(this, "ApiUrl", {
      value: this.api.url,
      description: "URL de API Gateway",
    });
  }
}

Paso 3: Autenticación (Cognito / Lambda Authorizer / API Key)

Patrón 1: Cognito User Pool Authorizer (BtoC)

import * as cognito from "aws-cdk-lib/aws-cognito";

const userPool = new cognito.UserPool(this, "UserPool", {
  userPoolName: "task-app-users",
  selfSignUpEnabled: true,
  signInAliases: { email: true },
  passwordPolicy: {
    minLength: 8,
    requireLowercase: true,
    requireUppercase: true,
    requireDigits: true,
  },
});

const cognitoAuthorizer = new apigateway.CognitoUserPoolsAuthorizer(
  this,
  "CognitoAuthorizer",
  {
    cognitoUserPools: [userPool],
    identitySource: "method.request.header.Authorization",
    resultsCacheTtl: cdk.Duration.minutes(5),
  }
);

projects.addMethod("GET", new apigateway.LambdaIntegration(listProjectsFn), {
  authorizer: cognitoAuthorizer,
  authorizationType: apigateway.AuthorizationType.COGNITO,
});

Patrón 2: Lambda Authorizer

// src/handlers/auth/authorizer.ts
import {
  APIGatewayAuthorizerResult,
  APIGatewayTokenAuthorizerHandler,
} from "aws-lambda";
import * as jwt from "jsonwebtoken";

export const handler: APIGatewayTokenAuthorizerHandler = async (event) => {
  const token = event.authorizationToken.replace("Bearer ", "");

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!) as {
      sub: string;
      email: string;
      role: string;
    };

    return generatePolicy(decoded.sub, "Allow", event.methodArn, {
      userId: decoded.sub,
      email: decoded.email,
      role: decoded.role,
    });
  } catch {
    throw new Error("Unauthorized");
  }
};

function generatePolicy(
  principalId: string,
  effect: "Allow" | "Deny",
  resource: string,
  context?: Record<string, string>
): APIGatewayAuthorizerResult {
  return {
    principalId,
    policyDocument: {
      Version: "2012-10-17",
      Statement: [
        {
          Action: "execute-api:Invoke",
          Effect: effect,
          Resource: resource.replace(/\/[^/]+\/[^/]+$/, "/*/*"),
        },
      ],
    },
    context,
  };
}

Paso 4: Gestión de Stages (dev/staging/prod)

// lib/config.ts
export type Stage = "dev" | "staging" | "prod";

export const stageConfig: Record<Stage, {
  throttleRateLimit: number;
  corsOrigins: string[];
  enableDataTrace: boolean;
}> = {
  dev: {
    throttleRateLimit: 10,
    corsOrigins: ["http://localhost:3000"],
    enableDataTrace: true,
  },
  staging: {
    throttleRateLimit: 50,
    corsOrigins: ["https://staging.example.com"],
    enableDataTrace: false,
  },
  prod: {
    throttleRateLimit: 1000,
    corsOrigins: ["https://example.com"],
    enableDataTrace: false,
  },
};
# Desplegar a desarrollo
CDK_ENV=dev npx cdk deploy Api-dev --require-approval never

# Staging
CDK_ENV=staging npx cdk deploy Api-staging

# Producción (con confirmación)
CDK_ENV=prod npx cdk deploy Api-prod

4 Errores Comunes

Error 1: Configuración CORS faltante (el más frecuente)

Síntoma: fetch() en el navegador lanza error CORS. Postman funciona bien.

// ❌ Insuficiente
defaultCorsPreflightOptions: {
  allowOrigins: apigateway.Cors.ALL_ORIGINS,
}

// ✅ Siempre agregar encabezados CORS en respuestas Lambda
return {
  statusCode: 200,
  headers: {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "https://example.com",
    "Access-Control-Allow-Credentials": "true",
  },
  body: JSON.stringify(data),
};

Error 2: Permiso de invocación Lambda faltante

listProjectsFn.addPermission("ApiGatewayInvoke", {
  principal: new iam.ServicePrincipal("apigateway.amazonaws.com"),
  sourceArn: this.api.arnForExecuteApi("GET", "/projects", "v1"),
});

Error 3: El límite de timeout de 29 segundos

// ✅ Patrón asíncrono: devolver job ID inmediatamente
export const startExport: APIGatewayProxyHandler = async (event) => {
  const jobId = crypto.randomUUID();

  await sqsClient.send(
    new SendMessageCommand({
      QueueUrl: process.env.JOB_QUEUE_URL!,
      MessageBody: JSON.stringify({ jobId, params: JSON.parse(event.body!) }),
    })
  );

  return {
    statusCode: 202,
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jobId, status: "processing" }),
  };
};

Error 4: Cuerpo de request faltante en Lambda

// ✅ Siempre establecer proxy: true explícitamente
project.addMethod(
  "POST",
  new apigateway.LambdaIntegration(createProjectFn, {
    proxy: true,
  })
);

Resumen

TareaValor de Claude CodeDificultad
Diseño REST APIAuto-generar specs, verificar principios RESTBaja
Lambda Integration CDKGenerar integración proxy + definiciones de recursosBaja
Auth CognitoGenerar User Pool, Authorizer, config de clienteMedia
Lambda AuthorizerImplementar validación JWT + generación de policyMedia
Gestión de stagesSeparar configs de env, generar comandos de despliegueMedia
Procesamiento asíncronoDiseñar integración SQS + patrón de pollingAlta

Resultado práctico: tiempo de diseño API Gateway-to-CDK-deploy reducido de 3 días a 1 día. La configuración de Cognito Authorizer, que antes requería más de una hora leyendo documentación de AWS, ahora se resuelve con un único prompt de Claude Code.


Artículos Relacionados

Referencias

#claude-code #aws #api-gateway #lambda #typescript #rest-api

Lleva tu flujo con Claude Code al siguiente nivel

50 plantillas de prompts probadas en producción, listas para copiar y pegar en Claude Code.

Gratis

PDF gratuito: Hoja de trucos de Claude Code en 5 minutos

Solo deja tu correo y te enviaremos al instante la hoja de trucos en una página A4.

Cuidamos tus datos personales y nunca enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero apasionado por Claude Code. Dirige claudecode-lab.com, un medio tecnológico en 10 idiomas con más de 2.000 páginas.