AWS Health イベントを何かしらのデータベースで管理されている方は多いと思います。
今回はイベントが発生したらNotionのデータベースに登録する仕組みをAWS Step Functionsで実装してみました。
やること
以下の構成図の通りですが、AWS Health イベントをAmazon EventBridgeで検知してStep Functions経由でNotionのデータベースに登録を行います。
NotionのAPIキーはSSM Parameter Storeに登録します。

設定
Notionにデータベースを作る
内容は以下のようになっています。
| 名前 | ステータス | 担当者 | 通知日付 | 期日 |
|---|---|---|---|---|
| タイトル | ステータス | ユーザー | 日付 | 日付 |
Notion API設定
コネクト作成後、アクセストークンをコピーした後に、右上の「・・・」から接続をクリックして作成したコネクトを選択します。

アクセストークンを使用して以下のcurlコマンドでデータベースの取得とデータの登録をしてみます。
ユーザーIDは適当なページを一つ作成してそこにメンションをつけてメッセージを取得すれば確認ができます。(ほかにスマートなやり方がある気がしますが...)
# データベース取得
curl --request GET \
--url https://api.notion.com/v1/databases/データベースID \
--header 'Authorization: Bearer トークン' \
--header 'Notion-Version: 2026-03-11'
# データベースにデータ追加
curl -X POST "https://api.notion.com/v1/pages" \
-H "Authorization: Bearer トークン" \
-H "Notion-Version: 2026-03-11" \
-H "Content-Type: application/json" \
--data '{
"parent": {
"type": "data_source_id",
"data_source_id": "'"データソースID (上記のcurlのレスポンスに含まれています)"'"
},
"properties": {
"名前": {
"title": [
{
"type": "text",
"text": {
"content": "APIから登録したタスク"
}
}
]
},
"ステータス": {
"status": {
"name": "未着手"
}
},
"通知日付": {
"date": {
"start": "2026-06-26"
}
},
"期日": {
"date": {
"start": "2026-06-27"
}
}
}
}'
# ページ内にメッセージを登録する
curl -X PATCH "https://api.notion.com/v1/blocks/ページID (上記コマンドのレスポンスに含まれています)/children" \
-H "Authorization: Bearer トークン" \
-H "Notion-Version: 2026-03-11" \
-H "Content-Type: application/json" \
--data '{
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"type": "text",
"text": {
"content": "テストメッセージ"
}
}
]
}
}
]
}'
# ユーザーID確認 (適当なページで自分にメンションをした後に以下のコマンドを実行してレスポンスに含まれるmentionからIDが確認できます)
curl --request GET \
--url "https://api.notion.com/v1/blocks/ページID/children" \
--header 'Authorization: Bearer トークン' \
--header 'Notion-Version: 2026-03-11'
上記の実行に成功すると以下のようにデータベースに登録されていることが確認できます。
AWSリソース作成
API経由での登録ができたらAWSリソースの作成を行っていきます。
今回はkiro-cliを使用してTerraformで作成しました。
Terraformのコードは以下に配置しています。
中身は以下のようになっており、必要なものだけを最低限作成しています。
.
├── README.md
├── eventbridge.tf
├── iam.tf
├── outputs.tf
├── ssm.tf
├── step_functions.tf
├── terraform.tfvars
├── variables.tf
└── versions.tf
eventbridge.tfではEventBridgeルールを作成しており、AWSHealthイベントをすべてキャッチするように以下のルールを設定しています。
ちなみにイベントスキーマのサンプルは以下のドキュメントに記載されています。
{
"detail-type": ["AWS Health Event"],
"source": ["aws.health"]
}
ssm.tfではデータソースIDやNotionのトークンなどを登録するパラメータストアを作成しています。
トークンだけSecureStringにしました。
locals {
ssm_prefix = trimprefix(var.prefix, "aws-")
}
resource "aws_ssm_parameter" "notion_api_token" {
name = "/${local.ssm_prefix}/notion-api-token"
description = "Notion API integration token"
type = "SecureString"
value = var.notion_api_token
}
resource "aws_ssm_parameter" "notion_datasource_id" {
name = "/${local.ssm_prefix}/notion-datasource-id"
description = "Notion datasource ID for health events"
type = "String"
value = var.notion_datasource_id
}
resource "aws_ssm_parameter" "notion_user_id" {
name = "/${local.ssm_prefix}/notion-user-id"
description = "Notion user ID to mention in page content"
type = "String"
value = var.notion_user_id
}
step_functions.tfではStepFunctionsを作成しており、ステップとしては4つになります。
1つ目と2つ目がSSMパラメータストアからNotion API実行に必要なID (データソースID、ユーザーID) をとってきています。
3つ目が、Notionのページを作成しており、ここでNotionの各プロパティを入力しています。
4つ目が、3つ目で作成したページ内にAWS HealthイベントのJSONを登録する部分です。
3~4についてはEventBridgeのEventBridge Connectionを使用してNotionのAPIを実行しています。
# EventBridge Connection for Notion API auth (API Key: Bearer token)
resource "aws_cloudwatch_event_connection" "notion" {
name = "${var.prefix}-notion-connection"
authorization_type = "API_KEY"
auth_parameters {
api_key {
key = "Authorization"
value = "Bearer ${var.notion_api_token}"
}
}
}
resource "aws_cloudwatch_log_group" "sfn" {
name = "/aws/states/${var.prefix}"
retention_in_days = 14
}
resource "aws_sfn_state_machine" "health_to_notion" {
name = "${var.prefix}-state-machine"
role_arn = aws_iam_role.sfn.arn
definition = jsonencode({
Comment = "Record AWS Health events to Notion datasource"
QueryLanguage = "JSONata"
StartAt = "GetNotionDataSourceId"
States = {
GetNotionDataSourceId = {
Type = "Task"
Resource = "arn:aws:states:::aws-sdk:ssm:getParameter"
Arguments = {
Name = aws_ssm_parameter.notion_datasource_id.name
WithDecryption = false
}
Output = {
"data_source_id" = "{% $states.result.Parameter.Value %}"
"event" = "{% $states.input %}"
}
Next = "GetNotionUserId"
}
GetNotionUserId = {
Type = "Task"
Resource = "arn:aws:states:::aws-sdk:ssm:getParameter"
Arguments = {
Name = aws_ssm_parameter.notion_user_id.name
WithDecryption = false
}
Output = {
"data_source_id" = "{% $states.input.data_source_id %}"
"user_id" = "{% $states.result.Parameter.Value %}"
"event" = "{% $states.input.event %}"
}
Next = "CreateNotionPage"
}
CreateNotionPage = {
Type = "Task"
Resource = "arn:aws:states:::http:invoke"
Arguments = {
ApiEndpoint = "https://api.notion.com/v1/pages"
Method = "POST"
Authentication = {
ConnectionArn = aws_cloudwatch_event_connection.notion.arn
}
Headers = {
"Content-Type" = "application/json"
"Notion-Version" = "2026-03-11"
}
RequestBody = {
parent = {
type = "data_source_id"
"data_source_id" = "{% $states.input.data_source_id %}"
}
properties = {
"名前" = {
title = [{
type = "text"
text = {
"content" = "{% '[' & $states.input.event.detail.service & '] ' & $states.input.event.detail.eventTypeCode %}"
}
}]
}
"通知日付" = {
date = {
"start" = "{% $states.input.event.time %}"
}
}
"ステータス" = {
status = {
name = "未着手"
}
}
"担当者" = {
people = "{% $parse($states.input.user_id) %}"
}
}
}
}
Output = {
"page_id" = "{% $states.result.ResponseBody.id %}"
"data_source_id" = "{% $states.input.data_source_id %}"
"user_id" = "{% $states.input.user_id %}"
"event" = "{% $states.input.event %}"
}
Next = "AddNotionPageContent"
Retry = [{
ErrorEquals = [
"States.HTTPErrorStatusCode500",
"States.HTTPErrorStatusCode502",
"States.HTTPErrorStatusCode503",
"States.HTTPErrorStatusCode504",
"States.HTTPErrorStatusCode429",
]
IntervalSeconds = 5
MaxAttempts = 3
BackoffRate = 2
JitterStrategy = "FULL"
}]
}
AddNotionPageContent = {
Type = "Task"
Resource = "arn:aws:states:::http:invoke"
Arguments = {
ApiEndpoint = "{% 'https://api.notion.com/v1/blocks/' & $states.input.page_id & '/children' %}"
Method = "PATCH"
Authentication = {
ConnectionArn = aws_cloudwatch_event_connection.notion.arn
}
Headers = {
"Content-Type" = "application/json"
"Notion-Version" = "2026-03-11"
}
RequestBody = {
children = [{
object = "block"
type = "code"
code = {
language = "json"
rich_text = [{
type = "text"
text = {
"content" = "{% $string($states.input.event, true) %}"
}
}]
}
}]
}
}
End = true
Retry = [{
ErrorEquals = [
"States.HTTPErrorStatusCode500",
"States.HTTPErrorStatusCode502",
"States.HTTPErrorStatusCode503",
"States.HTTPErrorStatusCode504",
"States.HTTPErrorStatusCode429",
]
IntervalSeconds = 5
MaxAttempts = 3
BackoffRate = 2
JitterStrategy = "FULL"
}]
}
}
})
logging_configuration {
log_destination = "${aws_cloudwatch_log_group.sfn.arn}:*"
include_execution_data = true
level = "ERROR"
}
}
terraform.tfvarsは以下のようにしてファイル保存してください。
notion_user_idは複数人登録できるようにリスト構造にしています。
notion_api_token = "トークン"
notion_datasource_id = "データソースID"
notion_user_id = "[{\"id\":\"ユーザーID\"}]"
Terraformコードの準備ができたら以下のコマンドでデプロイしてください。
terraform init
terraform apply
テスト
AWSリソースの作成が完了したら、Step Functionsの画面からサンプルイベントでテスト実行してみます。
AWSサポートの有料プランを契約している場合、Healthイベントのサンプル実行を依頼することができるのですが、今回は手短に確認したかったので、とりあえずStep Functionsの画面から実行しています。
サンプルイベントはAWSのドキュメントに記載されているJSONを使ってみます。
{
"version": "0",
"id": "7bf73129-1428-4cd3-a780-95db273d1602",
"detail-type": "AWS Health Event",
"source": "aws.health",
"account": "123456789012",
"time": "2023-01-27T09:01:22Z",
"region": "af-south-1",
"resources": [],
"detail": {
"eventArn": "arn:aws:health:af-south-1::event/EC2/AWS_EC2_OPERATIONAL_ISSUE/AWS_EC2_OPERATIONAL_ISSUE_7f35c8ae-af1f-54e6-a526-d0179ed6d68f",
"service": "EC2",
"eventTypeCode": "AWS_EC2_OPERATIONAL_ISSUE",
"eventTypeCategory": "issue",
"eventScopeCode": "PUBLIC",
"communicationId": "01b0993207d81a09dcd552ebd1e633e36cf1f09a-1",
"startTime": "Fri, 27 Jan 2023 06:02:51 GMT",
"endTime": "Fri, 27 Jan 2023 09:01:22 GMT",
"lastUpdatedTime": "Fri, 27 Jan 2023 09:01:22 GMT",
"statusCode": "open",
"eventRegion": "af-south-1",
"eventDescription": [{
"language": "en_US",
"latestDescription": "Current severity level: Operating normally\n\n[RESOLVED] \n\n [03:15 PM PST] We continue see recovery \n\nThe following AWS services were previously impacted but are now operating normally: APPSYNC, BACKUP, EVENTS."
}],
"affectedEntities": [],
"page": "1",
"totalPages": "1",
"backupEvent": "false",
"affectedAccount": "123456789012",
"personas": ["OPERATIONS"]
}
}
クリックしたら「入力 - オプション」に上記のJSONをペーストして実行を開始をクリックしてください。

実行が正常に完了すると以下のようにNotionのデータベースに登録されていることが確認できます。


さいごに
最初はLambdaで作ろうと思っていたのですが、とりあえずNotionに登録するだけであればStep FunctionsだけでもAPI実行できるのでLambdaいらないのでは?というところから始めてみました。
実際メッセージの細かい編集などが無い今回のようなものであればStep Functionsのみで十分かなといった印象です。
Lambdaだと自由度は高いですが、定期的なランタイム更新などが発生するので通知するだけの目的で使うのはちょっと面倒なのかなと思いました。




