ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

API Gateway から Step Functions を直接呼び出す方法

この記事を共有する

目次

はじめに

こんにちは、パーソル&サーバーワークスの小竹です。
社内研修でのサーバーレスシステム構築時に、API Gatewayから直接AWS Step Functionsを呼び出す方法を調べたので、本記事にまとめてみました!

構成概要

本構成では、API Gatewayを使用してHTTPリクエストを受け取り、Step Functionsのステートマシンを起動します。
Step Functionsのステートマシンは、Expressワークフローを使用して同期的に実行され、処理結果をAPI Gatewayを通じてクライアントに返すような構成となっています。

スクリーンショット 2025-05-07 191654.png

CloudFormationコード

CloudFormationのサンプルコードを添付しました。
上記、構成図通りのリソースが作成されます。


ここを押すと展開します

AWSTemplateFormatVersion: '2010-09-09'
Description: API Gateway (GET) → Step Functions (Express) with CloudWatch Logs
Resources:
  StepFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/vendedlogs/states/${AWS::StackName}-statemachine"
      RetentionInDays: 7
  StepFunctionsExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "StepFunctions-${AWS::StackName}-role"
      Path: /service-role/
      MaxSessionDuration: 3600
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service: states.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess
        - arn:aws:iam::aws:policy/AmazonS3FullAccess
      Policies:
        - PolicyName: AllowStepFunctionsLogs
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:*
                Resource: "*"
  MyStateMachine:
    Type: AWS::StepFunctions::StateMachine
    DependsOn: StepFunctionLogGroup
    Properties:
      StateMachineName: !Sub "${AWS::StackName}-MyStateMachine"
      StateMachineType: EXPRESS
      RoleArn: !GetAtt StepFunctionsExecutionRole.Arn
      LoggingConfiguration:
        Destinations:
          - CloudWatchLogsLogGroup:
              LogGroupArn: !GetAtt StepFunctionLogGroup.Arn
        IncludeExecutionData: true
        Level: ALL
      DefinitionString: |
        {
          "StartAt": "HelloWorld",
          "States": {
            "HelloWorld": {
              "Type": "Pass",
              "Result": {
                "message": "Hello from Step Functions!"
              },
              "End": true
            }
          }
        }
  # API Gateway 実行ロール(Step Functions実行権限)
  ApiGatewayExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: apigateway.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: AllowStepFunctionsStart
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: states:StartSyncExecution
                Resource: !Ref MyStateMachine
  # API Gateway 本体
  MyApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: StepFunctionsApi
  MyResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      ParentId: !GetAtt MyApi.RootResourceId
      PathPart: start
      RestApiId: !Ref MyApi
  MyMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      HttpMethod: GET
      ResourceId: !Ref MyResource
      RestApiId: !Ref MyApi
      AuthorizationType: NONE
      Integration:
        Type: AWS
        IntegrationHttpMethod: POST
        Uri: !Sub >-
          arn:aws:apigateway:${AWS::Region}:states:action/StartSyncExecution
        Credentials: !GetAtt ApiGatewayExecutionRole.Arn
        RequestTemplates:
          application/json: !Sub |
            #set($data='{"param":"'+$input.params('param')+'"}')
            #set($data=$util.escapeJavaScript($data))
            {
              "input" :"$data",
              "stateMachineArn": "${MyStateMachine}"
            }
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates:
              application/json: "$input.body"
      RequestParameters:
        method.request.querystring.example: false
      MethodResponses:
        - StatusCode: 200
  MyDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: MyMethod
    Properties:
      RestApiId: !Ref MyApi
      StageName: prod
Outputs:
  ApiEndpoint:
    Description: API Endpoint to start Step Functions (GET /start?example=value)
    Value: !Sub "https://${MyApi}.execute-api.${AWS::Region}.amazonaws.com/prod/start?example=value"

構成のポイント

  • Express ワークフローで低レイテンシ処理を実現
  • Lambdaを使わずに API Gateway → Step Functions を直接連携
  • Step Functionsのログを有効化し、ステートマシンの実行内容を可視化
  • StartSyncExecution を使用し、同期的にレスポンスを取得

1. Step Functions(Express)ステートマシン

🧩 構成のポイント: Express ワークフローによる低レイテンシ処理

StateMachineType: EXPRESS を指定することで、ステートマシンはミリ秒単位で実行され、API連携に適した構成になります。 Express型は短時間処理・高頻度呼び出しに最適で、同期実行にも対応しているのが特徴です。
今回のケースでは、DynamoDBクエリ処理など軽量な業務処理が想定されていたため、Express型を採用しました。

StateMachineType: EXPRESS

2. CloudWatch Logsへの出力設定

🧩 構成のポイント: Step Functionsのログを有効化し、ステートマシンの実行内容を可視化

ステートマシンに LoggingConfiguration を追加し、Level: ALLIncludeExecutionData: true を設定することで、各ステップの入力・出力やエラー内容をCloudWatch Logsに出力できます。
デバッグや監視にも役立ちます。

LoggingConfiguration:
  Level: ALL
  IncludeExecutionData: true

3. API Gateway → Step Functions の統合

🧩 構成のポイント: StartSyncExecutionを使い、同期的にレスポンスを取得

API Gateway から Step Functions を直接呼び出すには、統合タイプを AWSIntegrationHttpMethodPOST に設定し、URI に StartSyncExecution を指定します。
これにより、Step Functions の実行が完了するまで待ち、結果を API レスポンスとして返すことができます。

Uri: arn:aws:apigateway:${AWS::Region}:states:action/StartSyncExecution

4. IAMロール(API Gateway用)

🧩 構成のポイント: Lambdaを使わずにAPI GatewayからStep Functionsへ直接連携

API Gateway から Step Functions を呼び出すには、適切な IAM ロールを設定する必要があります。以下のように states:StartSyncExecution を許可します。

Action: states:StartSyncExecution

5. API Gateway 設定(テンプレート)

🧩 構成のポイント: Lambdaを使わずにAPI GatewayからStep Functionsへ直接連携

リクエストテンプレートで、クエリパラメータを JSON に変換し、Step Functions に渡します。
また、マッピングテンプレートは、Velocity Template Language (VTL)という言語で記載する必要があります。

RequestTemplates:
  application/json: |
    #set($data='{"param":"'+$input.params('param')+'"}')
    #set($data=$util.escapeJavaScript($data))
    { 
        "input" :"$data",
        "stateMachineArn": "${MyStateMachine}
    }

「stateMachineArn」にステートマシンのARNを定義することで、対象のステートマシンが実行されるようになります。
また、パラメータを整形することで、クライアントからの入力をそのままStep Functionsに渡せます。

6. 動作確認

API Gatewayからテストを実施

API Gatewayのテストにて、クエリ文字列「param=test」を指定して実行しました。
レスポンス本文にて、inputとoutputが正常に出力されていることを確認できました。

スクリーンショット 2025-05-07 195048.png

Curlコマンドでの動作確認

コマンドプロンプトからもAPI Gatewayのテストと同じ結果が返されることが確認できました。

スクリーンショット 2025-05-07 200300.png

まとめ

API GatewayからStep Functionsを直接呼び出す構成により、Lambdaを挟まずにシンプルなAPIを実現できました。
今回の構成で特に苦労したのは、API Gatewayのマッピングテンプレートの記述です。
Velocity Template Language (VTL)は初めて触れましたが、リクエストやレスポンスの整形に不可欠なため、業務で活用するには基礎からしっかり理解しておく必要があると感じました。

この記事は私が書きました

小竹 巧朗

記事一覧

AWS認定 全冠目指して勉強中です! 趣味はスノボとゴルフです。

小竹 巧朗

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。