Custom Process Outbound Transactions
Custom Process for outbound transactions lets you bypass the SuiteApp's native message generation and build your own outbound EDI logic. When enabled, the SuiteApp hides its native Generate buttons and leaves message creation entirely to your custom SuiteScript. You control what gets sent and when.
This is useful when:
- A trading partner requires non-standard outbound data that the native mappers don't produce
- Your business logic requires conditional generation (e.g., only send invoices that meet specific criteria)
- You need to pull data from custom records or external systems before generating the EDI message
- You want full control over the outbound payload structure
For inbound custom processing, see Custom Process Inbound Transactions.
How It Works
Outbound custom process works differently from inbound. With inbound, the SuiteApp stages the raw EDI data and stops — your code picks up from there. With outbound, the relationship is reversed: there is no incoming data to stage. Instead, your code must create the outbound message payload and hand it off to the SuiteApp for delivery.
Transaction Flow
-
Configuration: An admin enables a transaction type on a Customer record and checks "Process as Custom." The handling preference for that transaction type should be set to "Custom (Manual/Workflow)."
-
Native buttons hidden: The SuiteApp's Generate buttons (Generate 810, Generate 855, Generate 856, Generate 940) no longer appear on the relevant NetSuite records for that customer. The "Generate and Send" button on Orderful Transaction records is also hidden.
-
Developer generates the message: Your custom SuiteScript creates or loads an Orderful Transaction record, builds the EDI message payload in JSON format, and writes it to the Message field.
-
Send to Orderful: Once the message is populated, it can be sent via:
- The "Send to Orderful" button on the Orderful Transaction record (visible for custom process types)
- Setting the status to "Ready To Send" — the outbound sending MapReduce picks it up automatically
- A WorkflowAction script triggered from a SuiteFlow workflow
-
Delivery: The SuiteApp POSTs the message to the Orderful API and updates the transaction status to Success or Error.
Configuration
Step 1: Enable Custom Process on the Customer
- Navigate to the Customer record
- Go to the Orderful EDI subtab → EDI Enabled Transaction Types
- Find or add the outbound transaction type (e.g., 810, 855, 856, 940)
- Check Process as Custom
- Save the Customer record
Step 2: Set Handling Preferences
On the same Customer record, set the handling preference for the transaction type to Custom (Manual/Workflow):
- 810 Invoice: Set "Invoice Handling Preference" to Custom
- 855 PO Acknowledgment: Set "PO Ack Handling Preference" to Custom
- 856 ASN: Set "ASN Handling Preference" to Custom
- 940 Warehouse Shipping Order: Set "WSO Handling Preference" to Custom
When the handling preference is Custom, the SuiteApp does not automatically generate outbound transactions when trigger events occur (e.g., invoice creation, sales order approval, item fulfillment shipment).
For details on handling preferences, see Outbound Transaction Handling Preferences.
Developer Workflow
Creating the Orderful Transaction Record
Your SuiteScript must create an Orderful Transaction record (customrecord_orderful_transaction) and populate the required fields:
/**
* Create a custom outbound Orderful Transaction record
* and populate it with a developer-generated message payload.
*/
define(['N/record', 'N/search'], function (record, search) {
function createCustomOutboundTransaction(options) {
const { entityId, documentType, message, isTestMode } = options;
// Create the Orderful Transaction record
const orderfulTxn = record.create({
type: 'customrecord_orderful_transaction',
});
// Set required fields
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_entity',
value: entityId
});
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_document',
value: documentType // Internal ID of the document type list value
});
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_direction',
value: 2 // Out
});
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_status',
value: getStatusId('transaction_status_ready_to_send')
});
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_message',
value: JSON.stringify(message)
});
orderfulTxn.setValue({
fieldId: 'custrecord_ord_tran_testmode',
value: isTestMode || false
});
const transactionId = orderfulTxn.save();
log.audit({
title: 'Custom Outbound Transaction Created',
details: `Orderful Transaction ${transactionId} created for entity ${entityId}`
});
return transactionId;
}
/**
* Helper: Look up the internal ID of a transaction status by script ID
*/
function getStatusId(scriptId) {
const results = search.create({
type: 'customlist_orderful_transaction_status',
filters: [['scriptid', 'is', scriptId]],
columns: ['internalid']
}).run().getRange(0, 1);
return results.length > 0 ? results[0].getValue('internalid') : null;
}
return { createCustomOutboundTransaction };
});Orderful Transaction Fields
| Field ID | Required | Description |
|---|---|---|
custrecord_ord_tran_entity | Yes | Internal ID of the Customer or Vendor |
custrecord_ord_tran_document | Yes | Document type (internal ID from customrecord_orderful_edi_document_type) |
custrecord_ord_tran_direction | Yes | Set to 2 (Out) |
custrecord_ord_tran_status | Yes | Set to Ready To Send when the message is ready for delivery |
custrecord_ord_tran_message | Yes | The JSON message payload (stringified) |
custrecord_ord_tran_isa_sender | Recommended | Company ISA ID (sender). If not set, the SuiteApp uses the company-level default. |
custrecord_ord_tran_receiver | Recommended | Customer ISA ID (receiver) |
custrecord_ord_tran_testmode | No | Set to true for sandbox/test transactions |
custrecord_ord_tran_inbound_transaction | No | Link to a parent inbound Orderful Transaction (if this outbound is a response to an inbound, e.g., 855 responding to an 850) |
custrecord_orderful_po_number | No | Purchase order number reference |
Sending the Transaction
Once the message payload is populated, send it to Orderful using one of these methods:
Method 1: Status-Based Automatic Sending
Set the transaction status to Ready To Send. The customscript_orderful_outbound_sending MapReduce script runs on a schedule and picks up all outbound transactions with this status. This is the simplest approach for batch processing.
record.submitFields({
type: 'customrecord_orderful_transaction',
id: transactionId,
values: {
custrecord_ord_tran_status: readyToSendStatusId
}
});Method 2: Manual Send via UI
If the Orderful Transaction record has a populated message and the transaction type is configured as custom process, the "Send to Orderful" button appears on the record. A user can click this button to send the transaction immediately.
Method 3: WorkflowAction
Use the customscript_orderful_send_orderful_wa WorkflowAction in a SuiteFlow workflow to trigger sending programmatically. This is useful for approval-based flows where a workflow state transition triggers the send.
Transaction Statuses
| Status | Script ID | When Used |
|---|---|---|
| Pending | transaction_status_pending | Initial state if creating a shell record before the message is ready |
| Ready To Send | transaction_status_ready_to_send | Message populated and ready for delivery. The outbound sending MapReduce picks up transactions in this status. |
| Success | transaction_status_success | Transaction successfully sent to and accepted by Orderful |
| Error | transaction_status_error | Send failed. Check the custrecord_ord_tran_error field for details. |
Comparison: Inbound vs Outbound Custom Process
| Aspect | Inbound | Outbound |
|---|---|---|
| What the SuiteApp provides | Raw EDI message payload, staged as an Orderful Transaction with status "Pending - Custom Process" | Nothing — native generation is disabled. Developer must create the message. |
| Developer's responsibility | Process the staged data and create NetSuite records (Sales Orders, Fulfillments, etc.) | Generate the outbound message payload and populate it on the Orderful Transaction record |
| Initial status | Pending - Custom Process | Pending (or Ready To Send if set by the developer at creation) |
| How to complete | Set status to Success after processing | Populate the message, then send via button, status change, or WorkflowAction |
| UI impact | No native records are created | Generate buttons are hidden; "Send to Orderful" button is shown |
Available WorkflowAction Scripts
These scripts can be used in SuiteFlow workflows on the Orderful Transaction record:
| Script ID | Purpose |
|---|---|
customscript_orderful_send_orderful_wa | Send an already-generated message to Orderful. Use this for custom process outbound. |
customscript_orderful_generate_send_wa | Generate the message using native mappers AND send. Not typically used for custom process (since the point is to bypass native generation). |
customscript_orderful_generate_810_wa | Generate a native 810 from an Invoice |
customscript_orderful_generate_855_wa | Generate a native 855 from a Sales Order |
customscript_orderful_generate_856_wa | Generate a native 856 from an Item Fulfillment |
customscript_orderful_generate_940_wa | Generate a native 940 from a Sales Order |
Best Practices
- Error handling: Wrap your message generation logic in try/catch blocks. If generation fails, set the Orderful Transaction status to
Errorand write a meaningful message to thecustrecord_ord_tran_errorfield. - Logging: Use
N/logto audit custom generation events. Include the Orderful Transaction ID, entity, and document type in log entries. - Test mode: Use the test mode flag (
custrecord_ord_tran_testmode) during development. Test mode transactions are sent using the Test ISA ID and can be identified separately in Orderful. - ISA IDs: Always set the sender and receiver ISA IDs on the Orderful Transaction record. If omitted, the SuiteApp falls back to company-level defaults, which may not be correct for all customers.
- Sandbox testing: Test custom outbound logic in a NetSuite sandbox environment before deploying to production.
- Null removal: The SuiteApp automatically strips
nullvalues, empty arrays, and empty objects from the payload before sending. You do not need to clean the payload yourself.
Message Payload Format
The message you write to custrecord_ord_tran_message must conform to the format expected by the Orderful API. There are two formats depending on whether you are sending a standard (Orderful JSON) or simplified transaction.
Standard Format (Orderful JSON)
Used for X12 transaction types (810, 855, 856, 846, 880, 940, 943). Sent to https://api.orderful.com/v3/transactions.
{
"sender": {
"isaId": "YOURCOMPANYISA"
},
"receiver": {
"isaId": "TRADINGPARTNERISA"
},
"type": {
"name": "810_INVOICE"
},
"stream": "LIVE",
"message": {
"transactionSets": [
{
// Transaction set content in Orderful JSON format
// Structure varies by transaction type
}
]
}
}Key fields:
| Field | Description |
|---|---|
sender.isaId | Your company's ISA ID (the sender for outbound transactions) |
receiver.isaId | The trading partner's ISA ID |
type.name | The Orderful transaction type identifier (see table below) |
stream | "LIVE" for production or "TEST" for sandbox transactions |
message.transactionSets | Array containing one transaction set object in Orderful JSON format |
Transaction type identifiers:
| Transaction | type.name Value |
|---|---|
| 810 Invoice | 810_INVOICE |
| 855 PO Acknowledgment | 855_PURCHASE_ORDER_ACKNOWLEDGMENT |
| 856 ASN | 856_SHIP_NOTICE_MANIFEST |
| 846 Inventory Advice | 846_INVENTORY_INQUIRY_ADVICE |
| 880 Grocery Invoice | 880_GROCERY_PRODUCTS_INVOICE |
| 940 Warehouse Shipping Order | 940_WAREHOUSE_SHIPPING_ORDER |
| 943 Warehouse Stock Transfer | 943_WAREHOUSE_STOCK_TRANSFER_SHIPMENT_ADVICE |
Simplified Format
Used for simplified (non-X12) transaction types. Sent to https://api.orderful.com/v2/integration-payloads.
{
"senderId": "YOURCOMPANYISA",
"receiverId": "TRADINGPARTNERISA",
"type": "855_PURCHASE_ORDER_ACKNOWLEDGMENT",
"stream": "LIVE",
"message": {
"purchaseOrderNumber": "PO12345",
"status": "accepted",
"lineItems": []
}
}Note the differences from the standard format:
senderIdandreceiverIdare flat strings (not nested objects)typeis a flat string (not{ "name": "..." })messagecontains the payload directly — notransactionSetswrapper
Format Detection
The SuiteApp automatically detects which format to use based on the message structure:
- If
messagecontainstransactionSets, it sends to the standard (/v3/transactions) endpoint - If
messagecontains simplified-format keys (e.g.,purchaseOrderNumber,invoiceNumber,shipmentId), it sends to the simplified (/v2/integration-payloads) endpoint
You do not need to specify the endpoint — just structure the message correctly and the SuiteApp handles routing.
Limitations
- No native message generation: When custom process is enabled for an outbound type, the SuiteApp's native mappers do not run. The developer is responsible for producing the complete message payload.
- No automatic shell creation: When the handling preference is set to Custom (Manual/Workflow), the SuiteApp does not automatically create an Orderful Transaction record when a trigger event occurs. The developer must create the record.
- No reprocess: Unlike inbound custom process transactions, outbound transactions do not have a "Reprocess" option. If a send fails, correct the message and re-send, or create a new Orderful Transaction record.
- Validation is on the Orderful platform: The SuiteApp does not validate custom-generated payloads before sending. Validation errors from the Orderful API are written to the Error field on the Orderful Transaction record.
Updated about 4 hours ago
