---
name: azion-install-the-send-event-to-endpoint-integration
description: >-
  Install Send Event to Endpoint from Azion Marketplace and run it on a firewall to stream request data to an HTTP endpoint or an S3 bucket.
---

# Install the Send Event to Endpoint integration

You install the Send Event to Endpoint integration from Azion Marketplace and run it on a [Firewall](/en/documentation/platform/firewall/), from Azion Console. The function takes the request data and sends it to an endpoint you define, through the JavaScript fetch API. A JSON argument file sets which data the function captures, and after it sends the data, the request continues through the Rules Engine.

Five objects have to exist before request data is streamed: the installed function, a firewall carrying the **Functions** module, a function instance holding the arguments, a Rules Engine rule with the **Run Function** behavior, and a workload deployment bound to the firewall. Each section below creates one of them.

---

## Prerequisites

- An Azion account. To sign in, refer to [How to access Azion Console](/en/documentation/guides/platform/account-and-billing/how-to-access-azion-console/).
- An application served by a [workload](/en/documentation/platform/workloads/), whose deployment you bind to the firewall in the last section.
- An HTTP endpoint that receives the data, an S3 bucket with its access key and secret key, or both.
- The [Azion CLI](/en/documentation/devtools/cli/) installed and authorized, for the last section.
- Turning on a product or a module can generate usage costs. For more information, refer to [Pricing](/en/documentation/fundamentals/pricing/).

---

## Install the integration

The function is installed once per account. To install it:

1. **Open Marketplace**

   Access [Azion Console](https://console.azion.com/) > **Marketplace**.

2. **Find the integration**

   Enter `Send Event to Endpoint` in the **Search on Marketplace** field, then select the integration's card. Browsing the cards and the categories reaches the same page.

3. **Select Install**

The card shows `Successfully installed!` and `Latest version installed!`, and the function appears in the **Function** list of the **Create Instance** drawer.

---

## Create the firewall

The firewall is where the function is instanced and where the rule that runs it lives. To create one:

1. **Open the Firewalls page**

   Access [Azion Console](https://console.azion.com/) > **Firewalls**, then create a firewall.

2. **Name the firewall**

   In the **General** section, enter a **Name**. For example: `send-event-firewall`.

3. **Turn on the Functions module**

   In the **Modules** section, turn on the **Functions** switch.

4. **Save the firewall**

The firewall shows a **Functions Instances** tab while the **Functions** module stays on. To use an existing firewall instead, turn on its **Functions** module and save it. For every setting on this form, refer to [Set a firewall's main settings](/en/documentation/guides/application-security/firewall-and-waf/firewall-configure-main-settings/).

---

## Create the function instance

The instance holds the data selection and the connection arguments for the endpoint or the bucket. To create it:

1. **Open the Functions Instances tab**

   In **Firewalls**, select your firewall, then select the **Functions Instances** tab.

2. **Select + Function**

   A firewall that has no instance shows the same action as **Function Instance**. The **Create Instance** drawer opens.

3. **Name the instance**

   In **Name**, enter a name. For example: `send-event`.

4. **Select the installed function**

   In **Function**, select the Send Event to Endpoint function. The list holds only the functions that run on a firewall.

5. **Enter the arguments**

   In **Arguments**, the editor is prefilled with the integration's default arguments in JSON. Enter your values, as the next section describes.

6. **Select Save**

The instance is listed in the **Functions Instances** tab.

### Arguments

The default arguments look like this:

```json
{
  "metadata": ["remote_addr"],
  "headers": ["x-hello"],
  "body": ["message", "user.id"],
  "http_connection_args": {
	"endpoint": "http://example_api:3000/test",
	"headers": {
  	"Authorization": "FakeAuth",
  		"X-Provider": "Azion Cells"
	}
  }
}
```

| Field                                | Required                             | Data type     | Notes                                                                                                                                                                                                                                                                                                                                                   |
| ------------------------------------ | ------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `metadata`                           | No                                   | Null or Array | The metadata fields the function streams. When `null` or not set, the function streams all metadata fields. To stream no metadata, set an empty array `[ ]` as the value.                                                                                                                                                                               |
| `headers`                            | No                                   | Null or Array | The request headers the function streams. When `null` or not set, the function streams all request headers. To stream no header, set an empty array `[ ]` as the value.                                                                                                                                                                                 |
| `body`                               | No                                   | Null or Array | The request body fields the function streams. When `null` or not set, the function streams all request body fields. To stream no body field, set an empty array `[ ]` as the value. To filter multi-level fields, use dot notation: the string `'user.name'` makes the function look for the field `'name'` in the object `'user'` of the request body. |
| `connection_args`                    | Yes                                  | Object        | The data the function uses to stream the request data. The endpoint is the URL that receives the data. The headers are the headers the fetch request includes. The function also adds a `'Content-Type: application/json'` header.                                                                                                                      |
| `s3_connection_args`                 | No                                   | Object        | The arguments the function uses to connect to the S3 bucket.                                                                                                                                                                                                                                                                                            |
| `s3_connection_args.full_host`       | Only when using `s3_connection_args` | String        | The full host of the S3 bucket.                                                                                                                                                                                                                                                                                                                         |
| `s3_connection_args.region`          | Only when using `s3_connection_args` | String        | The region of the S3 bucket.                                                                                                                                                                                                                                                                                                                            |
| `s3_connection_args.access_key`      | Only when using `s3_connection_args` | String        | The access key for the connection to the S3 bucket.                                                                                                                                                                                                                                                                                                     |
| `s3_connection_args.secret_key`      | Only when using `s3_connection_args` | String        | The secret key for the connection to the S3 bucket.                                                                                                                                                                                                                                                                                                     |
| `s3_connection_args.file_path`       | No                                   | String        | The path where the function stores the file it creates. Default value: `/`                                                                                                                                                                                                                                                                              |
| `s3_connection_args.use_date_prefix` | No                                   | String        | When on, the function adds a subfolder named after the current date, in the format YYYY-MM-DD, to the file path. Default value: `true`                                                                                                                                                                                                                  |

You can also use a catch-all argument file, like this:

```json
{
    "connection_args": {
        "endpoint": "http://example_api:3000/test", 
    }
}
```

When you supply valid connection arguments for both the HTTP endpoint and the S3 bucket, the function delivers the event data to both at the same time.

### Streamed data

The function sends the streamed data as a JSON file like this:

```json
{
  "body": {
	"field_a": <data>,
	...
  },
  "geoip_asn": <data>,
  "geoip_city": <data>,
  "geoip_city_continent_code": <data>,
  "geoip_city_country_code": <data>,
  "geoip_city_country_name": <data>,
  "geoip_continent_code": <data>,
  "geoip_country_code": <data>,
  "geoip_country_name": <data>,
  "geoip_region": <data>,
  "geoip_region_name": <data>,
  "headers": {
	"x-header-a": <data>,
	...
  },
  "remote_addr": <data>,
  "remote_port": <data>,
  "remote_user": <data>,
  "request_id": <data>,
  "request_url": <data>,
  "server_protocol": <data>,
  "ssl_cipher": <data>,
  "ssl_protocol": <data>
}
```

The `request_id`, the `request_url`, and the metadata fields are at the root of the JSON file. The body fields and the request headers are in objects.

### S3 output files

Each run of the function creates a new file in the S3 bucket. The file takes its name from the ID of the request that ran the function.

For example: `connection_args.file_path` is set to `/my-data/`, and the function runs on May 9th, 2023, for the request ID `abcd-1234`. The function saves the file at `/my-data/2023-05-09/abcd-1234.json`. When `connection_args.use_date_prefix` is set to `false`, the function saves the file as `/my-data/abcd-1234.json`.

> **AWS S3 HMAC compatibility**
>
> The integration does not support AWS Signature Version 4 (SigV4) HMAC authentication. On an Amazon S3 bucket with HMAC turned on, the function fails to deliver data, and [Real-Time Events](/en/documentation/platform/real-time-events/) shows this error:
>
> ```xml
> <Error>
>   <Code>InvalidRequest</Code>
>   <Message>Missing required header for this request: x-amz-content-sha256</Message>
> </Error>
> ```
>
> AWS SigV4 HMAC authentication requires the `x-amz-content-sha256` header, and the integration does not generate it. To solve this, turn off HMAC authentication on your S3 bucket. For details, refer to the [AWS documentation on S3 authentication](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html).

### Connection errors

When the argument file has no `http_connection_args` and no `s3_connection_args`, the function has no valid connection arguments. The function ends the request and returns a JSON error message with the cause:

```json
{
  "error": "A001",
  "detail": "The function instance is missing or has invalid required arguments."
}
```

When the function cannot connect to the HTTP endpoint or to the S3 provider, it ignores the user request. The function still creates an error log, which you can access through [Data Stream](/en/documentation/platform/data-stream/). For example, an invalid access key shows this message:

```json
[Send event to endpoint] S3 connection error; 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Error>
	<Code>InvalidAccessKeyId</Code>
	<Message>The key 'DAKEY' is not valid</Message>
</Error>
```

---

## Create the rule

The instance streams nothing until a rule runs it. A [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine/) rule selects the requests that reach the instance, through a **Run Function** behavior. To create the rule:

1. **Open the Rules Engine tab**

   In **Firewalls**, select your firewall, then select the **Rules Engine** tab.

2. **Select + Rule**

3. **Name the rule**

   In **Name**, enter a name. For example: `Run Send Event to Endpoint`.

4. **Set the criterion**

   In the **Criteria** section, select the domains that run the integration. For example: if `Host` *matches* `yourdomain.com`.

5. **Add the Run Function behavior**

   In the **Behaviors** section, select **Run Function**, then select the instance by the name you gave it.

6. **Select Save**

The firewall runs the instance on every request to the domains in the criterion.

---

## Bind the firewall to the workload

The binding is on the workload's deployment, so create a deployment that names both the application and the firewall:

```bash
azion create workload-deployment --workload-id <workload-id> --name <deployment-name> \
  --application-id <application-id> --firewall-id <firewall-id> --strategy-type default \
  --active true --current true
```

The command prints the id of the new deployment:

```text
Created Workload Deployment with ID 123456
```

Requests to the workload's domain reach the firewall, and the rule runs the Send Event to Endpoint instance on each one.

---

## Next steps

- [Marketplace integrations](/en/documentation/platform/marketplace/integrations.md): Every integration Azion Marketplace offers, and where each one runs.
- [Rules Engine for Firewall](/en/documentation/platform/firewall/rules-engine.md): Every criterion and behavior a firewall rule accepts.
- [Data Stream](/en/documentation/platform/data-stream.md): Read the error logs the function writes when a connection fails.
- [Update an integration](/en/documentation/guides/application-development/integrations/update-an-integration.md): Move an installed integration to its latest version.
