EDIFACT transport patterns
Receive and send EDIFACT over the mailbox networks, file drops and HTTP endpoints your trading partners use.
An EDIFACT interchange travels over the carrier the trading partners agreed on - a mailbox network, a file drop, an HTTP endpoint or email - so there is no dedicated EDIFACT connection type. The UNB-UNZ envelope holds the addressing, the channel that receives the text invokes your service with it, and self.request.edifact is the interchange parsed into typed messages, whichever channel delivered it.
Unlike HL7 v2 over MLLP, where the protocol includes a live socket and an acknowledgment loop, EDIFACT networks are store-and-forward - delivering to the network is the transport-level confirmation.
The transport patterns
- Mailbox networks - national or sector-wide networks give every participant a mailbox, and clients poll for inbound messages over an HTTP-based API, commonly SOAP or REST. Dutch healthcare, for example, exchanges its EDIFACT traffic this way.
- File drops - a shared directory, an SMB share, or an SFTP server where one side writes interchange files and the other picks them up.
- Direct APIs - a partner exposes an HTTP endpoint that accepts the interchange text as the request body.
- Email - the oldest pattern, one interchange per message, still in use between long-standing partners.
Zato covers each with connections it already has - REST and SOAP outgoing connections, file transfer channels, SFTP, IMAP and SMTP connections, and scheduler jobs for polling.
Receiving from a mailbox
A scheduler job polls the mailbox API, and each retrieved interchange goes through the same parsing path. The job reads the provider's address from an outgoing REST connection. Create the connection under Connections > Outgoing > REST, with EDI Mailbox as its name:
The service lists pending messages, retrieves each one and parses it. Mailbox providers differ in the details of their APIs, but the poll takes this shape:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
from zato.edifact import parse_edifact
# Registers the example dialect - use your own here
import zato.edifact.nl
class PollMailbox(Service):
name = 'demo.edifact.poll-mailbox'
def handle(self) -> 'None':
# An outgoing REST connection to the mailbox provider
conn = self.rest['EDI Mailbox']
# List and retrieve pending messages ..
response = conn.get(self.cid, {'action': 'list'})
for item in response.data['messages']:
wire_text = item['body']
# .. parse each interchange ..
interchange = parse_edifact(wire_text)
# .. and log who sent it and how many messages it carries.
sender = interchange.header.sender.identification
count = len(interchange.messages)
self.logger.info('Received %d messages from %s', count, sender)
Receiving from a file drop
A file transfer channel picks up interchange files as they appear and invokes a service with each file. The service reads the parsed interchange from self.request.edifact:
class HandleFile(Service):
name = 'demo.edifact.handle-file'
def handle(self) -> 'None':
# The channel read the file and the request parsed it
interchange = self.request.edifact
for msg in interchange.messages:
message_type = msg.unh.identifier.message_type
self.logger.info('Received %s', message_type)
Receiving over email
An IMAP connection with a schedule invokes a service once per new e-mail. An interchange sent this way travels as the plain-text body of the e-mail and self.request.edifact reads it from there:
class HandleEmail(Service):
name = 'demo.edifact.handle-email'
def handle(self) -> 'None':
interchange = self.request.edifact
# A bare message without a UNB envelope has no header - the message itself says who sent it
report = interchange.message
self.logger.info('Received %s', report.unh.identifier.message_type)
Receiving over HTTP
A partner posting interchanges directly uses a REST channel, where the request body is the interchange text, or a SOAP channel, where the text is the content of the operation element. The service is the same in both cases:
class HandleHTTP(Service):
name = 'demo.edifact.handle-http'
def handle(self) -> 'None':
interchange = self.request.edifact
sender = interchange.header.sender.identification
count = len(interchange.messages)
self.logger.info('Received %d messages from %s', count, sender)
Where the text comes from
self.request.edifact parses the interchange once, on first access, and every later access returns the same object. The text it parses depends on the channel:
- File transfer - the bytes of the received file
- IMAP - the first plain-text part of the e-mail
- REST, MLLP, AMQP, Kafka, IBM MQ - the request body, as text or bytes
- SOAP - the text of the operation element inside the SOAP body, or the text of its single child element
Bytes are decoded by the syntax identifier in the UNB header - UNOA and UNOB as ASCII, UNOC as ISO-8859-1, UNOD as ISO-8859-2, UNOE as ISO-8859-5, UNOF as ISO-8859-7 and UNOY as UTF-8. Bare messages without a UNB header decode as ISO-8859-1.
Text that reaches the service some other way, e.g. as the response to an outgoing call as in the mailbox example above, goes through parse_edifact directly.
Sending
Serialization produces the wire text, and any outgoing connection delivers it:
# Zato
from zato.edifact.nl import MEDVRI
from zato.edifact.nl.segments import TXT
class SendReply(Service):
name = 'demo.edifact.send-reply'
def handle(self) -> 'None':
# A short free-text message confirming the results arrived ..
reply = MEDVRI()
# .. its UNH header carries the reference and the message identity ..
reply.unh.reference_number = '8002'
reply.unh.identifier.message_type = 'MEDVRI'
reply.unh.identifier.version = '1'
# .. the sender and the date follow ..
reply.sender.person_name = 'E. Vermeer'
reply.sender.institution_name = 'GGZ De Linde'
reply.det.date.year = '26'
reply.det.date.month = '08'
reply.det.date.day = '31'
# .. the text is one TXT segment per line ..
line = TXT()
line.text = 'Results received, thank you'
reply.text = [line]
# .. and the UNT trailer closes the message.
reply.unt.segment_count = '5'
reply.unt.reference_number = '8002'
# Serialization produces the wire text ..
wire_text = reply.serialize()
# .. an outgoing REST connection delivers it ..
conn = self.rest['EDI Mailbox']
_ = conn.post(self.cid, wire_text)
# .. an outgoing REST connection delivers it ..
conn = self.rest['EDI Mailbox']
# .. so do send it now.
_ = conn.post(self.cid, wire_text)
Acknowledgments
EDIFACT has service messages for acknowledgments (CONTRL, APERAK), but many networks - healthcare mailbox networks among them - do not use them, relying on the network's own delivery guarantees instead. If a partner does require them, they are ordinary messages: define their classes per Dialects and profiles, build them like any other message, and send them back over the same carrier.
See also
| Page | What it covers |
|---|---|
| Message parsing | What parse_edifact does with the text a carrier delivers |
| Scheduler examples | Creating the jobs that poll mailboxes on a schedule |
| EDIFACT in healthcare tutorial | A REST channel receiving lab results and a letter going out |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines