Storing ERP Invoice Data in IBM Sterling OMS Using Custom Attributes
A Practical Guide to Invoice URL Persistence and Storefront Display
Direct answer
When an e-commerce order is fulfilled through IBM Sterling OMS, the system orchestrates reservation, picking, packing, shipping, and payment capture. After payment capture, an invoice is typically generated in an external ERP or accounting system. The challenge is how the storefront displays that invoice to the customer without building a separate invoice lookup service.
By Adaptive Development · Enterprise Integration Engineering
AI Assistants
Overview
When an e-commerce order is fulfilled through IBM Sterling OMS, the system orchestrates reservation, picking, packing, shipping, and payment capture. After payment capture, an invoice is typically generated in an external ERP or accounting system. The challenge is how the storefront displays that invoice to the customer without building a separate invoice lookup service.
The answer lies in IBM Sterling OMS Custom Attributes combined with a Service Definition pipeline. Configure OMS to call middleware, receive invoice URLs in the HTTP response, and write those URLs to the order using changeOrder—all within a single OMS Service Definition. The storefront can then retrieve everything from one getOrderDetails API call.
A critical design point: the middleware is a passive responder. It receives the invoice payload from OMS, creates the invoice in the ERP, and returns URLs in the HTTP response. The middleware does not call back into OMS. All logic for storing invoice data on the order lives inside the OMS Service Definition.
This article uses Odoo as the reference ERP because of its open JSON-RPC interface and customer portal URLs that work without login. The pattern is fully ERP-agnostic: any system that returns an invoice URL in an HTTP response—SAP, NetSuite, Microsoft Dynamics, or a custom billing service—fits without modification.
Prerequisites
- IBM Sterling OMS installed and operational (tested on OMS 10.x).
- A middleware service available to handle HTTP POST requests from OMS and return invoice URLs in the response body.
- An ERP system (Odoo or equivalent) with invoice creation via API, customer-accessible invoice URL generation, and payment registration support.
- A payment gateway (e.g., Stripe) integrated with OMS for payment capture.
- OMS Applications Manager accessible for Service Definition configuration.
- API access credentials (JWT or basic auth) for OMS REST APIs.
Creating Custom Attributes in IBM Sterling OMS
IBM Sterling OMS allows extending the Order entity with custom fields without modifying extensions.xml or triggering a full entity build. This uses three APIs: manageAttribute, manageEntityAttributeDomain, and manageEntityCustomAttribute.
For this invoice use case, five custom attributes are created on the Order: OdooInvoiceId (internal ERP invoice ID), InvoicePortalUrl (shareable view URL), InvoicePdfUrl (direct PDF download URL), InvoiceStatus (e.g., ACCEPTED, PENDING), and InvoiceNo (human-readable invoice number). Repeat the steps below for each attribute; examples use InvoicePortalUrl as AttributeID.
3.1 Create the Custom Attribute
API: manageAttribute (table YFS_ATTRIBUTE). Example input for InvoicePortalUrl:
<AttributeList>
<Attribute
Operation="Create"
AttributeDomainID="EntityAttribute"
AttributeGroupID="CustomAttributeGroupID_1"
AttributeID="InvoicePortalUrl"
DataType="TEXT"
OrganizationCode="DEFAULT"/>
</AttributeList>
Repeat for OdooInvoiceId, InvoicePortalUrl, InvoicePdfUrl, InvoiceStatus, and InvoiceNo (all DataType="TEXT"). Use the same AttributeDomainID and AttributeGroupID across all five attributes.
3.2 Create Entity Attribute Domain
API: manageEntityAttributeDomain (table YFS_ENTITY_ATTRIBUTE_DOMAIN). Perform this step once:
<EntityAttributeDomain
AttributeDomainID="EntityAttribute"
DocumentType="0001"
Operation="Create"
OrganizationCode="DEFAULT"
TableName="YFS_ORDER_HEADER"/>
- DocumentType="0001" refers to Sales Orders in OMS.
- TableName="YFS_ORDER_HEADER" binds attributes to the order header.
- Copy EntityAttributeDomainKey from the response; it is required for the next step.
3.3 Create Entity Custom Attribute
API: manageEntityCustomAttribute (table YFS_ENTITY_CUSTOM_ATTRIBUTE). Repeat per attribute:
<EntityCustomAttributeList>
<EntityCustomAttribute
Action="Create"
AttributeDomainID="EntityAttribute"
AttributeGroupID="CustomAttributeGroupID_1"
AttributeID="InvoicePortalUrl"
EntityAttributeDomainKey="[KEY FROM STEP 3.2]"
OrganizationCode="DEFAULT"
Searchable="Y"
Status="ACTIVE"/>
</EntityCustomAttributeList>
Replace the placeholder with EntityAttributeDomainKey from step 3.2. Copy EntityCustomAttributeKey from each response for activation.
3.4 Activate Entity Custom Attribute
API: manageEntityCustomAttribute. Repeat for each attribute using its EntityCustomAttributeKey:
<EntityCustomAttributeList>
<EntityCustomAttribute
Action="Activate"
EntityCustomAttributeKey="[KEY FROM STEP 3.3]"/>
</EntityCustomAttributeList>
After activation, custom attributes are live on YFS_ORDER_HEADER_EXTENSION and accessible via standard OMS APIs.
Middleware Integration: Creating the Invoice in the ERP
The middleware receives the invoice payload from OMS (step 1 of the Service Definition), creates the invoice in the ERP, and returns invoice URLs in the HTTP response. That is the full extent of middleware responsibility in this flow.
The middleware does not call back into OMS. OMS reads the HTTP response inside the Service Definition pipeline and writes invoice data to the order.
- Receive invoice payload (OrderNo, invoice lines, amount, payment reference).
- Find or create the customer record in the ERP.
- Create the invoice with correct line items.
- Post or confirm the invoice and register payment (mark as PAID).
- Generate customer-accessible invoice URL and PDF URL.
- Return invoice metadata in the HTTP response body.
{
"invoiceId": "118",
"invoiceNo": "77",
"invoiceStatus": "ACCEPTED",
"portalUrl": "http://erp-host/my/invoices/118?access_token=...",
"pdfUrl": "http://erp-host/my/invoices/118?access_token=...&report_type=pdf&download=true"
}
In Odoo, invoices are accessible via a portal URL: http://<odoo-host>/my/invoices/<invoice_id>?access_token=<token>. The access_token allows unauthenticated customer access.
- SAP: document sharing URL from SAP Document Management.
- NetSuite: PDF generation endpoint with token authentication.
- Custom ERP: any stable URL with token-based or signed access.
- Requirement: the URL must be accessible by the end customer without ERP credentials.
Service Definition in IBM Sterling OMS (Send_Invoice_Service)
Send_Invoice_Service is a manually created OMS Service Definition under Order Fulfillment, triggered by the Send Invoice transaction after payment capture. All three steps run inside OMS; middleware is only the HTTP endpoint in step 1.
Start → HTTP Sender → XSL Translator → changeOrder API → End
5.1 Step 1: HTTP Sender (OMS to Middleware)
- Component: HTTP Sender.
- URL: http://<middleware-host>/webhook/invoice.
- HTTP Post Variable: payload.
- Connection Timeout ms: 10000; Read Timeout ms: 100000.
- OMS sends invoice XML as POST body; middleware returns invoice URLs in the HTTP response.
5.2 Step 2: XSL Translator
The XSL Translator transforms the middleware HTTP response into XML structure expected by changeOrder, mapping invoiceId, invoiceNo, portalUrl, pdfUrl, and invoiceStatus to Custom Attribute XPath values:
<Order>
<CustomAttributes>
<Attribute Name="OdooInvoiceId" Value="118"/>
<Attribute Name="InvoiceNo" Value="77"/>
<Attribute Name="InvoiceStatus" Value="ACCEPTED"/>
<Attribute Name="InvoicePortalUrl" Value="http://erp-host/my/invoices/118?access_token=..."/>
<Attribute Name="InvoicePdfUrl" Value="http://erp-host/my/invoices/118?access_token=...&report_type=pdf&download=true"/>
</CustomAttributes>
</Order>
5.3 Step 3: changeOrder API
Component: API (Standard API, changeOrder). The API node uses XSL output as input. Facts tab binds transformed fields:
- OrderHeaderKey → /Order/@OrderHeaderKey
- OdooInvoiceId → /Order/CustomAttributes/Attribute[@Name='OdooInvoiceId']/@Value
- InvoicePortalUrl → /Order/CustomAttributes/Attribute[@Name='InvoicePortalUrl']/@Value
- InvoicePdfUrl → /Order/CustomAttributes/Attribute[@Name='InvoicePdfUrl']/@Value
- InvoiceStatus → /Order/CustomAttributes/Attribute[@Name='InvoiceStatus']/@Value
- InvoiceNo → /Order/CustomAttributes/Attribute[@Name='InvoiceNo']/@Value
OMS executes changeOrder and writes invoice metadata to YFS_ORDER_HEADER_EXTENSION. No external call is made at this step.
Pipeline summary:
1. HTTP Sender — OMS sends invoice payload; middleware creates ERP invoice and returns URLs.
2. XSL Translator — OMS transforms middleware response to OMS XML.
3. changeOrder API — OMS writes invoice URLs to Order Custom Attributes.
Retrieving Invoice Data on the Storefront
The storefront uses getOrderDetails with a lightweight Template requesting only required fields—an OMS best practice that avoids full order payload and keeps response times fast under load.
<Order
OrderNo="Y100001310"
EnterpriseCode="DEFAULT"
DocumentType="0001">
<Template>
<Order OrderNo="" Status="" PaymentStatus="">
<CustomAttributes
OdooInvoiceId=""
InvoicePortalUrl=""
InvoicePdfUrl=""
InvoiceStatus=""
InvoiceNo=""/>
</Order>
</Template>
</Order>
- Display a View Invoice button linking to InvoicePortalUrl.
- Display a Download PDF button linking to InvoicePdfUrl.
- Show InvoiceNo and InvoiceStatus on the order history page.
- Confirm PaymentStatus is PAID before showing invoice options.
Sample API Responses
Middleware log (invoice created, URLs returned to OMS):
INVOICE received from OMS
Invoice No : 77
Order No : Y100001310
Amount : USD 765.80
Payment via : STRIPE | Auth: pi_3TcMW2SJwyWGTllK16aYy7pV
Lines : 2
• E-COM08 x 1.0 @ $15.80 = $15.80
• DESK0006 x 1.0 @ $750.00 = $750.00
Invoice created in ERP : ID=118, Status=PAID
Portal URL returned : http://erp-host/my/invoices/118?access_token=c5731f85-...
PDF URL returned : http://erp-host/my/invoices/118?access_token=c5731f85-...&report_type=pdf
[ Middleware work ends here. OMS handles the rest. ]
OMS then executes the XSL Translator and calls changeOrder internally. Storefront getOrderDetails response:
{
"Status": "Shipped",
"PaymentStatus": "PAID",
"OrderNo": "Y100001310",
"CustomAttributes": {
"InvoiceNo": "77",
"OdooInvoiceId": "118",
"InvoiceStatus": "ACCEPTED",
"InvoicePortalUrl": "http://erp-host/my/invoices/118?access_token=c5731f85-...",
"InvoicePdfUrl": "http://erp-host/my/invoices/118?access_token=c5731f85-...&report_type=pdf&download=true"
}
}
Conclusion
IBM Sterling OMS Custom Attributes combined with a Service Definition pipeline provide a clean, deployment-free mechanism to capture ERP invoice data and surface it to the storefront.
- Middleware handles ERP communication only—it receives, creates, and returns; it does not call OMS.
- OMS handles its own data persistence via HTTP Sender, XSL Translator, and changeOrder within the Service Definition.
- The storefront queries only OMS and never needs ERP or middleware knowledge.
This pattern extends beyond invoices: warranty certificates, return labels, and shipping documents can follow the same approach—trigger a Service Definition, call an external system, transform via XSL, and write results back with changeOrder. Keeping each layer responsible for its own concerns keeps the integration maintainable, testable, and easy to extend.




