X12 850 Purchase Order

The 850 is the X12 purchase order. A buyer - a retailer, distributor or manufacturer - sends it to a supplier to order goods or services, and it is the transaction most trading relationships start with.

BEG identifies the order, N1 loops name the buyer, ship-to and bill-to parties, and each PO1 loop is a line item with quantity, unit price and product identifiers. CTT closes the order with the line count.

At a glance

Standard
X12
Version
004010
Functional group
PO (GS01)
Sent by
Buyer to supplier
Responses
997, 855, 856, 810
ediFabric .NET template
TS850 in EdiFabric.Templates.X12
OpenEDI definition
View 850 in the spec library

850 structure

The full X12 850 layout from its OpenEDI definition, the same model ediFabric uses to parse, validate and generate it: 31 loops and 196 segment positions, in file order. Loops are shaded and their segments indented; Max use is how many times a segment or loop may repeat.

Segment / loop Name Usage Max use
STTransaction Set HeaderMandatory1
BEGBeginning Segment for Purchase OrderMandatory1
CURCurrencyOptional1
REFReference IdentificationOptional>1
PERAdministrative Communications ContactOptional3
TAXTax ReferenceOptional>1
FOBF.O.B. Related InstructionsOptional>1
CTPPricing InformationOptional>1
PAMPeriod AmountOptional10
CSHSales RequirementsOptional5
TC2CommodityOptional>1
SAC loopService, Promotion, Allowance, or Charge InformationOptional25
SACService, Promotion, Allowance, or Charge InformationMandatory1
CURCurrencyOptional1
ITDTerms of Sale/Deferred Terms of SaleOptional>1
DISDiscount DetailOptional20
INCInstallment InformationOptional1
DTMDate/Time ReferenceOptional10
LDTLead TimeOptional12
LINItem IdentificationOptional5
SIService Characteristic IdentificationOptional>1
PIDProduct/Item DescriptionOptional200
MEAMeasurementsOptional40
PWKPaperworkOptional25
PKGMarking, Packaging, LoadingOptional200
TD1Carrier Details (Quantity and Weight)Optional2
TD5Carrier Details (Routing Sequence/Transit Time)Optional12
TD3Carrier Details (Equipment)Optional12
TD4Carrier Details (Special Handling, or Hazardous Materials, or Both)Optional5
MANMarks and NumbersOptional10
PCTPercent AmountsOptional>1
CTBRestrictions/ConditionsOptional5
TXITax InformationOptional>1
AMT loopMonetary AmountOptional>1
AMTMonetary AmountMandatory1
REFReference IdentificationOptional>1
DTMDate/Time ReferenceOptional1
PCTPercent AmountsOptional>1
FA1 loopType of Financial Accounting DataOptional>1
FA1Type of Financial Accounting DataMandatory1
FA2Accounting DataMandatory>1
N9 loopReference IdentificationOptional1000
N9Reference IdentificationMandatory1
DTMDate/Time ReferenceOptional>1
MSGMessage TextOptional1000
N1 loopNameOptional200
N1NameMandatory1
N2Additional Name InformationOptional2
N3Address InformationOptional2
N4Geographic LocationOptional>1
NX2Location ID ComponentOptional>1
REFReference IdentificationOptional12
PERAdministrative Communications ContactOptional>1
SIService Characteristic IdentificationOptional>1
FOBF.O.B. Related InstructionsOptional1
TD1Carrier Details (Quantity and Weight)Optional2
TD5Carrier Details (Routing Sequence/Transit Time)Optional12
TD3Carrier Details (Equipment)Optional12
TD4Carrier Details (Special Handling, or Hazardous Materials, or Both)Optional5
PKGMarking, Packaging, LoadingOptional200
LM loopCode Source InformationOptional>1
LMCode Source InformationMandatory1
LQIndustry CodeMandatory>1
SPI loopSpecification IdentifierOptional>1
SPISpecification IdentifierMandatory1
REFReference IdentificationOptional5
DTMDate/Time ReferenceOptional5
MSGMessage TextOptional50
N1 loopNameOptional20
N1NameMandatory1
N2Additional Name InformationOptional2
N3Address InformationOptional2
N4Geographic LocationOptional1
REFReference IdentificationOptional20
G61ContactOptional1
MSGMessage TextOptional50
CB1 loopContract and Cost Accounting Standards DataOptional>1
CB1Contract and Cost Accounting Standards DataMandatory1
REFReference IdentificationOptional20
DTMDate/Time ReferenceOptional5
LDTLead TimeOptional1
MSGMessage TextOptional50
ADV loopAdvertising Demographic InformationOptional>1
ADVAdvertising Demographic InformationMandatory1
DTMDate/Time ReferenceOptional>1
MTXTextOptional>1
PO1 loopBaseline Item DataMandatory100000
PO1Baseline Item DataMandatory1
LINItem IdentificationOptional>1
SIService Characteristic IdentificationOptional>1
CURCurrencyOptional1
CN1Contract InformationOptional1
PO3Additional Item DetailOptional25
CTP loopPricing InformationOptional>1
CTPPricing InformationMandatory1
CURCurrencyOptional1
PAMPeriod AmountOptional10
MEAMeasurementsOptional40
PID loopProduct/Item DescriptionOptional1000
PIDProduct/Item DescriptionMandatory1
MEAMeasurementsOptional10
PWKPaperworkOptional25
PO4Item Physical DetailsOptional>1
REFReference IdentificationOptional>1
PERAdministrative Communications ContactOptional3
SAC loopService, Promotion, Allowance, or Charge InformationOptional25
SACService, Promotion, Allowance, or Charge InformationMandatory1
CURCurrencyOptional1
CTPPricing InformationOptional1
IT8Conditions of SaleOptional1
CSHSales RequirementsOptional>1
ITDTerms of Sale/Deferred Terms of SaleOptional2
DISDiscount DetailOptional20
INCInstallment InformationOptional1
TAXTax ReferenceOptional>1
FOBF.O.B. Related InstructionsOptional>1
SDQDestination QuantityOptional500
IT3Additional Item DataOptional5
DTMDate/Time ReferenceOptional10
TC2CommodityOptional>1
TD1Carrier Details (Quantity and Weight)Optional1
TD5Carrier Details (Routing Sequence/Transit Time)Optional12
TD3Carrier Details (Equipment)Optional12
TD4Carrier Details (Special Handling, or Hazardous Materials, or Both)Optional5
PCTPercent AmountsOptional>1
MANMarks and NumbersOptional10
MSGMessage TextOptional>1
SPISpecification IdentifierOptional>1
TXITax InformationOptional>1
CTBRestrictions/ConditionsOptional>1
QTY loopQuantityOptional>1
QTYQuantityMandatory1
SIService Characteristic IdentificationOptional>1
SCH loopLine Item ScheduleOptional200
SCHLine Item ScheduleMandatory1
TD1Carrier Details (Quantity and Weight)Optional2
TD5Carrier Details (Routing Sequence/Transit Time)Optional12
TD3Carrier Details (Equipment)Optional12
TD4Carrier Details (Special Handling, or Hazardous Materials, or Both)Optional5
REFReference IdentificationOptional>1
PKG loopMarking, Packaging, LoadingOptional200
PKGMarking, Packaging, LoadingMandatory1
MEAMeasurementsOptional>1
LS loopLoop HeaderOptional1
LSLoop HeaderMandatory1
LDT loopLead TimeOptional>1
LDTLead TimeMandatory1
QTYQuantityOptional>1
MSGMessage TextOptional1
REFReference IdentificationOptional3
LM loopCode Source InformationOptional>1
LMCode Source InformationMandatory1
LQIndustry CodeMandatory>1
LELoop TrailerMandatory1
N9 loopReference IdentificationOptional1000
N9Reference IdentificationMandatory1
DTMDate/Time ReferenceOptional>1
MEAMeasurementsOptional40
MSGMessage TextOptional1000
N1 loopNameOptional200
N1NameMandatory1
N2Additional Name InformationOptional2
N3Address InformationOptional2
N4Geographic LocationOptional1
QTYQuantityOptional>1
NX2Location ID ComponentOptional>1
REFReference IdentificationOptional12
PERAdministrative Communications ContactOptional3
SIService Characteristic IdentificationOptional>1
DTMDate/Time ReferenceOptional1
FOBF.O.B. Related InstructionsOptional1
SCHLine Item ScheduleOptional200
TD1Carrier Details (Quantity and Weight)Optional2
TD5Carrier Details (Routing Sequence/Transit Time)Optional12
TD3Carrier Details (Equipment)Optional12
TD4Carrier Details (Special Handling, or Hazardous Materials, or Both)Optional5
PKGMarking, Packaging, LoadingOptional200
LDT loopLead TimeOptional>1
LDTLead TimeMandatory1
MANMarks and NumbersOptional10
QTYQuantityOptional5
MSGMessage TextOptional1
REFReference IdentificationOptional3
SLN loopSubline Item DetailOptional1000
SLNSubline Item DetailMandatory1
MSGMessage TextOptional>1
SIService Characteristic IdentificationOptional>1
PIDProduct/Item DescriptionOptional1000
PO3Additional Item DetailOptional104
TC2CommodityOptional>1
ADVAdvertising Demographic InformationOptional>1
DTMDate/Time ReferenceOptional10
CTPPricing InformationOptional25
PAMPeriod AmountOptional10
PO4Item Physical DetailsOptional1
TAXTax ReferenceOptional3
N9 loopReference IdentificationOptional>1
N9Reference IdentificationMandatory1
DTMDate/Time ReferenceOptional>1
MSGMessage TextOptional>1
SAC loopService, Promotion, Allowance, or Charge InformationOptional25
SACService, Promotion, Allowance, or Charge InformationMandatory1
CURCurrencyOptional1
CTPPricing InformationOptional1
QTY loopQuantityOptional>1
QTYQuantityMandatory1
SIService Characteristic IdentificationOptional>1
N1 loopNameOptional10
N1NameMandatory1
N2Additional Name InformationOptional2
N3Address InformationOptional2
N4Geographic LocationOptional1
NX2Location ID ComponentOptional>1
REFReference IdentificationOptional12
PERAdministrative Communications ContactOptional3
SIService Characteristic IdentificationOptional>1
AMT loopMonetary AmountOptional>1
AMTMonetary AmountMandatory1
REFReference IdentificationOptional1
PCTPercent AmountsOptional>1
LM loopCode Source InformationOptional>1
LMCode Source InformationMandatory1
LQIndustry CodeMandatory>1
CTT loopTransaction TotalsOptional1
CTTTransaction TotalsMandatory1
AMTMonetary AmountOptional1
SETransaction Set TrailerMandatory1

Mandatory segments must be sent, Optional ones only when the data applies. Trading partners often add their own rules in companion guides - ediFabric templates can be adjusted to match. Open the element-level definition in the EdiNation spec library.

Sample 850 file

A tax-exempt purchase order for one line item, from the X12 examples. Paste it into EdiNation to see every element named and validated.

ISA*00*          *00*          *16*SENDER1        *1B*RECEIVER1      *071216*1406*U*00204*000000263*1*T*>~
GS*IN*SENDER1*RECEIVER1*20071216*1406*000000001*X*004010~
ST*850*0001~
BEG*00*SA*XX-1234**20170301**NA~
PER*BD*ED SMITH*TE*8001234567~
TAX*53247765*SP*CA*********9~
N1*BY*ABC AEROSPACE*9*1234567890101~
N2*AIRCRAFT DIVISION~
N3*2000 JET BLVD~
N4*FIGHTER TOWN*CA*98898~
PO1*1*25*EA*36*PE*MG*XYZ-1234~
MEA*WT*WT*10*OZ~
IT8*******B0~
SCH*25*EA***106*20170615~
CTT*1~
AMT*TT*900~
SE*15*0001~
GE*1*000000001~
IEA*1*000000263~

The same 850 as JSON

ediFabric turns every loop, segment and element into a named field. This is the transaction from the sample, in the JSON that ediFabric Native and Cloud return and accept.

{
  "ST": {
    "TransactionSetIdentifierCode_01": "850",
    "TransactionSetControlNumber_02": "0001"
  },
  "BEG": {
    "TransactionSetPurposeCode_01": "00",
    "PurchaseOrderTypeCode_02": "SA",
    "PurchaseOrderNumber_03": "XX-1234",
    "Date_05": "20170301",
    "AcknowledgmentType_07": "NA"
  },
  "PER": [
    {
      "ContactFunctionCode_01": "BD",
      "Name_02": "ED SMITH",
      "CommunicationNumberQualifier_03": "TE",
      "CommunicationNumber_04": "8001234567"
    }
  ],
  "TAX": [
    {
      "TaxIdentificationNumber_01": "53247765",
      "LocationQualifier_02": "SP",
      "LocationIdentifier_03": "CA",
      "TaxExemptCode_12": "9"
    }
  ],
  "N1Loop": [
    {
      "N1": {
        "EntityIdentifierCode_01": "BY",
        "Name_02": "ABC AEROSPACE",
        "IdentificationCodeQualifier_03": "9",
        "IdentificationCode_04": "1234567890101"
      },
      "N2": [
        {
          "Name_01": "AIRCRAFT DIVISION"
        }
      ],
      "N3": [
        {
          "AddressInformation_01": "2000 JET BLVD"
        }
      ],
      "N4": [
        {
          "CityName_01": "FIGHTER TOWN",
          "StateorProvinceCode_02": "CA",
          "PostalCode_03": "98898"
        }
      ]
    }
  ],
  "PO1Loop": [
    {
      "PO1": {
        "AssignedIdentification_01": "1",
        "QuantityOrdered_02": "25",
        "UnitorBasisforMeasurementCode_03": "EA",
        "UnitPrice_04": "36",
        "BasisofUnitPriceCode_05": "PE",
        "ProductServiceIDQualifier_06": "MG",
        "ProductServiceID_07": "XYZ-1234"
      },
      "MEA": [
        {
          "MeasurementReferenceIDCode_01": "WT",
          "MeasurementQualifier_02": "WT",
          "MeasurementValue_03": "10",
          "CompositeUnitofMeasure_04": {
            "UnitorBasisforMeasurementCode_01": "OZ"
          }
        }
      ],
      "IT8": {
        "ProductServiceSubstitutionCode_07": "B0"
      },
      "SCHLoop": [
        {
          "SCH": {
            "Quantity_01": "25",
            "UnitorBasisforMeasurementCode_02": "EA",
            "DateTimeQualifier_05": "106",
            "Date_06": "20170615"
          }
        }
      ]
    }
  ],
  "CTTLoop": {
    "CTT": {
      "NumberofLineItems_01": "1"
    },
    "AMT": {
      "AmountQualifierCode_01": "TT",
      "MonetaryAmount_02": "900"
    }
  },
  "SE": {
    "NumberofIncludedSegments_01": "15",
    "TransactionSetControlNumber_02": "0001"
  }
}

Parse and validate an 850 file

Read the file into typed objects with ediFabric .NET, convert it to JSON in process with the ediFabric Native bindings for Python, Java and C, or post it to the ediFabric Cloud REST API from any language.

using EdiFabric.Templates.X12004010;

License.SetSerial("YOUR_SERIAL_KEY");

using (var stream = File.OpenRead(@"C:\edi\PurchaseOrder.txt"))
using (var reader = new X12Reader(stream, "EdiFabric.Templates.X12"))
{
    var items = await reader.ReadToEndAsync();
    foreach (var transaction in items.OfType<TS850>())
    {
        if (transaction.IsValid(out MessageErrorContext errors))
            Console.WriteLine($"{transaction.ST.TransactionSetControlNumber_02} is valid");
        else
            Console.WriteLine(string.Join(Environment.NewLine, errors.Flatten()));
    }
}
import json
import edifabric_x12 as ef

serial = "YOUR_SERIAL_KEY"
ef.load_library()
ef.set_serial(serial)
ef.set_map(json.dumps({"default": serial, "maps": {}}))

edi = open("PurchaseOrder.txt", "rb").read()
output, offset = ef.parse(edi, ef.ParseMode.JSON_VALIDATE)
transactions = output[:offset]
report = json.loads(output[offset:])
print(report["errors_count"])
import com.edifabric.nativex12.EdiFabricX12;
import com.edifabric.nativex12.ParseMode;
import com.edifabric.nativex12.ParseResult;

String serial = "YOUR_SERIAL_KEY";
EdiFabricX12.loadLibrary();
EdiFabricX12.setSerial(serial);
EdiFabricX12.setMap("{\"default\":\"" + serial + "\",\"maps\":{}}");

String edi = Files.readString(Path.of("PurchaseOrder.txt"));
ParseResult result = EdiFabricX12.parse(edi, ParseMode.JSON_VALIDATE);
System.out.println(result.getTransactions());
System.out.println(result.getReport());
#include "edifabric_x12.h"

const char *serial = "YOUR_SERIAL_KEY";
ef_parse_result result;

if (ef_load_library(NULL) != 0)
    return 1;
ef_set_serial(serial);
ef_set_map("{\"default\":\"YOUR_SERIAL_KEY\",\"maps\":{}}");

char *edi = read_file("PurchaseOrder.txt", NULL);   /* helper in example_all_functions.c */
if (ef_parse(edi, EF_PARSE_JSON_VALIDATE, NULL, &result) == 0) {
    /* transactions = output[0 .. offset), report = output[offset .. length) */
    fwrite(result.output.data, 1, (size_t)result.output.length, stdout);
    ef_free(result.output.data);
}
curl -X POST 'https://api.edination.com/v2/x12/read' \
-H 'Ocp-Apim-Subscription-Key: YOUR_SERIAL_KEY' \
-H 'Content-Type: application/octet-stream' \
--data-binary '@PurchaseOrder.txt'

Generate an 850 file

Populate a TS850 object in .NET, or pass JSON in the shape shown above to ediFabric Native or ediFabric Cloud, and get a valid 850 file back.

using EdiFabric.Templates.X12004010;

License.SetSerial("YOUR_SERIAL_KEY");

var transaction = new TS850();

//  Indicates the start of a purchase order transaction set and assigns a control number.
transaction.ST = new ST();
transaction.ST.TransactionSetIdentifierCode_01 = "850";
transaction.ST.TransactionSetControlNumber_02 = "0001";

//  Indicates that this is original purchase order number XX-1234, dated March 1, 2017, and that no acknowledgment is necessary.
transaction.BEG = new BEG();
transaction.BEG.TransactionSetPurposeCode_01 = "00";
transaction.BEG.PurchaseOrderTypeCode_02 = "SA";
transaction.BEG.PurchaseOrderNumber_03 = "XX-1234";
transaction.BEG.Date_05 = "20170301";
transaction.BEG.AcknowledgmentType_07 = "NA";

//  Repeating PER
transaction.PER = new List<PER>();

// ... set the remaining loops and segments the same way

// SegmentBuilders is in the Common project of the example repository
using (var stream = new MemoryStream())
{
    using (var writer = new X12Writer(stream))
    {
        writer.Write(SegmentBuilders.BuildIsa("1"));
        writer.Write(SegmentBuilders.BuildGs("1"));
        writer.Write(transaction);
    }
    Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));
}
import json
import edifabric_x12 as ef

serial = "YOUR_SERIAL_KEY"
ef.load_library()
ef.set_serial(serial)
ef.set_map(json.dumps({"default": serial, "maps": {}}))

# the transactions JSON returned by ef.parse, edited or produced by your application
transactions = open("PurchaseOrder.json", "rb").read()
edi = ef.build(transactions, postfix="\r\n")
print(edi)
import com.edifabric.nativex12.EdiFabricX12;

String serial = "YOUR_SERIAL_KEY";
EdiFabricX12.loadLibrary();
EdiFabricX12.setSerial(serial);
EdiFabricX12.setMap("{\"default\":\"" + serial + "\",\"maps\":{}}");

// the transactions JSON returned by parse, edited or produced by your application
String transactions = Files.readString(Path.of("PurchaseOrder.json"));
String edi = EdiFabricX12.build(transactions, "\r\n");
System.out.println(edi);
#include "edifabric_x12.h"

ef_buffer edi;

if (ef_load_library(NULL) != 0)
    return 1;
ef_set_serial("YOUR_SERIAL_KEY");
ef_set_map("{\"default\":\"YOUR_SERIAL_KEY\",\"maps\":{}}");

/* the transactions JSON returned by ef_parse, edited or produced by your application */
char *transactions = read_file("PurchaseOrder.json", NULL);
if (ef_build(transactions, "\r\n", &edi) == 0) {
    fwrite(edi.data, 1, (size_t)edi.length, stdout);
    ef_free(edi.data);
}
# the JSON returned by /read, edited or produced by your application
curl -X POST 'https://api.edination.com/v2/x12/write' \
-H 'Ocp-Apim-Subscription-Key: YOUR_SERIAL_KEY' \
-H 'Content-Type: application/json' \
--data-binary '@PurchaseOrder.json' \
-o 'PurchaseOrder.txt'

850 questions

What documents follow an 850?

The supplier returns a 997 functional acknowledgment, often an 855 purchase order acknowledgment, then an 856 ship notice when the goods ship and an 810 invoice.

How do I change or cancel an 850?

With an 860 purchase order change request, or by resending the 850 with BEG01 set to 01 (cancellation) or 05 (replace) when the trading partner allows it.

Why do retailers have their own 850 specifications?

The X12 standard is broad, so each trading partner publishes an implementation guide with the segments, qualifiers and codes it uses. ediFabric templates can be adjusted to match.

How do I parse and generate X12 850 files in .NET, Python, Java and C?

In .NET, install EdiFabric and EdiFabric.Templates.X12, read the file with X12Reader into TS850 objects and write them back with X12Writer. From Python, Java or C, use ediFabric Native, which converts 850 files to JSON and JSON back to X12 inside your process. From any other language, post the file to the ediFabric Cloud REST API.

Parse your first 850 in five minutes

The Community plan is free forever and needs no credit card. It includes ediFabric .NET, Native and Cloud.