---
description: >-
  Stream FHIR resource events to AWS EventBridge for serverless event-driven
  architectures and cross-account integrations.
---

# AidboxTopicSubscription AWS EventBridge tutorial

{% hint style="info" %}
This functionality is available starting from Aidbox version **2601**.
{% endhint %}

{% hint style="warning" %}
**Aidbox version compatibility**

| Aidbox | Connector JAR | Profile URL |
| --- | --- | --- |
| ≥ 2604 | `topic-destination-aws-eventbridge-2604.0.jar` | `http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeBestEffortProfile`<br>`http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeAtLeastOnceProfile` |
| < 2604 | `topic-destination-aws-eventbridge-2601.1.jar` | `http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-eventbridge-best-effort`<br>`http://aidbox.app/StructureDefinition/aidboxtopicdestination-aws-eventbridge-at-least-once` |

Examples below use the ≥ 2604 form. On older Aidbox, swap both the JAR and the `meta.profile` URL. Redeploy the JAR when crossing the 2604 boundary — older JARs register profiles via a legacy path the new validator no longer honors.
{% endhint %}

## Objectives

* Learn how to integrate [AidboxTopicSubscriptions](../../modules/topic-based-subscriptions/aidbox-topic-based-subscriptions.md) with AWS EventBridge

## Before you begin

* Make sure your Aidbox version is **2601** or newer
* Setup the local Aidbox instance using getting started [guide](../../getting-started/run-aidbox-locally.md)

## What is AWS EventBridge?

[AWS EventBridge](https://aws.amazon.com/eventbridge/) is a serverless event bus service that enables you to build event-driven applications. It provides a central hub for receiving, filtering, transforming, and routing events from various sources to AWS services or custom applications.

For detailed information, see the [official EventBridge documentation](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html).

### Key Concepts

[**Event Bus**](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-bus.html) is a router that receives events and delivers them to targets based on rules. EventBridge provides:

* **Default event bus**: Receives events from AWS services
* **Custom event buses**: For your application events
* **Partner event buses**: For SaaS integrations

[**Events**](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html) are JSON objects with standard fields:

* `source`: Identifies the event producer (for example, `aidbox.mycompany.com`)
* `detail-type`: Categorizes events for filtering (for example, `FHIR Patient Notification`)
* `detail`: The actual payload (FHIR Bundle with subscription notification)

### Best Effort vs At-Least-Once Delivery

In Aidbox, two [AidboxTopicDestination](../../modules/topic-based-subscriptions/aidbox-topic-based-subscriptions.md#aidboxtopicdestination) profiles are supported:

* `http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeBestEffortProfile` — Events are sent immediately. If EventBridge returns an error, the event is lost. Low latency, suitable for non-critical notifications.
* `http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeAtLeastOnceProfile` — Events are persisted to database before sending. If EventBridge is unavailable, events remain in queue and are retried automatically. Supports batching up to 10 events. Guaranteed delivery for critical integrations.

## Setting up locally

Follow the steps to try AWS EventBridge AidboxTopicSubscription with [LocalStack](https://www.localstack.cloud/) — a local AWS emulator for development and testing.

### 1. Create directory structure

```sh
mkdir eventbridge && cd eventbridge
```

### 2. Configure docker-compose.yaml

Download the getting started [docker-compose.yaml](../../getting-started/run-aidbox-locally.md) and add LocalStack service for local testing:

```yaml
services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - "4566:4566"
    environment:
      - SERVICES=events
      - DEBUG=1

  aidbox:
    # ... existing aidbox configuration ...
    extra_hosts:
      - "host.docker.internal:host-gateway"
    volumes:
      - ./topic-destination-aws-eventbridge-2601.1.jar:/topic-destination-aws-eventbridge.jar
    environment:
      BOX_MODULE_LOAD: io.healthsamurai.topic-destination.eventbridge.core
      BOX_MODULE_JAR: "/topic-destination-aws-eventbridge.jar"
      # ... other envs ...
```

### 3. Download the EventBridge module

Download **.jar** EventBridge module file from [our bucket](https://console.cloud.google.com/storage/browser/aidbox-modules/topic-destination-aws-eventbridge) and place it next to **docker-compose.yaml**.

```sh
curl -O https://storage.googleapis.com/aidbox-modules/topic-destination-aws-eventbridge/topic-destination-aws-eventbridge-2601.1.jar
```

### 4. Start services

```sh
docker compose up -d
```

### 5. Verify installation

In AidboxUI, go to **FHIR Packages -> io.healthsamurai.topic** and make sure that EventBridge profiles are present:

* `aidboxtopicdestination-aws-eventbridge-best-effort`
* `aidboxtopicdestination-aws-eventbridge-at-least-once`

![aidbox fhir packages ui](../../../assets/eventbridge.avif)

### 6. Create Event Bus in LocalStack

```sh
aws --endpoint-url=http://localhost:4566 events create-event-bus --name test-bus
```

To verify:

```sh
aws --endpoint-url=http://localhost:4566 events list-event-buses
```

## Basic Usage (Best Effort)

### 1. Create a subscription topic

```http
POST /fhir/AidboxSubscriptionTopic
content-type: application/json
accept: application/json

{
  "resourceType": "AidboxSubscriptionTopic",
  "url": "patient-topic",
  "status": "active",
  "trigger": [
    {
      "resource": "Patient",
      "fhirPathCriteria": "name.exists()"
    }
  ]
}
```

### 2. Create AidboxTopicDestination

```http
POST /fhir/AidboxTopicDestination
content-type: application/json
accept: application/json

{
  "id": "eventbridge-destination",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeBestEffortProfile"
    ]
  },
  "kind": "aws-eventbridge-best-effort",
  "topic": "patient-topic",
  "parameter": [
    {
      "name": "eventBusName",
      "valueString": "test-bus"
    },
    {
      "name": "region",
      "valueString": "us-east-1"
    },
    {
      "name": "source",
      "valueString": "aidbox.mycompany.com"
    },
    {
      "name": "detailType",
      "valueString": "FHIR Patient Notification"
    },
    {
      "name": "accessKeyId",
      "valueString": "test"
    },
    {
      "name": "secretAccessKey",
      "valueString": "test"
    },
    {
      "name": "endpointOverride",
      "valueString": "http://host.docker.internal:4566"
    }
  ]
}
```

### 3. Create a Patient

```http
POST /fhir/Patient
content-type: application/json

{
  "name": [{"family": "Smith", "given": ["John"]}]
}
```

### 4. Verify event delivery

Check the topic destination status:

```http
GET /fhir/AidboxTopicDestination/eventbridge-destination/$status
```

Response:

```json
{
  "resourceType": "Parameters",
  "parameter": [
    { "name": "messagesDelivered", "valueDecimal": 1 },
    { "name": "messagesDeliveryAttempts", "valueDecimal": 0 },
    { "name": "messagesInProcess", "valueDecimal": 0 },
    { "name": "messagesQueued", "valueDecimal": 0 },
    { "name": "startTimestamp", "valueDateTime": "2025-05-05T10:00:00Z" },
    { "name": "status", "valueString": "active" }
  ]
}
```

#### View events in LocalStack

To verify events are actually delivered to EventBridge, create an SQS queue as a target:

```sh
aws --endpoint-url=http://localhost:4566 events put-rule \
  --name "log-all" \
  --event-bus-name "test-bus" \
  --event-pattern '{"source": [{"prefix": ""}]}'
```

```sh
aws --endpoint-url=http://localhost:4566 sqs create-queue --queue-name test-queue
```

```sh
aws --endpoint-url=http://localhost:4566 events put-targets \
  --rule "log-all" \
  --event-bus-name "test-bus" \
  --targets "Id"="1","Arn"="arn:aws:sqs:us-east-1:000000000000:test-queue"
```

```sh
aws --endpoint-url=http://localhost:4566 sqs receive-message \
  --queue-url http://localhost:4566/000000000000/test-queue
```

## At-Least-Once with Batching

For guaranteed delivery with batch processing, use the at-least-once profile:

```http
POST /fhir/AidboxTopicDestination
content-type: application/json
accept: application/json

{
  "id": "eventbridge-reliable",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeAtLeastOnceProfile"
    ]
  },
  "kind": "aws-eventbridge-at-least-once",
  "topic": "patient-topic",
  "parameter": [
    {
      "name": "eventBusName",
      "valueString": "test-bus"
    },
    {
      "name": "region",
      "valueString": "us-east-1"
    },
    {
      "name": "source",
      "valueString": "aidbox.mycompany.com"
    },
    {
      "name": "detailType",
      "valueString": "FHIR Patient Notification"
    },
    {
      "name": "accessKeyId",
      "valueString": "test"
    },
    {
      "name": "secretAccessKey",
      "valueString": "test"
    },
    {
      "name": "endpointOverride",
      "valueString": "http://host.docker.internal:4566"
    },
    {
      "name": "batchSize",
      "valueInteger": 10
    }
  ]
}
```

The `batchSize` parameter (1-10) controls how many events are sent in a single [PutEvents API](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html) call. EventBridge allows [maximum 10 entries per request](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-quota.html).

## Configuration Reference

### Available Parameters

| Parameter          | Type         | Required | Description                                                       |
| ------------------ | ------------ | -------- | ----------------------------------------------------------------- |
| `eventBusName`     | valueString  | Yes      | Event Bus name or ARN (`default`, `my-bus`, or full ARN)          |
| `region`           | valueString  | Yes      | AWS region (`us-east-1`, `eu-west-1`, etc.)                       |
| `source`           | valueString  | Yes      | Event source identifier for routing rules                         |
| `detailType`       | valueString  | Yes      | Event type for filtering in EventBridge rules                     |
| `accessKeyId`      | valueString  | No       | AWS Access Key ID (uses default credential chain if not provided) |
| `secretAccessKey`  | valueString  | No       | AWS Secret Access Key                                             |
| `endpointOverride` | valueString  | No       | Override endpoint URL (for LocalStack: `http://localhost:4566`)   |
| `batchSize`        | valueInteger | No       | Events per batch, 1-10 (at-least-once only, default: 1)           |

### Event Format

Events sent to EventBridge have this structure:

```json
{
  "source": "aidbox.mycompany.com",
  "detail-type": "FHIR Patient Notification",
  "detail": {
    "topic": "patient-topic",
    "value": {
      "resourceType": "Bundle",
      "type": "history",
      "timestamp": "2025-05-05T10:00:00Z",
      "entry": [
        {
          "resource": {
            "resourceType": "AidboxSubscriptionStatus",
            "status": "active",
            "type": "event-notification",
            "notificationEvent": [
              {
                "eventNumber": 1,
                "focus": { "reference": "Patient/123" }
              }
            ],
            "topic": "patient-topic",
            "topic-destination": {
              "reference": "AidboxTopicDestination/eventbridge-destination"
            }
          }
        },
        {
          "request": { "method": "POST", "url": "/fhir/Patient" },
          "fullUrl": "http://localhost:8080/fhir/Patient/123",
          "resource": {
            "resourceType": "Patient",
            "id": "123",
            "name": [{ "family": "Smith", "given": ["John"] }]
          }
        }
      ]
    }
  },
  "event-bus-name": "test-bus"
}
```

## AWS Authentication

### Option 1: Access Keys (for development)

Provide `accessKeyId` and `secretAccessKey` parameters directly in the AidboxTopicDestination.

### Option 2: IAM Role (recommended for production)

When running on AWS (EC2, ECS, EKS), omit `accessKeyId` and `secretAccessKey`. The module will use the default AWS credential chain:

1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
2. Web Identity Token (for EKS)
3. EC2/ECS Instance Profile

Required IAM permissions:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "events:PutEvents",
      "Resource": "arn:aws:events:*:*:event-bus/your-bus-name"
    }
  ]
}
```

## Creating EventBridge Rules

[EventBridge Rules](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rules.html) define how events are routed to targets. To route events from EventBridge to targets, create rules in the AWS Console or via CLI:

```sh
aws events put-rule \
  --name "patient-notifications" \
  --event-bus-name "test-bus" \
  --event-pattern '{
    "source": ["aidbox.mycompany.com"],
    "detail-type": ["FHIR Patient Notification"]
  }'
```

```sh
aws events put-targets \
  --rule "patient-notifications" \
  --event-bus-name "test-bus" \
  --targets "Id"="1","Arn"="arn:aws:sqs:us-east-1:123456789:patient-queue"
```

## Monitoring

### Status Endpoint

```http
GET /fhir/AidboxTopicDestination/{id}/$status
```

### Response Parameters

| Parameter                  | Description                                  |
| -------------------------- | -------------------------------------------- |
| `messagesDelivered`        | Total successfully delivered events          |
| `messagesDeliveryAttempts` | Failed delivery attempts                     |
| `messagesInProcess`        | Events currently being sent                  |
| `messagesQueued`           | Events waiting in queue (at-least-once only) |
| `startTimestamp`           | Destination start time                       |
| `status`                   | Always `active`                              |
| `lastErrorDetail`          | Recent error information                     |

### Prometheus Metrics

```http
GET /metrics
```

Metrics include:

* `aidbox_topic_destination_messages_delivered`
* `aidbox_topic_destination_messages_queued`
* `aidbox_topic_destination_messages_in_process`

## Set up with AWS

### Prerequisites

1. AWS account with EventBridge access
2. AWS CLI configured: `aws configure`
3. IAM user/role with `events:PutEvents` permission

### Step 1: Create Event Bus

```sh
aws events create-event-bus --name aidbox-events --region us-east-1
```

### Step 2: Create SQS Queue for Testing

Create a queue to receive events (for verification):

```sh
aws sqs create-queue --queue-name aidbox-test-queue --region us-east-1
```

### Step 3: Create EventBridge Rule

Route events to the SQS queue:

```sh
aws events put-rule \
  --name "aidbox-to-sqs" \
  --event-bus-name "aidbox-events" \
  --event-pattern '{"source": ["aidbox.mycompany.com"]}' \
  --region us-east-1
```

```sh
SQS_ARN=$(aws sqs get-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --attribute-names QueueArn \
  --query 'Attributes.QueueArn' \
  --output text \
  --region us-east-1)
```

```sh
aws events put-targets \
  --rule "aidbox-to-sqs" \
  --event-bus-name "aidbox-events" \
  --targets "Id"="1","Arn"="$SQS_ARN" \
  --region us-east-1
```

### Step 4: Configure SQS Policy

Allow EventBridge to send messages to SQS:

```sh
aws sqs set-queue-attributes \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --attributes '{
    "Policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Action\":\"sqs:SendMessage\",\"Resource\":\"arn:aws:sqs:us-east-1:YOUR_ACCOUNT_ID:aidbox-test-queue\"}]}"
  }' \
  --region us-east-1
```

### Step 5: Create AidboxTopicDestination

When running on AWS infrastructure (EC2, ECS, EKS), use IAM roles instead of access keys. See [AWS Authentication](aws-eventbridge-aidboxtopicdestination.md#aws-authentication) for details.

```http
POST /fhir/AidboxTopicDestination
content-type: application/json

{
  "id": "eventbridge-aws",
  "resourceType": "AidboxTopicDestination",
  "meta": {
    "profile": [
      "http://health-samurai.io/fhir/core/StructureDefinition/aidboxtopicdestination-awsEventBridgeAtLeastOnceProfile"
    ]
  },
  "kind": "aws-eventbridge-at-least-once",
  "topic": "patient-topic",
  "parameter": [
    {"name": "eventBusName", "valueString": "aidbox-events"},
    {"name": "region", "valueString": "us-east-1"},
    {"name": "source", "valueString": "aidbox.mycompany.com"},
    {"name": "detailType", "valueString": "FHIR Patient Notification"}
  ]
}
```

### Step 6: Test and Verify

1. Create a Patient in Aidbox
2. Check SQS for received messages:

```sh
aws sqs receive-message \
  --queue-url https://sqs.us-east-1.amazonaws.com/YOUR_ACCOUNT_ID/aidbox-test-queue \
  --region us-east-1
```

## Related Documentation

### Aidbox

* [Topic-based Subscriptions](../../modules/topic-based-subscriptions/aidbox-topic-based-subscriptions.md)
* [AidboxTopicDestination](../../modules/topic-based-subscriptions/aidbox-topic-based-subscriptions.md#aidboxtopicdestination)

### AWS EventBridge

* [What is Amazon EventBridge?](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html)
* [Amazon EventBridge Event Buses](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-bus.html)
* [Amazon EventBridge Events](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events.html)
* [Sending Events with PutEvents](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevents.html)
* [Amazon EventBridge Rules](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-rules.html)
* [Amazon EventBridge Targets](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-targets.html)
* [Amazon EventBridge Quotas](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-quota.html)
* [PutEvents API Reference](https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEvents.html)
