# Configure webhooks
Source: https://www.stedi.com/docs/healthcare/configure-webhooks

***

title: "Configure webhooks"
sidebarTitle: "Configure webhooks"
----------------------------------

You can set up webhooks that automatically send claim processing events to your endpoint.

These events contain the information you need to retrieve 277CA claim acknowledgment and 835 Electronic Remittance Advice (ERA) responses through Stedi APIs. They can also help you monitor your claims pipeline when you're submitting claims through [Stedi SFTP](/healthcare/submit-claims-sftp-connection).

You can either create a single webhook that forwards events from all transactions, or create a separate webhook for each transaction type.

Configuring a webhook involves:

* Creating a [credential set](#credential-set) for authentication to the endpoint.
* Creating a [webhook](#webhook) that specifies the URL where Stedi should deliver events.
* Adding one or more [event bindings](#event-bindings) that trigger the webhook.

## Credential set

A credential set defines how to authenticate with a specific API. You can use a single credential set across multiple webhooks. Stedi supports the following types of configurations.

\| Type       | Description                                                                                                                            |
\| ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
\| API Keys   | The API keys as headers in the request. The most common version is ‘bearer tokens’.                                                    |
\| Basic Auth | [HTTP Basic Auth](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Authentication), where you provide a username and password. |
\| None       | For endpoints that don't require any authentication.                                                                                   |

### Unauthenticated endpoints

When using the 'None' credential set type in webhooks, it's functionally the same as using 'API Keys'. However, we set a dummy value for `Header name` and `Value` (`x-stedi-noauth` and `dummy`). Since the receiving API isn't authenticating the call, it will ignore these values and accept the request.

### Create credential set

You can define a credential set as part of configuring a new webhook. You can also create a new credential set independently and then attach it to one or more webhooks.

To create a credential set:

1. Go to the [Webhooks](https://portal.stedi.com/app/webhooks) page.
2. Click **Manage credentials**, and then click **Create credential set**.
3. Enter a name.
4. Choose the appropriate **Authentication type**.
5. Enter the details.
6. Click **Create credential set**.

## Webhook

A webhook defines which URL endpoint Stedi should call when the webhook is invoked, and which HTTP method to use (`POST`, `PUT`, `GET`, `PATCH`, `DELETE`).

You can only attach one credential set to each webhook. However, you might have multiple webhooks for a single system integration, each with a different endpoint.

### Create webhook

To create a new webhook:

1. Go to the [Webhooks](https://portal.stedi.com/app/webhooks) page.
2. Click **Create webhook**.
3. Enter a name.
4. Choose a **Method** and enter an **Endpoint** URL. This is where Stedi delivers the events when the webhook is invoked.
5. Select a **Credential set** to use for authentication or create a new one for this endpoint.
6. (Optional) Set the **Concurrency**. You can set the maximum number of deliveries that Stedi will attempt to deliver to the endpoint at one time. This can help you avoid overloading the target service.

## Event bindings

Event bindings allow you to specify which events trigger the webhook. You can create multiple event bindings for a single webhook. For example, you may want to create an event binding for each type of transaction you want to send to your API.

### Create event binding

To create a new event binding:

1. Go to the [Webhooks](https://portal.stedi.com/app/webhooks) page.
2. Click the webhook.
3. Click the **Event bindings** tab.
4. Click **New event binding**.
5. Choose **Transaction processed** as the **Event type**.
6. (Optional) Set one or more [filters](#event-filters).
7. Click **Create binding**.

### Choosing event types

The recommended event bindings depend on your use case:

* **API claim submission:** At a minimum, you should create an event binding for transaction processed events because they contain the information you need to retrieve claim responses from Stedi. You may also want to set up event bindings for file delivered and file failed events.
* **SFTP claim submission:** At a minimum, you should create an event binding for file failed events because they're emitted when Stedi is unable to deliver your claim to the payer. You may also want to set up event bindings for file delivered events and transaction processed events.

<Note>
  The file processed and fragment processed events are not relevant to claims
  processing.
</Note>

**Transaction processed events**

Stedi emits a transaction processed event after it successfully receives and translates a payer or intermediary clearinghouse response into JSON. It also emits this event once it successfully translates a JSON claim submission into X12 EDI format for the payer. The event payload contains the information you need to retrieve processed responses through Stedi APIs:

* `x12.transactionSetIdentifier` specifies the transaction type (277 or 835).
* `transactionId` allows you to retrieve the transaction in JSON format using either the [277CA Report](/healthcare/api-reference/get-healthcare-reports-277) or [835 ERA Report](/healthcare/api-reference/get-healthcare-reports-835) endpoint.
* `fileExecutionId` allows you to retrieve the transaction in X12 EDI format through the [Retrieve Execution Input](/healthcare/api-reference/get-execution-input) endpoint.

Even if you plan to retrieve claim responses through Stedi SFTP, you may want to monitor these events so you can receive alerts when new claim responses are available.

<Accordion title="Example transaction processed events for 277CA and 835 ERA">
  ```json tab="processed 277CA"
  {
    "event": {
      "version": "0",
      "id": "f972fb53-653a-1747-ce30-bed15fc04f5c",
      "detail-type": "transaction.processed.v2",
      "source": "stedi.core",
      "account": "<ACCOUNT_ID>",
      "time": "2024-07-18T16:21:24Z",
      "region": "us-east-1",
      "resources": [
        "https://core.us.stedi.com/2023-08-01/transactions/f0d3f790-0bc9-432b-93kd-e4b7ece67946"
      ],
      "detail": {
        "transactionId": "f0d4f780-0ec9-432b-93gd-e4b7ece93946",
        "direction": "INBOUND",
        "mode": "test",
        "fileExecutionId": "9f76b485-6hca-43bf-917e-d5b54bec6234",
        "processedAt": "2024-07-18T16:21:24.658Z",
        "fragments": null,
        "artifacts": [
          {
            "artifactType": "application/edi-x12",
            "usage": "input",
            "url": "https://core.us.stedi.com/2023-08-01/transactions/f0d9f790-0ec9-431b-93fd-e4h7ece63946/input",
            "sizeBytes": 1313,
            "model": "transaction"
          },
          {
            "artifactType": "application/json",
            "usage": "output",
            "url": "https://core.us.stedi.com/2023-08-01/transactions/f0d3f740-0ec9-432b-98fd-e4b7ece63946/output",
            "sizeBytes": 5602,
            "model": "transaction"
          }
        ],
        "partnership": {
          "partnershipId": "local-clearinghouse-test",
          "partnershipType": "x12",
          "sender": {
            "profileId": "clearinghouse-test"
          },
          "receiver": {
            "profileId": "local"
          }
        },
        "x12": {
          "transactionSetting": {
            "guideId": "01J1M50C1Q44KYDZY8V7R1TPBW",
            "transactionSettingId": "01J1M50P9623BFE0FFT5Q2BR49"
          },
          "metadata": {
            "interchange": {
              "acknowledgmentRequestedCode": "0",
              "controlNumber": 11
            },
            "functionalGroup": {
              "controlNumber": 11,
              "release": "005010X214",
              "date": "2024-07-18",
              "time": "16:20:47",
              "functionalIdentifierCode": "HN"
            },
            "transaction": {
              "controlNumber": "1001",
              "transactionSetIdentifier": "277"
            },
            "receiver": {
              "applicationCode": "001690149382",
              "isa": {
                "qualifier": "ZZ",
                "id": "001690149382"
              }
            },
            "sender": {
              "applicationCode": "STEDITEST",
              "isa": {
                "qualifier": "ZZ",
                "id": "STEDITEST"
              }
            }
          }
        },
        "connectionId": "01J1M5124B2HWMNN91Q3Z6AM61"
      }
    }
  }
  ```

  ```json tab="processed 835 ERA"
  {
    "event": {
      "version": "0",
      "id": "5d1bcb90-cb0b-1844-5b93-86d5e5b9c4a8",
      "detail-type": "transaction.processed.v2",
      "source": "stedi.core",
      "account": "<ACCOUNT_ID>",
      "time": "2025-07-14T20:43:39Z",
      "region": "us-east-1",
      "resources": [
        "https://core.us.stedi.com/2023-08-01/transactions/95e7786c-7066-4494-b83a-b1f300624902"
      ],
      "detail": {
        "transactionId": "95e7786c-7066-4494-b83a-b1f300624902",
        "direction": "INBOUND",
        "mode": "test",
        "fileExecutionId": "5d30f0a0-63af-4aeb-b96c-353b4b25c99a",
        "processedAt": "2025-07-14T20:43:39.808Z",
        "fragments": null,
        "artifacts": [
          {
            "artifactType": "application/edi-x12",
            "usage": "input",
            "url": "https://core.us.stedi.com/2023-08-01/transactions/95e7786c-7066-4494-b83a-b1f300624902/input",
            "sizeBytes": 2016,
            "model": "transaction"
          },
          {
            "artifactType": "application/json",
            "usage": "output",
            "url": "https://core.us.stedi.com/2023-08-01/transactions/95e7786c-7066-4494-b83a-b1f300624902/output",
            "sizeBytes": 13864,
            "model": "transaction"
          }
        ],
        "partnership": {
          "partnershipId": "local-clearinghouse-test",
          "partnershipType": "x12",
          "sender": {
            "profileId": "clearinghouse-test"
          },
          "receiver": {
            "profileId": "local"
          }
        },
        "x12": {
          "transactionSetting": {
            "guideId": "01J8JH1SGTB2FYKN2PG4MH84RP",
            "transactionSettingId": "01J8JH23VA3G2X8GENVVE6XZB9"
          },
          "metadata": {
            "interchange": {
              "acknowledgmentRequestedCode": "0",
              "controlNumber": 1
            },
            "functionalGroup": {
              "controlNumber": 1,
              "release": "005010X221A1",
              "date": "2025-07-14",
              "time": "20:43:21",
              "functionalIdentifierCode": "HP"
            },
            "transaction": {
              "controlNumber": "0001",
              "transactionSetIdentifier": "835"
            },
            "receiver": {
              "applicationCode": "599264680681",
              "isa": {
                "qualifier": "ZZ",
                "id": "599264680681"
              }
            },
            "sender": {
              "applicationCode": "STEDITEST",
              "isa": {
                "qualifier": "ZZ",
                "id": "STEDITEST"
              }
            }
          }
        },
        "connectionId": "01JE9257XJ4G4YFMXCHJPFR434"
      }
    }
  }
  ```
</Accordion>

**File delivered events**

Stedi emits a file delivered event when it successfully generates and delivers a claim. You may want to send these events to your system for monitoring and alerting.

Note that this event is emitted when Stedi delivers your claim to our connection with the payer. It doesn't indicate whether the payer received the claim or whether they have accepted or rejected it.

<Accordion title="Example file delivered event">
  ```json file.delivered.v2 event
  {
    "event": {
      "version": "0",
      "id": "3fb45b5f-bd7f-f9d0-c0a2-84946f20a9da",
      "detail-type": "file.delivered.v2",
      "source": "stedi.core",
      "account": "<ACCOUNT_ID>",
      "time": "2025-05-06T19:35:17Z",
      "region": "us-east-1",
      "resources": [],
      "detail": {
        "fileExecutionId": "e181c2ab-f85c-42bd-9cda-a7bd1e32b4c9",
        "processedAt": "2025-05-05T20:14:57.882927984Z",
        "artifacts": [
          {
            "artifactType": "application/edi-x12",
            "usage": "input",
            "sizeBytes": 1270,
            "url": "https://core.us.stedi.com/2023-08-01/executions/e181c2ab-f85c-42bd-9cda-a7bd1e32b4c9/input",
            "model": "execution"
          },
          {
            "artifactType": "application/edi-x12",
            "usage": "output",
            "sizeBytes": 1270,
            "url": "https://core.us.stedi.com/2023-08-01/executions/e181c2ab-f85c-42bd-9cda-a7bd1e32b4c9/output",
            "model": "execution"
          }
        ],
        "connection": {
          "connectionType": "STEDI_ACCOUNT_FTP",
          "connectionId": "01JM0XF37DXZ3THZ7N75YJTW52"
        },
        "delivery": {
          "status": "DELIVERED",
          "message": "Delivered to 'Test Account SFTP'",
          "artifactId": "9d7c38f4-410b-4032-aad4-016d8140b265.x12"
        }
      }
    }
  }
  ```
</Accordion>

**File failed events**

Stedi emits a file failed event when it either fails to process a response from a payer or cannot deliver a submitted claim.

If you're submitting claims through Stedi's SFTP connection, we strongly recommend monitoring these events so that you can receive instant notifications when a submitted claim fails due to validation errors in the EDI file.

File failed events can indicate connection problems or other issues that our engineering team must resolve with the payer. If you're submitting claims through Stedi APIs, you may want to also monitor these events so you can alert our customer support team if needed.

<Accordion title="Example file failed event">
  ```json file failed event
  {
    "event": {
      "version": "0",
      "id": "cef43062-0258-cbac-b06d-ec6a21f03c69",
      "detail-type": "file.failed.v2",
      "source": "stedi.core",
      "account": "<ACCOUNT_ID>",
      "time": "2025-06-05T11:26:16Z",
      "region": "us-east-1",
      "resources": [
        "https://core.us.stedi.com/2023-08-01/executions/7590afcd-26d7-4182-a8fc-1d1051e2815c"
      ],
      "detail": {
        "fileExecutionId": "7590afcd-26d7-4182-a8fc-1d1051e2815c",
        "direction": "INBOUND",
        "processedAt": "2025-06-05T11:26:16.354Z",
        "source": {
          "dirname": "remote-ftp/test/01JJYJ0GGVZD5GR230YP6G3MEA/fromPartner",
          "name": "Test_Dental.1234567.835"
        },
        "artifacts": [
          {
            "artifactType": "application/edi-x12",
            "url": "https://core.us.stedi.com/2023-08-01/executions/7590afcd-26d7-4182-a8fc-1d1051e2815c/input",
            "usage": "input",
            "model": "execution"
          }
        ],
        "connectionId": "01JJYJ0GGVZD5GR230YP6G3MEA",
        "partnership": {
          "partnershipId": "stedi-test_dentalpartner",
          "partnershipType": "x12",
          "receiver": {
            "profileId": "stedi-test"
          },
          "sender": {
            "profileId": "dentalpartner"
          }
        },
        "errors": [
          {
            "message": "String element BPR-10 must have a length of 10, actual length is 5\nElement PER-02 is not used by this guide",
            "faultCode": "FAILED_TO_TRANSLATE"
          }
        ],
        "x12": {
          "metadata": {
            "interchange": {
              "acknowledgmentRequestedCode": "1",
              "controlNumber": 56199839
            }
          },
          "receiver": {
            "isa": {
              "qualifier": "30",
              "id": "117151744"
            }
          },
          "sender": {
            "isa": {
              "qualifier": "ZZ",
              "id": "900117186"
            }
          }
        }
      }
    }
  }
  ```
</Accordion>

### Event filters

You may want to further filter the events Stedi sends to your endpoint:

* **Transaction:** This is useful if you want to send events for 277CA claim acknowledgments to one endpoint and events for 835 ERAs to another. For example, if you set this to `835: Health Care Claim Payment/Advice`, Stedi only sends events for processed 835 ERAs to your endpoint.
* **Partnership:** This is useful if you want to send test claims to one endpoint and production claims to another. For example, if you set this to `local-clearinghouse-test`, Stedi only sends events for test claims to your endpoint.

<Note>
  The **Guide**, **Connection**, and **Mode** filters are not relevant to claims
  processing.
</Note>

### Event schema

All Stedi events follow a standard JSON Schema. The event payload itself does not include the contents of a given file or transaction. Instead, it references an API path to retrieve the entire object.

```json JSON event structure example
{
  "version": "0",
  "id": "8a9fc08a-24b2-4eeb-af7c-f96376ea471e",
  "detail-type": "transaction.processed.v2",
  "source": "stedi.core",
  "account": "<ACCOUNT_ID>",
  "time": "2021-11-12T00:00:00Z",
  "region": "us-east-1",
  "resources": [
    "https://core.us.stedi.com/2023-08-01/transactions/3543b3f7-0d78-48cc-97c3-ac145e250a1d"
  ],
  "detail": { ... }
}
```

In addition to their `version`, `id`, and `time`, events have the following properties:

* **`detail-type`** - Indicates the type of event, such as `transaction.processed.v2` or `file.failed.v2`.
* **`source`** - Indicates the component that generated the event. All events use `source: “stedi.core”`.
* **`account`** - The account ID that generated the event.
* **`region`** - The AWS region where the event was generated.
* **`resources`** - The URL to the resource that Stedi created. This could be a transaction or a file execution, depending on the event type. Hitting the URL with your API key is equivalent to calling the [Get Execution](/edi-platform/api-reference/core/get-executions) and [Get Transaction](/edi-platform/api-reference/core/get-transactions) endpoints.
* **`detail`** - The JSON payload. The schema for each payload is determined by the `detail-type`.

## HTTP response codes

Stedi considers a `2xx` response a success, and marks any other response as a failure.

Stedi retries events associated with status codes other than `2xx` for up to 4 times with a 90 second wait period inbetween retries.

If the maximum number of retries has been exhausted, Stedi adds the event to the [error queue](#error-queue) for the webhook.

You can set the **Concurrency** when configuring the webhook to prevent throttling. This setting determines the maximum number of deliveries that Stedi will attempt to deliver to the endpoint at one time.

## Certificates

Webhooks only support valid, publicly trusted certificates. Self-signed certificates or certificates from private certificate authorities aren't supported.

You'll receive the following error if the endpoint configured for the webhook uses a certificate that isn't signed by a known, trusted certificate authority:

```
"awsResponse": "Unable to invoke ApiDestination endpoint: API destination endpoint cannot be reached."
```

## Timeouts

The target endpoint must respond with a `2xx` status code within 5 seconds, or the event will be counted as a failed delivery.

<Note>This is a hard limit that cannot be increased or configured.</Note>

Because of this timeout limitation, we recommend designing your webhook endpoints to immediately acknowledge receipt with a `2xx` response, then process the data asynchronously. See [Best practices for webhook endpoints](#best-practices-for-webhook-endpoints).

## Retries and duplicate deliveries

When a delivery fails, Stedi will retry up to 4 times every 90 seconds. After the fifth retry, Stedi moves the event to the error queue.

If your webhook doesn't respond within 5 seconds, Stedi marks that as a failure and then automatically retries. This can result in duplicate deliveries.

<Warning>
  We strongly recommend using idempotency in your webhook receivers to safely
  handle duplicate deliveries. See [Best practices for webhook endpoints](#best-practices-for-webhook-endpoints).
</Warning>

## Error queue

Each webhook includes an error queue. Each item in the queue consists of the original event that was attempted to be delivered. This ensures if the target service has some downtime, or anything else goes wrong, the missed events can be retried later. The error queue retains items for 14 days.

The order of the error queue is not guaranteed. The downstream service must be designed to be idempotent to handle at-least-once delivery of events, and must accept events out of order.

## Logs

To view logs, click the webhook to go to its detail page, and then navigate to the **Logs** tab.

## Deauthorized connections

If a webhook sends a message to an endpoint that returns a 401 (Unauthorized) response, the destination will be 'deauthorized'. In this state, the webhook won't be able to deliver messages.

If there is an issue with your authentication information (such as the password, API key, or OAuth settings), edit the webhook to fix it.

If the authentication information is correct, and there was a different reason for the endpoint returning a 401, you can try again by adding a temporary header. For example, `x-stedi-reauthorize` with today's date as a value. When you save, the webhook will attempt to deliver again. This header can be removed later. Editing the value of a header will also restart deliveries.

You will likely have a queue of messages to deliver, so Stedi will automatically start retrying them after you make this change. If the endpoint is still returning an invalid response, the webhook will return to `Deauthorized`.

## Best practices for webhook endpoints

When creating endpoints to receive webhooks from Stedi, we recommend the following architecture:

1. **Acknowledge first, process later**: Design your endpoint to immediately return a `2xx` status code to acknowledge receipt, then process the payload asynchronously.
2. **Store payloads for processing**: Capture the webhook data in a queue, database, or other storage mechanism before processing.
3. **Process asynchronously**: Handle the actual business logic in a separate process or worker after acknowledging receipt.
4. **Implement idempotency**: Use idempotency keys from the event payload to prevent duplicate processing.
   * Store the `eventId` from each webhook payload in your database
   * Before processing an incoming webhook, check if its `eventId` has already been processed
   * Design operations to be idempotent, ensuring that processing the same event multiple times doesn't cause issues (e.g., avoid incrementing counters on each processing attempt)

This architecture prevents [timeouts](#timeouts), handles potential duplicate deliveries, and allows you to process high volumes of events.