diff --git a/stepfunctions-sns-apigw-human-review/APIGateway/ReviewRESTApi.yaml b/stepfunctions-sns-apigw-human-review/APIGateway/ReviewRESTApi.yaml
new file mode 100644
index 000000000..23aa11410
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/APIGateway/ReviewRESTApi.yaml
@@ -0,0 +1,36 @@
+openapi: "3.0.1"
+info:
+ title: "ram-sfn-human-approval"
+ version: "2024-09-27T16:44:01Z"
+paths:
+ /:
+ x-amazon-apigateway-any-method:
+ responses:
+ "200":
+ description: "200 response"
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Empty"
+ x-amazon-apigateway-integration:
+ type: "aws"
+ credentials:
+ Fn::GetAtt: [ReviewRESTApiRole, Arn]
+ httpMethod: "POST"
+ uri: "arn:aws:apigateway:${AWS::Region}:states:action/SendTaskSuccess"
+ responses:
+ default:
+ statusCode: "200"
+ responseTemplates:
+ application/json: "{\n \"Expense report status\" : \"$util.escapeJavaScript($input.params('Type'))\"\
+ \n}"
+ requestTemplates:
+ application/json: "{\n \"output\": \"{\\\"Result\\\": \\\"$util.escapeJavaScript($input.params('Type'))\\\
+ \"}\",\n \"taskToken\": \"$util.base64Decode($util.escapeJavaScript($input.params('Token')))\"\
+ \n}"
+ passthroughBehavior: "when_no_templates"
+components:
+ schemas:
+ Empty:
+ title: "Empty Schema"
+ type: "object"
\ No newline at end of file
diff --git a/stepfunctions-sns-apigw-human-review/README.md b/stepfunctions-sns-apigw-human-review/README.md
new file mode 100644
index 000000000..24b9b942a
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/README.md
@@ -0,0 +1,72 @@
+# Filter and Transform Amazon SQS messages with Amazon EventBridge Pipes
+
+The application will create a Amazon Step Functions State Machine, an Amazon SNS topic, and an Amazon API Gateway REST API. This pattern allows you to integrate a human review or approval process into your workflows. The State Machine task sends a message to an SNS topic which sends a notification to a human reviewer by email. The workflow then waits until the approver completes their review. When the reviewer makes a selection, it will trigger an API that sends the `SendTaskSuccess` [API](https://docs.aws.amazon.com/step-functions/latest/apireference/API_SendTaskSuccess.html) or or `SendTaskFailure` [API](https://docs.aws.amazon.com/step-functions/latest/apireference/API_SendTaskFailure.html) call with the chosen result.
+This pattern is implemented with AWS Serverless Application Model (AWS SAM).
+
+Learn more about this pattern at Serverless Land Patterns: https://serverlessland.com/patterns/stepfunctions-sns-apigw-human-review
+
+Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
+
+## Requirements
+
+- [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
+- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
+- [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+- [AWS SAM](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) installed and configured
+
+## Deployment Instructions
+
+1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
+ ```
+ git clone https://github.com/aws-samples/serverless-patterns
+ ```
+2. Change directory to the pattern directory:
+ ```
+ cd serverless-patterns/stepfunctions-sns-apigw-human-review/
+ ```
+3. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yaml file:
+ ```
+ sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM
+ ```
+4. During the prompts:
+ * Enter a stack name
+ * Enter `us-east-1` or any other AWS Region.
+ * Enter an email address that should receive the notifications from the workflow.
+ * Allow SAM CLI to create IAM roles with the required permissions. Please keep all other options to default.
+
+Once you have run `sam deploy --guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults.
+
+## How it works
+
+![image](./Resources/statemachine.png)
+
+1. During the workflow execution, a message is sent to an [Amazon Simple Notification Service (SNS)](https://aws.amazon.com/sns/) topic which sends out a notification via Email. The notification contains links to `Approve` or `Reject` the request. The link contains an API Gateway endpoint with [task token](https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token), which is automatically generated by AWS Step Functions.
+2. After approving or denying, the reviewer calls the `SendTaskSuccess` API and passes the task token as well as the review result.
+3. The Step Function assesses the outcome and moves the workflow to the next task.
+
+## Testing
+
+1. After deployment you receive an email titled `AWS Notification - Subscription Confirmation`. To confirm your subscription, click on the link provided in the email. This will allow SNS to send you emails.
+2. Navigate to the AWS Step Functions console and select the step function workflow.
+3. Select `Start Execution` and use the JSON payload listed below as input.
+ ```
+ {
+ "expense": 900
+ }
+ ```
+4. Select `Start Execution` and wait until you receive the email from SNS.
+5. Select the review response as `Approve`.
+6. Observe the task in the Step Functions console. Since the response confirms the approval, the task moved to the `Request Approved` step.
+7. If you trigger a new execution and select the review response as `Decline` in step 6, the workflow transitions to `Request Rejected` step.
+
+## Delete stack
+
+```
+sam delete
+```
+
+---
+
+Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: MIT-0
diff --git a/stepfunctions-sns-apigw-human-review/Resources/statemachine.png b/stepfunctions-sns-apigw-human-review/Resources/statemachine.png
new file mode 100644
index 000000000..fae555d54
Binary files /dev/null and b/stepfunctions-sns-apigw-human-review/Resources/statemachine.png differ
diff --git a/stepfunctions-sns-apigw-human-review/StepFunction/step-function-definition.json b/stepfunctions-sns-apigw-human-review/StepFunction/step-function-definition.json
new file mode 100644
index 000000000..5f1706f1d
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/StepFunction/step-function-definition.json
@@ -0,0 +1,47 @@
+{
+ "Comment": "A description of my state machine",
+ "StartAt": "Total Expenses >= $500",
+ "States": {
+ "Total Expenses >= $500": {
+ "Type": "Choice",
+ "Choices": [
+ {
+ "Variable": "$.expense",
+ "NumericLessThan": 500,
+ "Next": "Auto approved"
+ }
+ ],
+ "Default": "Get human approval"
+ },
+ "Auto approved": {
+ "Type": "Succeed"
+ },
+ "Get human approval": {
+ "Type": "Task",
+ "Resource": "arn:aws:states:::sns:publish.waitForTaskToken",
+ "Parameters": {
+ "TopicArn": "${TopicArn}",
+ "Message.$": "States.Format('Please review \n\nApprove: \"${ApiEndpoint}?Type=Approved&Token={}\" \n\nDecline: \"${ApiEndpoint}?Type=Rejected&Token={}\"',States.Base64Encode($$.Task.Token), States.Base64Encode($$.Task.Token))",
+ "Subject": "Expense Approval"
+ },
+ "Next": "Approval/Decline"
+ },
+ "Approval/Decline": {
+ "Type": "Choice",
+ "Choices": [
+ {
+ "Variable": "$.Result",
+ "StringEquals": "Approved",
+ "Next": "Request Approved"
+ }
+ ],
+ "Default": "Request Rejected"
+ },
+ "Request Approved": {
+ "Type": "Succeed"
+ },
+ "Request Rejected": {
+ "Type": "Fail"
+ }
+ }
+}
\ No newline at end of file
diff --git a/stepfunctions-sns-apigw-human-review/example-pattern.json b/stepfunctions-sns-apigw-human-review/example-pattern.json
new file mode 100644
index 000000000..06fe937dc
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/example-pattern.json
@@ -0,0 +1,75 @@
+{
+ "title": "Human review process using Amazon Step Functions.",
+ "description": "Integrate a human review process into your workflow.",
+ "language": "",
+ "level": "200",
+ "framework": "SAM",
+ "diagram":"/resources/statemachine.png",
+ "introBox": {
+ "headline": "How it works",
+ "text": [
+ "This application will create a State Machine, an SNS topic, and an API Gateway REST API.",
+ "The State Machine sends a message to an SNS topic which sends a notification to a human reviewer by email. The workflow then waits until the approver completes their review. When the reviewer makes a selection, it will trigger an API that sends the SendTaskSuccess API call with the chosen result.",
+ "Waiting for completion of the review is done using the .waitForTaskToken service integration. The payload of the SNS message contains a task token, which is automatically generated by AWS Step Functions.",
+ "The task will pause until it receives that task token back with a SendTaskSuccess or SendTaskFailure API call."
+
+ ]
+ },
+ "gitHub": {
+ "template": {
+ "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/stepfunctions-sns-apigw-human-review",
+ "templateURL": "serverless-patterns/stepfunctions-sns-apigw-human-review",
+ "projectFolder": "stepfunctions-sns-apigw-human-review",
+ "templateFile": "template.yaml"
+ }
+ },
+ "resources": {
+ "bullets": [
+ {
+ "text": "Discover service integration patterns in Step Functions",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html"
+ },
+ {
+ "text": "Wait for a Callback with Task Token",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token"
+ },
+ {
+ "text": "Calling a Step Functions API using API Gateway",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-api-gateway.html"
+ },
+ {
+ "text": "Intrinsic functions in Amazon States Language for Step Functions workflows",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/intrinsic-functions.html"
+ }
+ ]
+ },
+ "deploy": {
+ "text": [
+ "sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM"
+ ]
+ },
+ "testing": {
+ "text": [
+ "See the GitHub repo for detailed testing instructions."
+ ]
+ },
+ "cleanup": {
+ "text": [
+ "Delete the stack: sam delete
."
+ ]
+ },
+ "authors": [
+ {
+ "name": "Sridhar Chevendra",
+ "image": "https://media.licdn.com/dms/image/v2/C4E03AQFpArv6Yxt3pQ/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1517698219415?e=1733356800&v=beta&t=ehp9uqF0PKEz2aNMjv-VGD7koJqfm_wcm7VsFwJaaPY",
+ "bio":"Sridhar uses customer-centric approach to build secure and scalable cloud architectures.",
+ "linkedin": "https://www.linkedin.com/in/sridhar-chevendra-92a7916/"
+ },
+ {
+ "name": "Anup Rajpara",
+ "image": "https://drive.google.com/file/d/1MqpPNLCqbU4kvvtTspNXZBqD99aVIJI9/view?usp=sharing",
+ "bio":"Anup is passionate about serverless & event-driven architectures.",
+ "linkedin": "https://www.linkedin.com/in/anup-rajpara-developer/"
+ }
+ ]
+}
diff --git a/stepfunctions-sns-apigw-human-review/stepfunctions-sns-apigw-human-review.json b/stepfunctions-sns-apigw-human-review/stepfunctions-sns-apigw-human-review.json
new file mode 100644
index 000000000..90652323a
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/stepfunctions-sns-apigw-human-review.json
@@ -0,0 +1,104 @@
+{
+ "title": "Human review process using Amazon Step Functions.",
+ "description": "Integrate a human review process into your workflow.",
+ "language": "",
+ "level": "200",
+ "framework": "SAM",
+ "diagram": "/resources/statemachine.png",
+ "introBox": {
+ "headline": "How it works",
+ "text": [
+ "The application will create a Amazon Step Functions State Machine, an Amazon SNS topic, and an Amazon API Gateway REST API.",
+ "The State Machine sends a message to an SNS topic which sends a notification to a human reviewer by email. The workflow then waits until the approver completes their review. When the reviewer makes a selection, it will trigger an API that sends the SendTaskSuccess API call with the chosen result.",
+ "Waiting for completion of the review is done using the .waitForTaskToken service integration. The payload of the SNS message contains a task token, which is automatically generated by AWS Step Functions.",
+ "The task will pause until it receives that task token back with a SendTaskSuccess or SendTaskFailure API call."
+ ]
+ },
+ "gitHub": {
+ "template": {
+ "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/stepfunctions-sns-apigw-human-review",
+ "templateURL": "serverless-patterns/stepfunctions-sns-apigw-human-review",
+ "projectFolder": "stepfunctions-sns-apigw-human-review",
+ "templateFile": "template.yaml"
+ }
+ },
+ "resources": {
+ "bullets": [
+ {
+ "text": "Discover service integration patterns in Step Functions",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html"
+ },
+ {
+ "text": "Wait for a Callback with Task Token",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/connect-to-resource.html#connect-wait-token"
+ },
+ {
+ "text": "Calling a Step Functions API using API Gateway",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-api-gateway.html"
+ },
+ {
+ "text": "Intrinsic functions in Amazon States Language for Step Functions workflows",
+ "link": "https://docs.aws.amazon.com/step-functions/latest/dg/intrinsic-functions.html"
+ }
+ ]
+ },
+ "deploy": {
+ "text": [
+ "sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM"
+ ]
+ },
+ "testing": {
+ "text": [
+ "See the GitHub repo for detailed testing instructions."
+ ]
+ },
+ "cleanup": {
+ "text": [
+ "Delete the stack: sam delete
."
+ ]
+ },
+ "authors": [
+ {
+ "name": "Sridhar Chevendra",
+ "image": "https://media.licdn.com/dms/image/v2/C4E03AQFpArv6Yxt3pQ/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1517698219415?e=1733356800&v=beta&t=ehp9uqF0PKEz2aNMjv-VGD7koJqfm_wcm7VsFwJaaPY",
+ "bio": "Sridhar uses customer-centric approach to build secure and scalable cloud architectures.",
+ "linkedin": "sridhar-chevendra-92a7916/"
+ },
+ {
+ "name": "Anup Rajpara",
+ "image": "https://drive.google.com/file/d/1MqpPNLCqbU4kvvtTspNXZBqD99aVIJI9/view?usp=sharing",
+ "bio": "Anup is passionate about serverless & event-driven architectures.",
+ "linkedin": "anup-rajpara-developer/"
+ }
+ ],
+ "patternArch": {
+ "icon1": {
+ "x": 20,
+ "y": 50,
+ "service": "apigw",
+ "label": "API Gateway REST API"
+ },
+ "icon2": {
+ "x": 50,
+ "y": 50,
+ "service": "sfn",
+ "label": "Amazon Step Function"
+ },
+ "icon3": {
+ "x": 80,
+ "y": 50,
+ "service": "sns",
+ "label": "Amazon SNS"
+ },
+ "line1": {
+ "from": "icon1",
+ "to": "icon2",
+ "label": ""
+ },
+ "line2": {
+ "from": "icon2",
+ "to": "icon3",
+ "label": ""
+ }
+ }
+}
diff --git a/stepfunctions-sns-apigw-human-review/template.yaml b/stepfunctions-sns-apigw-human-review/template.yaml
new file mode 100644
index 000000000..d9ddb7f6d
--- /dev/null
+++ b/stepfunctions-sns-apigw-human-review/template.yaml
@@ -0,0 +1,91 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: Sample SAM template to deploy a simplified workflow that waits for human approval in Step Functions.
+
+Parameters:
+ ApproverEmailAddress:
+ Description: Enter the email address that will receive review notifications.
+ Type: String
+
+Resources:
+ SNSNotificationTopic:
+ Type: AWS::SNS::Topic
+ Properties:
+ DisplayName: !Sub ${AWS::StackName}-sns-topic
+ TopicName: !Sub ${AWS::StackName}-sns-topic
+ Subscription:
+ - Endpoint: !Ref ApproverEmailAddress
+ Protocol: "email"
+ Metadata:
+ SamResourceId: SNSNotificationTopic
+
+ ReviewRESTApiRole:
+ Type: AWS::IAM::Role
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service:
+ - apigateway.amazonaws.com
+ Action:
+ - sts:AssumeRole
+ Policies:
+ - PolicyName: !Sub ${AWS::StackName}-sfn-permissions
+ PolicyDocument:
+ Version: 2012-10-17
+ Statement:
+ - Effect: Allow
+ Action:
+ - states:SendTaskSuccess
+ Resource: "*"
+ Metadata:
+ SamResourceId: ReviewRESTApiRole
+
+ ReviewRESTApi:
+ Type: AWS::Serverless::Api
+ Properties:
+ StageName: Prod
+ DefinitionBody:
+ Fn::Transform:
+ Name: AWS::Include
+ Parameters:
+ Location: ./APIGateway/ReviewRESTApi.yaml
+ Metadata:
+ SamResourceId: ReviewRESTApi
+
+ ReviewSfnRole:
+ Type: AWS::IAM::Role
+ Properties:
+ RoleName: !Sub ${AWS::StackName}-review-sfn-role
+ AssumeRolePolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service: states.amazonaws.com
+ Action: sts:AssumeRole
+ Policies:
+ - PolicyName: !Sub ${AWS::StackName}-review-sfn-policy
+ PolicyDocument:
+ Version: "2012-10-17"
+ Statement:
+ - Effect: Allow
+ Action:
+ - sns:Publish
+ Resource: !GetAtt SNSNotificationTopic.TopicArn
+ Metadata:
+ SamResourceId: ReviewSfnRole
+
+ ReviewStateMachine:
+ Type: AWS::Serverless::StateMachine
+ Properties:
+ DefinitionUri: "./StepFunction/step-function-definition.json"
+ DefinitionSubstitutions:
+ TopicArn: !GetAtt SNSNotificationTopic.TopicArn
+ ApiEndpoint: !Sub https://${ReviewRESTApi}.execute-api.${AWS::Region}.amazonaws.com/Prod
+ Role: !GetAtt ReviewSfnRole.Arn
+ Metadata:
+ SamResourceId: "ReviewStateMachine"
+