The 997 functional acknowledgment is the transaction set that tells you whether the last thing you sent was accepted. When it says "rejected", the useful information is buried in AK3, AK4, and AK5 — and those are numeric codes with no text explanation.
ST*997*0001~
AK1*PO*1~
AK2*850*0001~
AK3*PO1*12**8~
AK4*4**7*ABC~
AK5*R*5~
AK9*R*1*1*0~
SE*8*0001~
Read from the bottom up and it says: one transaction set received, zero accepted, rejected because of an element error in the twelfth segment.
AK1*PO*1 — acknowledging functional group PO (purchase orders) with group control number 1. That number must match the GS06 of the group you sent.
AK2*850*0001 — specifically the 850 with transaction set control number 0001, matching your ST02.
AK3*PO1*12**8~
AK301 = PO1 — the segment ID at fault.AK302 = 12 — its position in the transaction set, counting ST as 1.AK303 — loop identifier, empty here.AK304 = 8 — the segment syntax error code.| AK304 | Meaning |
|---|---|
| 1 | Unrecognised segment ID |
| 2 | Unexpected segment |
| 3 | Mandatory segment missing |
| 4 | Loop occurs over maximum times |
| 5 | Segment exceeds maximum use |
| 6 | Segment not in defined transaction set |
| 7 | Segment not in proper sequence |
| 8 | Segment has data element errors |
Code 8 is a pointer, not a diagnosis — it means "look at the AK4 that follows".
AK4*4**7*ABC~
AK401 = 4 — element position within the segment. So PO104, the unit price.AK402 — X12 data element reference number, often omitted.AK403 = 7 — the data element syntax error code.AK404 = ABC — a copy of the offending data.| AK403 | Meaning |
|---|---|
| 1 | Mandatory data element missing |
| 2 | Conditional required data element missing |
| 3 | Too many data elements |
| 4 | Data element too short |
| 5 | Data element too long |
| 6 | Invalid character in data element |
| 7 | Invalid code value |
| 8 | Invalid date |
| 9 | Invalid time |
| 10 | Exclusion condition violated |
So the full reading: the twelfth segment is a PO1; its fourth element contained ABC, which is not a valid code value. A unit price of ABC — almost always a mapper writing a string where a number belongs.
AK5 is the verdict on one transaction set. AK501 carries the code:
| AK501 | Meaning |
|---|---|
A | Accepted |
E | Accepted, but errors were noted |
R | Rejected |
M | Rejected — message authentication code failed |
W | Rejected — assurance failed on validity tests |
X | Rejected — content could not be analysed after decryption |
AK9 is the verdict on the whole functional group: AK9*R*1*1*0 means rejected, 1 transaction set included, 1 received, 0 accepted.
The distinction that catches people: AK501 = E means the partner accepted your document despite noting errors. You do not need to resend. Teams that treat any AK3 presence as failure end up sending duplicates.
The whole exercise is turning AK302 = 12 into "the segment on line 12 of the file I sent". Counting segments by hand in a thousand-line interchange is where the time goes — a tool that shows segment positions directly turns a ten-minute count into a jump.
Related: reading the 850 that got rejected.