# Webhooks

Webhooks deliver the results of a flow to an endpoint as they are processed. An inbound flow ends in a webhook output node, so the JSON it produces from your trading partner's EDI is pushed to you rather than something you have to poll for. For the shape of that JSON, see [JSON Format](/resources/docs/json-format).

## Webhook Kinds

When you create a webhook you choose its kind, and the kind is fixed for the life of the webhook:

- **Standard**: delivers to your own HTTPS endpoint. This is what you use in production.
- **Sandbox**: delivers to an in-app sink instead of an endpoint of your own. Use it to see exactly what a real delivery looks like while you are building and testing, before you have an endpoint ready.

You cannot switch a webhook between standard and sandbox after it is created. Create a new webhook if you need the other kind.

## Creating a Webhook

1. Go to **Webhooks** and click **Add Webhook**
2. Give the webhook a **Name**
3. Choose the **Kind** (Standard or Sandbox)
4. Fill in the remaining fields, which depend on the kind:
   - **URL** (standard only): the endpoint where deliveries are sent. Must start with `http://` or `https://`.
   - **Content Type**: the content type header sent with each delivery. Defaults to `application/json`.
   - **Secret Key** (standard only): used to sign each delivery so you can verify it came from Tediware. Leave it blank to have one generated for you.
   - **API Key** (standard only): sent to your endpoint as an `X-Api-Key` header so you can authenticate the request.
   - **Tags**: optional labels for organizing your webhooks.

## Standard Webhooks

A standard webhook sends each delivery as an HTTP request to your URL. Alongside the body, Tediware sends these headers:

- `Content-Type`: the content type you configured, `application/json` by default
- `X-Webhook-Signature`: the signature used to verify the delivery
- `X-Request-ID`: a unique identifier for the delivery
- `X-Api-Key`: the API key you configured, if any

### Verifying the Signature

Each delivery is signed so you can confirm it is genuine. The signature is an HMAC-SHA256 of the signed string `<timestamp>.<body>` using your webhook's secret key, and it is sent as the `v1` value in the `X-Webhook-Signature` header. To verify a delivery, recompute the HMAC on your side and compare it to `v1`. If they match, the delivery is authentic and unmodified.

### Retries

If your endpoint does not respond in time, Tediware retries the delivery up to three times in total, waiting one second before the second attempt and two seconds before the third.

## Sandbox Webhooks

A sandbox webhook delivers to an in-app sink so you can inspect a real delivery without standing up an endpoint. Open the webhook and click **View sink** to see its deliveries.

### The Sink Page

The sink page shows the webhook's sink URL and signing secret, followed by every delivery it has captured. Each delivery shows:

- When it was received and whether its signature verified
- Its kind: **Inbound** (EDI received from a partner and translated to JSON), **Outbound** (your JSON generated into EDI), or **Error**
- The request body and headers exactly as they were sent
- A signature breakdown: the signed string, the HMAC computed from your secret, and the `v1` value from the header, so you can see verification working step by step

The list refreshes on its own, so a delivery appears shortly after you run a flow.

### The Sandbox API Key

To fetch the result behind a delivery, a consumer needs an API key. On the sink page, click **Provision sandbox API key** to create one. The key is scoped to that sink: it can only read the results delivered there and their artifacts, so it is safe to copy and experiment with. You can revoke it at any time from **API Keys**.

### Fetching Results and Artifacts

Each delivery body carries a `resultId`. The sink page gives you a ready-made command to fetch the result and each of its artifacts, and an **Execute** button that runs the call in the browser using your sandbox key. Every artifact has a usage: the input artifact is the document the flow received, and the output artifact is always the document that was delivered. When you receive EDI from a partner, the input is their EDI and the output is the delivered JSON; if the transaction setting has a mapping, the result also carries a translation artifact, the parsed JSON the mapping transformed. When you send EDI to a partner, the input is your JSON and the output is the generated EDI. If an inbound mapping fails on a document, delivery still happens, and the result's detail carries `mappingFailed: true` and a `mappingError` describing what went wrong; the output is then either the untransformed translation (the transformation failed to run) or mapped output that did not validate against the canonical shape, per `mappingError.kind` (see Mappings).

### Sandbox Flows

A flow that delivers to a sandbox webhook is always **Paused** and cannot be processed automatically. Run it yourself with **Process** while you are testing. Its captured deliveries appear inline on the flow page as well as on the sink page.

## Using Webhooks in Flows

Inbound flows deliver their results to a webhook. When you configure a partner for inbound processing, you assign the inbound webhook that the built flow delivers to. See **Flows** for how flows are built and run.
