The EDI 997 Functional Acknowledgment is the X12 transaction set that confirms receipt of any inbound EDI document and reports whether it passed syntax validation. Every trading partner expects one within hours of transmitting an 850, 810, or 856. A missing 997 is treated as a failed transmission, which can trigger re-sends, duplicate orders, and chargebacks.
What is an EDI 997?
An EDI 997 Functional Acknowledgment (FA) is a structured receipt document defined by the ASC X12 standards body that a trading partner returns to confirm that a received transaction set was syntactically valid or to report specific segment and element errors.
Authoritative sources for 997 implementation:
- The X12.org Transaction Sets reference defines the 997 functional group acknowledgment structure used across all transaction types
- The DISA (Data Interchange Standards Association) maintains the X12 secretariat and formal ballot process for 997 error codes
- Retailer implementation guides (Walmart SupplierOne, Target Partners Online, Amazon Vendor Central) specify timing requirements and mandatory error reporting fields
An EDI 997 is sent to confirm:
- ✅ The EDI file was successfully received
- ✅ The structure and syntax are valid
- ✅ All required segments are present
- ✅ Data elements are in correct format
Important: A 997 only confirms technical validity, NOT business acceptance. You can receive a positive 997 but still have the business document rejected later.
Interactive Example: Positive 997
Here's a 997 acknowledging a received 850 Purchase Order:
Generic 997 Functional Acknowledgment
Positive acknowledgment confirming receipt of an 850 PO
Raw EDI (X12)
Human-Readable
Interchange
Functional Group
Transaction 997
Functional AcknowledgmentWhen to Send a 997
The 997 should be sent:
Timing: Within 24 hours of receiving an EDI transaction (many systems send within minutes)
For every transaction received:
- 850 Purchase Orders → Send 997
- 810 Invoices → Send 997
- 856 Ship Notices → Send 997
- 855 PO Acknowledgments → Send 997
- Even 997s can receive 997s!
Critical: Not sending a 997 can result in:
- Trading partner assumes transmission failed
- Documents may be re-sent (duplicates)
- Compliance violations
- Potential chargebacks
Key Segments Explained
AK1 - Functional Group Response Header
AK1*PO*1
- AK101: Functional Identifier Code from original GS segment
- PO = Purchase Order (850)
- SH = Ship Notice (856)
- IN = Invoice (810)
- PR = Purchase Order Acknowledgment (855)
- AK102: Group Control Number (from original GS06)
AK2 - Transaction Set Response Header
AK2*850*0001
- AK201: Transaction Set Identifier Code (850 = Purchase Order)
- AK202: Transaction Set Control Number (from original ST02)
AK5 - Transaction Set Response Trailer
This is the verdict on the transaction:
AK5*A
AK501 Status Codes:
| Code | Meaning | Description |
|---|---|---|
| A | Accepted | Transaction is valid and accepted |
| E | Accepted with Errors | Minor errors, but transaction was processed |
| M | Rejected, Message Authentication Code Failed | Security issue |
| P | Partially Accepted | Some parts valid, some rejected |
| R | Rejected | Transaction is invalid and rejected |
| W | Rejected, Assurance Failed | Security/authentication failed |
| X | Rejected, Content After Decryption Could Not Be Analyzed | Encryption issue |
AK9 - Functional Group Response Trailer
AK9*A*1*1*1
- AK901: Functional Group Acknowledgment Code
- A = Accepted
- E = Accepted with errors
- P = Partially accepted
- R = Rejected
- AK902: Number of transaction sets included
- AK903: Number of received transaction sets
- AK904: Number of accepted transaction sets
Acceptance Status Examples
Example 1: Fully Accepted (Best Case)
AK1*PO*1 // Purchase Order group 1
AK2*850*0001 // Transaction 850, control # 0001
AK5*A // ACCEPTED
AK9*A*1*1*1 // Group accepted, 1 of 1 accepted
Translation: "We received your 850 PO (control #0001), it's perfect, and we accepted it."
Example 2: Rejected with Error
AK1*PO*1
AK2*850*0001
AK3*N1*4 // Error in N1 segment, position 4
AK4*1*5 // Element 1 of N1 is invalid
AK5*R*5 // REJECTED - Invalid segment
AK9*R*1*1*0 // Group rejected, 0 of 1 accepted
Translation: "We received your 850, but the N1 segment (position 4) has an error in element 1. We rejected it."
Example 3: Multiple Transactions
AK1*PO*5
AK2*850*0001 // First PO
AK5*A // Accepted
AK2*850*0002 // Second PO
AK5*A // Accepted
AK2*850*0003 // Third PO
AK3*PO1*10 // Error in PO1 segment
AK4*2*7 // Element 2 is invalid
AK5*R*7 // Rejected
AK9*P*3*3*2 // Partially accepted: 2 of 3
Translation: "You sent 3 POs in group 5. We accepted #0001 and #0002, but rejected #0003 due to an error in PO1 segment."
Error Reporting (AK3 and AK4)
When a transaction is rejected, the 997 should explain why:
AK3 - Data Segment Note
Points to the specific segment with an error:
AK3*PO1*5*7
- AK301: Segment ID (e.g., PO1, N1, REF)
- AK302: Segment position in transaction set
- AK303: Loop identifier (optional)
AK4 - Data Element Note
Points to the specific data element with an error:
AK4*2*7*8
- AK401: Position in segment (element number)
- AK402: Element reference number
- AK403: Error code
Common AK403 Error Codes:
| Code | Meaning | Example |
|---|---|---|
| 1 | Mandatory data element missing | PO102 (quantity) is empty |
| 2 | Conditional required data element missing | If PO103 is EA, then PO102 is required |
| 3 | Too many data elements | Extra elements beyond what's allowed |
| 4 | Data element too short | UPC only has 10 digits instead of 12 |
| 5 | Data element too long | Part number exceeds 30 characters |
| 6 | Invalid character in data element | Letters in a numeric field |
| 7 | Invalid code value | Unit of measure "XX" doesn't exist |
| 8 | Invalid date | DTM00220231132 (no 32nd day) |
| 9 | Invalid time | BSN04*2561 (hour can't be 25) |
| 10 | Exclusion condition violated | Both mutually exclusive elements present |
Complete Error Example
ISA*00* *00* *ZZ*BUYER456 *ZZ*VENDOR123 *231120*1432*U*00401*000000007*0*P*:~
GS*FA*BUYER456*VENDOR123*20231120*1432*7*X*004010~
ST*997*0007~
AK1*PO*1~
AK2*850*0001~
AK3*PO1*5~ // Error in PO1 segment at position 5
AK4*2**1~ // Element 2 (quantity) is missing
AK3*N4*8~ // Error in N4 segment at position 8
AK4*3**8~ // Element 3 (zip code) has invalid format
AK5*R*1~ // REJECTED - segment error
AK9*R*1*1*0~ // Group rejected
SE*9*0007~
GE*1*7~
IEA*1*000000007~
Translation: "Your 850 was rejected because:
- PO1 segment (line item 5) is missing the quantity
- N4 segment (address 8) has an invalid zip code format"
Implementation Approaches
Option 1: Manual 997 Generation
Suitable for low-volume EDI:
1. Receive inbound EDI
2. Parse and validate
3. Log any errors
4. Generate 997 based on validation results
5. Send 997 via VAN/AS2
Pros: Full control, can customize validation Cons: Time-consuming, error-prone
Option 2: Automated 997 Generation
Recommended for most implementations:
1. EDI software receives transaction
2. Real-time syntax validation
3. 997 auto-generated instantly
4. 997 transmitted automatically
5. Log for audit trail
Pros: Fast, reliable, no manual work Cons: Need EDI software/middleware
Option 3: VAN-Generated 997s
Many VANs (Value-Added Networks) can generate 997s:
1. Send EDI to VAN
2. VAN validates syntax
3. VAN generates 997
4. VAN sends 997 to partner
5. You receive confirmation
Pros: Zero effort, VAN handles it Cons: Limited customization, VAN fees, may not catch business logic errors
Best Practices
1. Send 997s Promptly
❌ Wait 24 hours to batch 997s
✅ Send within minutes of receiving transaction
Prompt 997s help partners know their transmission succeeded and allows faster error correction.
2. Always Send a 997
❌ Only send 997 if there's an error
✅ Send 997 for every transaction (accepted or rejected)
Silence = uncertainty. Partners need to know you received their transmission.
3. Provide Detailed Error Information
❌ AK5*R (rejected with no explanation)
✅ AK5*R + AK3/AK4 segments explaining what's wrong
Help your partner fix issues faster with specific error details.
4. Log All 997s
Keep an audit trail:
- ✅ 997 sent timestamp
- ✅ Original transaction details
- ✅ Accept/reject status
- ✅ Error details if rejected
Useful for troubleshooting and compliance audits.
5. Monitor 997 Receipt
After you send EDI to a partner:
- ✅ Expect a 997 within 24 hours
- ✅ Alert if no 997 received
- ✅ Check if 997 shows rejection
- ✅ Investigate and resubmit if needed
997 vs. Business Acceptance
Critical Distinction:
997 FA = Technical acceptance only
855/856/810 = Business acceptance
Example Flow:
1. You send 850 PO
2. Partner sends 997*A (✅ received and valid)
3. Partner sends 855*04 (❌ cannot fulfill - out of stock)
The 997*A means "your EDI syntax is correct," but the 855 rejection means they can't actually fulfill your order.
Common 997 Mistakes
1. Not Sending 997s at All
❌ Assume partner knows you received the file
✅ Always send 997 confirmation
2. Incorrect Control Numbers
❌ AK2*850*9999 (wrong control number)
✅ AK2*850*0001 (matches original ST02)
3. Wrong Functional Identifier
❌ AK1*SH*1 (for an 850 PO)
✅ AK1*PO*1 (matches original GS01)
4. Accepting Invalid Data
❌ AK5*A (but data has business logic errors)
✅ AK5*R + detailed error codes
Don't accept bad data just because it parses correctly!
Testing Your 997 Implementation
Use our EDI Inspector to:
- Validate 997 structure
- Check control number matching
- Verify error code accuracy
- Test against partner specs
Integration Tips
Automated 997 Response
def on_edi_received(edi_file):
try:
# Parse and validate
parsed = parse_edi(edi_file)
validate_syntax(parsed)
validate_business_rules(parsed)
# Generate positive 997
fa = generate_997(
status='A', # Accepted
original_control=parsed.control_number
)
# Send 997
send_edi(fa)
# Process transaction
process_transaction(parsed)
except SyntaxError as e:
# Generate negative 997
fa = generate_997(
status='R', # Rejected
errors=e.details,
original_control=parsed.control_number
)
send_edi(fa)
except BusinessError as e:
# Send positive 997 (syntax OK)
fa = generate_997(status='A')
send_edi(fa)
# But send business rejection (855/810/etc)
rejection = generate_business_rejection(e)
send_edi(rejection)
Related Transaction Sets
- 850 Purchase Order - Needs 997 acknowledgment
- 856 Ship Notice - Needs 997 acknowledgment
- 810 Invoice - Needs 997 acknowledgment
- 855 Purchase Order Acknowledgment - Business-level acceptance
Compliance Requirements
Most trading partners require:
| Partner | 997 Timing | Rejection Requirements |
|---|---|---|
| Walmart | Within 4 hours | Must include error details |
| Target | Within 24 hours | AK3/AK4 segments required |
| Amazon | Within 2 hours | Immediate transmission |
| Home Depot | Within 8 hours | Full error reporting |
Late or missing 997s may result in compliance violations or chargebacks.
Frequently Asked Questions
What does AK5 = "A" vs. AK5 = "R" mean?
AK5 is the transaction set response trailer and its first element (AK501) is the verdict on the transaction. "A" means Accepted: the transaction parsed correctly and passed all syntax checks. "R" means Rejected: the transaction had one or more errors that prevented processing. When you see "R," look for AK3 and AK4 segments immediately before it in the same AK2 block. Those segments point to the exact segment position and element number that failed.
What is the difference between a 997 and a 999?
The 997 is the original X12 Functional Acknowledgment used in version 004010 and earlier. The 999 is the updated Implementation Acknowledgment introduced in version 005010 and later. The 999 adds a fourth reporting level for implementation-level errors (IK3/IK4) on top of the basic AK3/AK4 syntax errors. Most retail trading partners still use 004010 and 997. If your partner requires 005010, check their implementation guide to see whether they expect a 997 or a 999.
How quickly do I have to send a 997 after receiving a transaction?
Timing varies by trading partner. Walmart requires a 997 within 4 hours. Amazon Vendor Central expects one within 2 hours. Target allows up to 24 hours. In practice, modern EDI translators generate and return a 997 within seconds of parsing an inbound file. If your system cannot do that, batching 997s every 30 minutes is generally safe. Anything slower risks the partner assuming the transmission failed.
Can a 997 acknowledge multiple transactions in one document?
Yes. A single 997 can contain multiple AK1/AK2/AK5 blocks, one for each functional group received. Each AK2 block corresponds to one transaction set (one 850, one 810, etc.). The AK9 segment at the end of each AK1 block summarizes how many transactions were in the group and how many were accepted.
Should I send a 997 for a 997 I receive?
Technically yes, though most implementations do not bother. The X12 spec treats a 997 like any other inbound transaction, meaning it should get its own acknowledgment. In practice, most trading partners disable 997-of-997 to avoid infinite loops. Check your partner's implementation guide. If they do not mention it, skip it.
Need Help?
Try our free EDI inspector to validate your 997 functional acknowledgments or contact our team for automated 997 implementation support.