# Inbound EDI

Inbound EDI is EDI that a trading partner sends to your organization. Tediware receives it, translates each transaction set to JSON, and notifies your system via a webhook. In most integrations, your system does nothing until the webhook fires -- Tediware handles receiving and processing the EDI automatically.

## How Inbound EDI Arrives

There are three ways EDI can arrive in Tediware:

**SFTP Polling** -- Tediware connects to the partner's SFTP server on a configurable schedule and picks up new files. This is the most common method for batch EDI exchanges. Once configured, it runs automatically with no action required from your system.

**AS2** -- The partner sends EDI directly to Tediware's AS2 endpoint. Files are processed as they arrive. Like SFTP, this is fully automatic once the connection is configured.

**API Endpoint** -- Your system receives EDI through its own channels (e.g., a vendor portal, email attachment, or another protocol) and pushes it to Tediware via the Platform API. This is an alternative for cases where your system is the one receiving the EDI, rather than Tediware. See the endpoint documentation below.

Regardless of how EDI arrives, the processing pipeline is the same. Tediware parses the interchange, splits it into individual transaction sets, translates each one to JSON, and fires your inbound webhook.

## Retrieving Translated Data

When Tediware finishes processing inbound EDI, it calls your inbound webhook with a lightweight notification. The webhook payload contains only identifiers -- not the translated document content. Your system then pulls the data through the API:

1. Your inbound webhook receives a POST with a `resultId` and `traceGuid`
2. Your system calls `GET /platform/results/:id` using the `resultId`
3. The result's `artifacts` array contains references to the processed files. The artifact with `"usage": "output"` is the delivered JSON document.
4. Your system calls `GET /platform/artifacts/:id` to download the JSON content
5. Your system processes the JSON -- creating orders, updating records, or routing to internal systems

Your webhook endpoint should return a `200` response immediately and handle the data retrieval in a background job. Tediware expects a response within 10 seconds. See the Webhooks page for payload format, signature verification, and retry behavior.

### Example: Translated 204 (Motor Carrier Load Tender)

Below is an example of the JSON you receive when downloading the output artifact for a 204 transaction set. The document is split into `heading`, `detail`, and `summary` sections. Field names are descriptive -- each includes the segment or element name followed by its X12 position code. For the full rules behind this shape, including coded and numeric values, loops, and composite elements, see the [JSON Format reference](/resources/docs/json-format).

```json
{
  "heading": {
    "transaction_set_header_ST": {
      "transaction_set_identifier_code_01": "motor_carrier_load_tender_204",
      "transaction_set_control_number_02": "100001"
    },
    "beginning_segment_for_shipment_information_transaction_B2": {
      "standard_carrier_alpha_code_02": "ABCD",
      "shipment_identification_number_04": "50001234",
      "shipment_method_of_payment_06": "collect_CC"
    },
    "set_purpose_B2A": {
      "transaction_set_purpose_code_01": "original_00",
      "application_type_02": "load_tender_truckload_tl_carrier_only_LT"
    },
    "date_time_G62": {
      "date_qualifier_01": "must_respond_by_64",
      "date_02": "2026-04-13",
      "time_qualifier_03": "must_respond_by_1",
      "time_04": "15:55:0",
      "time_code_05": "central_time_CT"
    },
    "business_instructions_and_reference_number_L11": [
      {
        "reference_identification_01": "0",
        "reference_identification_qualifier_02": "region_ACB"
      }
    ],
    "note_special_instruction_NTE": [
      {
        "description_02": "No Comments"
      }
    ],
    "party_identification_N1_loop": [
      {
        "party_identification_N1": {
          "entity_identifier_code_01": "ordered_by_OB",
          "name_02": "Acme Retail Inc",
          "identification_code_qualifier_03": "global_location_number_gln_UL",
          "identification_code_04": "0012345000008"
        }
      }
    ],
    "equipment_details_N7_loop": [
      {
        "equipment_details_N7": {
          "equipment_initial_01": "AR",
          "equipment_number_02": "0",
          "equipment_description_code_11": "trailer_dry_freight_TF",
          "equipment_length_15": 5300
        }
      }
    ]
  },
  "detail": {
    "stop_off_details_S5_loop": [
      {
        "stop_off_details_S5": {
          "stop_sequence_number_01": 1,
          "stop_reason_code_02": "complete_CL",
          "number_of_units_shipped_05": 0,
          "unit_or_basis_for_measurement_code_06": "miles_DH"
        },
        "business_instructions_and_reference_number_L11": [
          {
            "reference_identification_01": "90001234",
            "reference_identification_qualifier_02": "pickup_reference_number_P8"
          }
        ],
        "date_time_G62": [
          {
            "date_qualifier_01": "requested_ship_date_pickup_date_10",
            "date_02": "20260416"
          }
        ],
        "bill_of_lading_handling_requirements_AT5_loop": [
          {
            "bill_of_lading_handling_requirements_AT5": {
              "special_services_code_02": "mutually_defined_ZZ"
            }
          }
        ],
        "party_identification_N1_loop": [
          {
            "party_identification_N1": {
              "entity_identifier_code_01": "ship_from_SF",
              "name_02": "NORTHERN SALT DISTRIBUTION",
              "identification_code_qualifier_03": "code_assigned_by_the_organization_originating_the_transaction_set_93",
              "identification_code_04": "90001234"
            },
            "geographic_location_N4": {
              "city_name_01": "AKRON",
              "state_or_province_code_02": "OH",
              "postal_code_03": "44314"
            },
            "party_location_N3": [
              {
                "address_information_01": "100 INDUSTRIAL PARKWAY"
              }
            ],
            "contact_G61": [
              {
                "contact_function_code_01": "information_contact_IC",
                "name_02": "JANE SMITH",
                "communication_number_qualifier_03": "telephone_TE",
                "communication_number_04": "3305550100"
              },
              {
                "contact_function_code_01": "information_contact_IC",
                "name_02": "JANE SMITH",
                "communication_number_qualifier_03": "electronic_mail_EM",
                "communication_number_04": "shipping@example.com"
              }
            ]
          }
        ],
        "order_information_detail_OID_loop": [
          {
            "order_information_detail_OID": {
              "reference_identification_01": "20",
              "purchase_order_number_02": "5000100200",
              "reference_identification_03": "16",
              "packaging_form_code_04": "case_CAS",
              "quantity_05": 16,
              "weight_unit_code_06": "pounds_L",
              "weight_07": 41360,
              "volume_unit_qualifier_08": "cubic_feet_E",
              "volume_09": 729
            },
            "date_time_G62": [
              {
                "date_qualifier_01": "cancel_after_this_date_01",
                "date_02": "20260418"
              }
            ]
          }
        ]
      },
      {
        "stop_off_details_S5": {
          "stop_sequence_number_01": 2,
          "stop_reason_code_02": "complete_unload_CU",
          "number_of_units_shipped_05": 428,
          "unit_or_basis_for_measurement_code_06": "miles_DH"
        },
        "shipment_weight_packaging_and_quantity_data_AT8": {
          "weight_qualifier_01": "gross_weight_G",
          "weight_unit_code_02": "pounds_L",
          "weight_03": 41360,
          "lading_quantity_04": 16,
          "volume_unit_qualifier_06": "cubic_feet_E",
          "volume_07": 729
        },
        "business_instructions_and_reference_number_L11": [
          {
            "reference_identification_01": "60007890",
            "reference_identification_qualifier_02": "appointment_number_AO"
          }
        ],
        "date_time_G62": [
          {
            "date_qualifier_01": "delivery_appointment_scheduled_date_78",
            "date_02": "20260417",
            "time_qualifier_03": "delivery_appointment_scheduled_time_3",
            "time_04": "1931",
            "time_code_05": "eastern_time_ET"
          }
        ],
        "party_identification_N1_loop": [
          {
            "party_identification_N1": {
              "entity_identifier_code_01": "ship_to_ST",
              "name_02": "DC 7034",
              "identification_code_qualifier_03": "global_location_number_gln_UL",
              "identification_code_04": "0012345045535"
            },
            "geographic_location_N4": {
              "city_name_01": "SMYRNA",
              "state_or_province_code_02": "DE",
              "postal_code_03": "19977"
            },
            "party_location_N3": [
              {
                "address_information_01": "500 WAREHOUSE DRIVE"
              }
            ]
          }
        ],
        "order_information_detail_OID_loop": [
          {
            "order_information_detail_OID": {
              "reference_identification_01": "20",
              "purchase_order_number_02": "5000100200",
              "reference_identification_03": "16",
              "packaging_form_code_04": "case_CAS",
              "quantity_05": 16,
              "weight_unit_code_06": "pounds_L",
              "weight_07": 41360,
              "volume_unit_qualifier_08": "cubic_feet_E",
              "volume_09": 729
            },
            "date_time_G62": [
              {
                "date_qualifier_01": "cancel_after_this_date_01",
                "date_02": "20260418"
              }
            ]
          }
        ]
      }
    ]
  },
  "summary": {
    "total_weight_and_charges_L3": {
      "weight_01": 41360,
      "weight_qualifier_02": "gross_weight_G",
      "freight_rate_03": 1232.64,
      "rate_value_qualifier_04": "per_mile_PM",
      "amount_charged_05": 1232.64,
      "volume_09": 729,
      "volume_unit_qualifier_10": "cubic_feet_E",
      "lading_quantity_11": 16
    },
    "transaction_set_trailer_SE": {
      "number_of_included_segments_01": 30,
      "transaction_set_control_number_02": "100001"
    }
  }
}
```

This is a two-stop shipment: stop 1 is a pickup from a shipper in Akron, OH, and stop 2 is a delivery to a distribution center in Smyrna, DE. The `heading` contains the tender metadata and ordering party. Each entry in the `stop_off_details_S5_loop` describes a stop with its address, contacts, dates, and order details. The `summary` contains total weight and charges.

The exact fields present depend on your partner's implementation guide. Different partners may include additional segments or omit optional ones. Tediware translates whatever is in the EDI -- the JSON output always reflects the actual content of the interchange.

## Inbound Mappings

Because the translation reflects whatever the partner sent, the same document type can arrive shaped differently from different partners. If your organization has assigned an inbound mapping to a partner's transaction setting, Tediware transforms the translation into your organization's canonical shape before delivery, so the output artifact carries the same structure for every mapped partner.

The canonical shape is a canonical X12 implementation your organization owns: one implementation of that transaction set, chosen as the target every mapped partner is normalized into. It is still X12-shaped JSON, with the same segment and element names and the same bare X12 codes (`"00"`, `"SA"`) as an unmapped translation. A mapping removes the variation between partners; the X12 vocabulary stays. Discover the shape the same way as any other, by downloading the output artifact of a processed document.

That leaves the last step to you. Whether or not a mapping is assigned, what arrives is an X12 document expressed as JSON, and turning it into your own domain objects (an order, a shipment, an invoice) is your integration's job. The value of a mapping is that you write that translation once per implementation rather than once per partner.

Two things change for a consumer when a mapping is assigned:

- The output artifact is the mapped document. The untransformed translation is still available on the same result as a JSON artifact with `"usage": "translation"`; the `"input"` artifact remains the partner's EDI.
- If the mapping fails on a document, delivery still happens, and the result's `detail` carries `mappingFailed: true` and a `mappingError` describing the failure. Check the flag before parsing, and route flagged deliveries to an exception path rather than parsing them as the canonical shape. The mapping can fail two ways, distinguished by `mappingError.kind`: `"expression"` means the transformation itself failed to run, and the output is the untransformed translation; `"validation"` means the transformation ran but produced output that does not match the canonical shape, and the output is that mapped document, with `mappingError.errors` listing what failed validation. Either way, `mappingFailed` is the one flag to check: absent means the output is the validated canonical shape, present means it is not guaranteed to be.

Without a mapping, none of this applies: the output artifact is always the direct translation shown above.

## Submitting EDI via the API

This endpoint lets your system push EDI into Tediware for processing. Use it when your system receives EDI directly and needs to feed it into the same inbound processing pipeline that handles SFTP and AS2 deliveries. If your partner sends EDI to Tediware via SFTP or AS2, you do not need this endpoint.

### Endpoint

```
POST /platform/partners/:key/edi
```

- `:key` -- the partner's unique key (e.g., `ACME`). Case-insensitive: `acme` and `ACME` resolve to the same partner.

### Request Body

The request body is JSON with the following fields:

- `contents` (required) -- the raw EDI string to process. This should be a complete EDI interchange starting with an ISA segment.
- `filename` (optional) -- a label for this submission. Must contain only letters, numbers, underscores, periods, and dashes, with a maximum length of 128 characters. If omitted, a random filename is generated.

### Success Response

On success, the API returns `200` with a trace identifier:

```json
{
  "message": "Processing queued",
  "traceGuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```

- `traceGuid` -- a unique identifier that links all processing results for this submission. Use it to query results or look up the trace in the application UI.

### Example Request

```bash
curl -X POST "https://tediware.com/platform/partners/ACME/edi" \
  -H "Authorization: Key your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": "ISA*00*          *00*          *ZZ*SENDER         *ZZ*RECEIVER       *260330*1200*U*00401*000001042*0*P*>~GS*IN*SENDER*RECEIVER*20260330*1200*1043*X*004010~ST*810*0001~BIG*20260330*INV-001~SE*3*0001~GE*1*1043~IEA*1*000001042~"
  }'
```

To submit EDI from a file:

```bash
EDI_CONTENTS=$(cat my-document.edi)
curl -X POST "https://tediware.com/platform/partners/ACME/edi" \
  -H "Authorization: Key your-api-key-here" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg contents "$EDI_CONTENTS" '{"contents": $contents}')"
```

### Error Responses

```
| Status | Code                | reason                  | Cause                                                              |
|--------|---------------------|-------------------------|--------------------------------------------------------------------|
| 400    | missing_parameter   |                         | The contents field is missing or null                               |
| 400    | invalid_filename    |                         | The filename contains invalid characters or exceeds 128 characters  |
| 401    | unauthorized        |                         | The API key is missing or invalid                                   |
| 404    | not_found           | partner                 | The partner key does not match any partner in your organization     |
| 422    | configuration_error | flow_inactive           | The partner has no inbound flow set to Active                       |
| 422    | configuration_error | missing_endpoint_node   | The flow has no EDI endpoint node                                   |
| 422    | configuration_error | ambiguous_endpoint_node | The flow has more than one matching node                            |
```

As on the outbound endpoint, 400 and 404 will never succeed on an unchanged resend, while a 422 `configuration_error` will once the flow is set up. See [Errors](/resources/api-docs/errors) for the full scheme.
