Not a translator.
A boundary.

Most EDI tools translate EDIFACT into something slightly less painful. CleanEDI does something different. It acts as an anti-corruption layer, a hard architectural boundary that absorbs everything messy on one side and only lets clean, stable business data through the other.

Your systems never know EDIFACT exists.

Try the decoderSee pricing

Everything messy stays on one side

CleanEDI owns the left side completely. You own the right side completely. Nothing crosses without being transformed into a clean business object first.

Trading partner side
Raw EDIFACT segments and qualifiers
Version differences (D96A, D01B, D10A)
EANCOM vs UN/EDIFACT variants
Non-standard qualifier usage
Missing mandatory segments
Malformed terminators and encoding
Partner-specific field positions
CONTRL acknowledgement generation
AS2 and SFTP transport
Duplicate message detection
Retry and dead-letter handling
CleanEDI boundary
Your system side
Clean JSON or XML business objects
Stable, predictable field names
Your naming conventions
Your unit of measure codes
Your date formats
Typed fields with proper null handling
Computed and derived fields
Injected static values
Validated GLNs and GTINs
Cross-validated totals and counts
Standard REST or webhook delivery

Inside the pipeline

01

Message arrives

An inbound EDIFACT interchange arrives from your trading partner via AS2 or SFTP. It might be EANCOM D01B, UN/EDIFACT D96A, single-line with no segment terminators, or carrying non-standard qualifiers specific to that partner. CleanEDI accepts it as-is.

Raw EDIFACT
UNA:+.? 'UNB+UNOA:2+9311...'UNH+1+ORDERS...'BGM+220+PO12345+9'...
02

Parser normalises

The message is normalised before parsing. Missing segment terminators are added. CRLF line endings are handled. BOM variants are stripped. Tab characters are removed. The message is then parsed by our engine into a structured segment tree.

Parsed structure
EdifactInterchange → Messages → Segments → Elements → Composites
03

Mapper produces canonical

The segment tree is mapped to a canonical business object. ORDERS becomes a PurchaseOrder with typed fields. NAD+BY becomes a Buyer with a GLN, name, and address. DTM+137 becomes an orderDate. Every segment has a home. Unrecognised segments are noted as warnings, not errors.

Canonical object
{ orderId, orderDate, buyer: { gln, name, address }, lines: [...] }
04

Partner rules apply

Each trading partner has a configuration that captures their quirks. Company A uses MOA+128 instead of MOA+86 for the total. A retailer puts GLNs in a non-standard element position. These are rules in configuration, not changes to code. The canonical output is normalised regardless.

Partner config
MOA+128 → totalAmount GLN position override Default currency: AUD
05

Transformation rules apply

Your integration rules run next. Field renames, value translations, computed fields, static injections, and date formatting all happen here. orderId becomes purchaseOrderNumber. PCE becomes EA. unitPrice × quantity becomes calculatedLineTotal. Your API shape, not ours.

Your rules
orderId → purchaseOrderNumber PCE → EA quantity × unitPrice → lineTotal
06

Delivery to your system

The transformed payload is delivered to your endpoint via webhook POST, dropped onto your message queue, or made available via REST. JSON, XML, or CSV. HMAC signed. Retry with exponential backoff. Dead-letter handling for persistent failures. A CONTRL acknowledgement is sent back to the trading partner automatically.

Your endpoint
POST https://your-api.com/orders Content-Type: application/json X-CleanEDI-Signature: sha256=...

A real business object, not a segment dump

The canonical output is a typed business object that maps directly to how your domain thinks about the transaction. An ORDERS message becomes a PurchaseOrder with a Buyer, a Supplier, and a list of OrderLines.

Every field has a defined type. Dates are DateOnly. Amounts are decimal. Nullable fields are explicitly nullable. Your code can rely on the schema.

Cross-validation runs automatically. If the line count in CNT does not match the actual LIN count, a warning is added. If line totals do not reconcile with the summary MOA, a warning is added. You get good data with context, not a silent failure.

See it live in the decoder
ORDERS canonical output (abbreviated)
{  "orderId": "PO-2026-98745",  "documentType": "220",  "messageFunction": "9",  "orderDate": "2026-08-23",  "requestedDeliveryDate": "2026-09-05",  "currency": "AUD",  "paymentTerms": "Net 30 days",  "buyer": {    "gln": "9311000000123",    "name": "MEGA MART PTY LTD",    "abn": "61123456789",    "address": {      "street": "100 RETAIL WAY",      "city": "MELBOURNE",      "state": "VIC",      "postalCode": "3000",      "countryCode": "AU"    },    "contact": {      "name": "JANE SMITH",      "email": "jane@retailer.example"    }  },  "supplier": { ... },  "lines": [    {      "lineNumber": 1,      "gtin": "9312345678901",      "productDescription": "PREMIUM CHOCOLATE BOX 250G",      "quantity": 120,      "unitOfMeasure": "PCE",      "unitPrice": 8.45,      "lineAmount": 1014.00,      "tax": { "taxType": "VAT", "rate": 10 }    }  ],  "summary": {    "totalLines": 4,    "totalAmount": 2405.00,    "totalAmountExcludingTax": 2186.36,    "totalTaxAmount": 218.64  }}

You define what crosses the boundary

The canonical model is CleanEDI's internal representation. What your system receives is your version of it, shaped entirely by your transformation rules. Six rule types let you define the exact contract between CleanEDI and your system.

Field renames
orderId → purchaseOrderNumber

Rename any field to match your system's naming conventions.

Value translations
PCE → EA

Translate EDIFACT code values to the codes your system expects.

Computed fields
quantity × unitPrice → lineTotal

Calculate and inject derived values before delivery.

Field removal
remove: grossPrice, envelope

Strip fields your API does not accept to avoid validation errors.

Static injection
source: EDI, tenantId: EXAMPLERETAIL

Add fixed values to every message for tagging and routing.

Date formatting
orderDate → DD/MM/YYYY

Reformat dates and numbers to the shape your system expects.

Try the live transformation demo →

How it actually works

What is an anti-corruption layer?

An anti-corruption layer is a design pattern from domain-driven design. It is a translation boundary between two systems with different models and languages. Without it, the complexity and assumptions of one system leak into the other. CleanEDI acts as this boundary between EDIFACT's document-centric model and your system's business-object model. Your code is never exposed to EDIFACT concepts.

What happens when a trading partner changes their EDIFACT implementation?

You update the partner configuration in CleanEDI. Your code does not change. The canonical output remains the same shape. This is the core value of the architectural boundary: changes on the EDIFACT side do not propagate to your system. You own the right side of the boundary.

What happens when a message has errors or non-standard content?

CleanEDI returns a canonical result alongside a warnings list. Warnings describe what was found but not mapped, what validation rules were violated, and what assumptions were made. The canonical output still contains everything that could be mapped. Your system receives good data with context rather than a hard failure.

Is the canonical model fixed or can we change it?

The canonical model is CleanEDI's internal representation. What you receive is your transformed version of it, shaped by your integration rules. Field names, value codes, date formats, and even the structure can be adjusted through your rule configuration. You define the contract on your side of the boundary.

How are trading partner quirks handled without changing code?

Each trading partner has a configuration record in CleanEDI that captures their specific behaviour. Non-standard qualifier mappings, default values for missing segments, field position overrides, and version-specific rules are all stored as configuration. When a new quirk is discovered, it is added to that partner's configuration. No deployment required.

What EDIFACT message types does the platform support?

ORDERS (purchase orders), DESADV (despatch advice/ASN), INVOIC (tax invoices and credit notes), and CONTRL (functional acknowledgements) are fully supported. ORDRSP, RECADV, PRICAT, and DELFOR are in development. The canonical model and pipeline work the same way for all message types.

See the boundary in action

Paste any EDIFACT message into the free decoder. See what the canonical model produces and how transformation rules reshape it for your system.

Try the decoderSee pricing