Introduction: Direct API Gateway to Step Functions

Welcome to the final lesson of this course on building serverless applications! So far, you have learned how to use AWS Lambda, API Gateway, and Step Functions to create and deploy serverless workflows. In this lesson, we will take your skills a step further by showing you how to use API Gateway to start Step Function executions directly — without needing a Lambda function in between.

This approach can make your applications faster and more cost-effective, since you avoid the extra step and cost of running Lambda just to start a workflow. You will learn how to use mapping templates to control the request and response, validate input, handle errors, and even route to different workflows — all using the Velocity Template Language (VTL).

By the end of this lesson, you will be able to build a robust API that starts Step Function executions with dynamic input and strong validation, all without writing any Lambda code.

Quick Recall: Mapping Templates and Direct Integrations

Before we dive in, let’s quickly remind ourselves what mapping templates are and why they matter.

A mapping template in API Gateway is a way to transform the incoming request or outgoing response. It lets you change the shape of the data, add or remove fields, and even add logic — using a language called Velocity Template Language (VTL).

In previous lessons, you may have seen mapping templates used to format data for Lambda functions. In this lesson, we will use them to talk directly to Step Functions, letting us control exactly how the API request is turned into a Step Function execution.

Generating Unique Execution Names with VTL

When starting a Step Function execution, you often want each execution to have a unique name. This helps you track and manage each workflow run.

Let’s see how to do this using a request mapping template in API Gateway.

First, we use the $util.autoId() function in VTL to generate a random string. We can combine this with a prefix, like "order-", to create a unique execution name.

Here’s how you can set this up in your mapping template:

Explanation:

  • #set($inputRoot = $util.parseJson($input.body)) parses the incoming JSON body so you can access its fields.
  • "name": "order-$util.autoId()" creates a unique execution name like order-abc123xyz.
  • "input": "$util.escapeJavaScript($input.body)" passes the original request body as input to the Step Function.

Example Output:

This ensures every execution has a unique name, which is important for tracking and debugging.

Input Validation in Request Mapping Templates

It’s important to make sure the incoming request has all the required fields before starting a workflow. For example, you might require a customerId in the request body.

You can use VTL’s #if directive to check for required fields and return an error if something is missing.

Here’s how you can add validation to your mapping template:

Explanation:

  • #if(!$inputRoot.customerId || $inputRoot.customerId == "") checks if customerId is missing or empty.
  • If it is, we set the response status to 400 and return an error message.
  • If not, we proceed to start the Step Function execution as before.

Example Output (when customerId is missing):

This helps prevent invalid requests from starting workflows, saving resources and making your API more reliable.

Transforming Step Functions Responses

When the Step Function execution starts, the response from AWS is not always user-friendly. You can use a response mapping template to transform the response and add helpful information.

For example, you might want to include:

  • The execution ARN
  • The execution name
  • A timestamp for when the execution started
  • A status field

Here’s how you can do this in your response mapping template:

Explanation:

  • $inputRoot.executionArn and $inputRoot.name come from the Step Functions response.
  • $util.time.nowISO8601() adds the current timestamp in a standard format.
  • "status": "RUNNING" gives a clear status for the client.

Example Output:

This makes your API responses easier to understand and use.

Error Handling for Step Functions Integration

Sometimes, starting a Step Function execution can fail. For example, the state machine might not exist, or you might try to use a duplicate execution name.

You can handle these errors in your API by mapping them to appropriate HTTP status codes and messages.

Here’s how you can set up error responses in your API Gateway integration:

Explanation:

  • The default response handles successful executions.
  • The 4\d{2} pattern matches client errors (like validation failures) and returns a 400 status.
  • The 5\d{2} pattern matches server errors and returns a 500 status with an error message.

Example Output (for a duplicate execution name):

Example Output (for an internal error):

This makes your API more robust and user-friendly by providing clear error messages.

Dynamic Workflow Routing with Request Templates

Sometimes, you want your API to start different workflows based on a parameter in the request. For example, you might have different workflows for orders, refunds, or inventory updates.

You can read a workflow_type parameter from the request body, validate it, and use it to customize the Step Function input and execution name.

Here’s how you can do this in your request mapping template:

Explanation:

  • We set a default workflowType to "order".
  • If the request includes a valid workflow_type (like "refund" or "inventory"), we use that instead.
  • The execution name and input are customized based on the workflow type.
  • We still validate that customerId is present.

Example Output (for a refund workflow):

Summary And Next Steps

In this lesson, you learned how to use API Gateway’s direct integration with Step Functions to build a flexible, robust API — without needing Lambda functions. You saw how to:

  • Generate unique execution names using VTL
  • Validate input and return helpful error messages
  • Transform Step Functions responses to be more user-friendly
  • Handle errors gracefully with custom status codes and messages
  • Route requests dynamically based on workflow type

You have now reached the end of this course on building serverless applications. Congratulations on making it this far! You are now ready to put these concepts into practice with the hands-on exercises that follow. Great work, and keep building!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal