# Building an Order Receiver Service
**Summary:**
This guide explains how to implement an order receiver service for Norce Commerce. The order receiver is responsible for accepting order requests from Norce Commerce, integrating them into your ERP system, and returning appropriate responses. The integration must be robust, handle retries, and provide clear status updates.
## Overview
The order receiver service is a key integration point between Norce Commerce and your ERP system. When a customer completes a checkout, Norce Commerce sends an order request to your service. Your service must process the order, handle business logic, and return a response indicating success or failure.
> **Timeliness:**
For sales orders, prompt processing is critical to fulfill customer expectations.
Norce Commerce uses a direct integration pattern: it calls your service with an order request and expects a synchronous response. If the call fails, Norce Commerce retries for a limited period before escalating to support.
## Responsibilities of the Order Receiver
When an order is created in Norce Commerce, it is sent to your order receiver service. The service must:
- Map the [OrderRequest](/api-reference/schemas/connectorder#orderrequest) to the target ERP format.
- Route the order if multiple targets exist.
- Handle errors and log issues.
- Notify stakeholders as needed.
- Return a correct [OrderResponse](/api-reference/schemas/connectorder#orderresponse).
Your service may also enrich or transform the order data before sending it to the ERP system.
## Configuration
Order receiver settings are managed in the Norce Commerce Admin UI under the *ERP integration* section.
**Image: Order receiver configuration in Admin UI**

**Key settings:**
- **ERP endpoint type:** Choose between *SOAP*, *REST (Legacy)*, *REST*, or *No Integration*.
*REST* is recommended. *No Integration* disables order integration.
- **ERP endpoint URL:** The address of your integration endpoint.
- **ERP endpoint username/password:** Credentials for basic authentication.
> **Security:**
In production, endpoints must use HTTPS and require basic authentication.
## OrderRequest Message Structure
The [OrderRequest](/api-reference/schemas/connectorder#orderrequest) is a comprehensive contract containing all order details. It is sent as JSON or XML.
**Important fields:**
- **Header.ApplicationKey:** GUID identifying the application in Norce.
- **ClientOrderRef:** Unique order reference, used for duplicate detection.
- **Payments.Payment.PaymentRef:** Payment identifier from the payment service provider.
- **Items.OrderItem.PartNo:** Product identifier.
- **Items.OrderItem.UnitPrice, UnitVat, Quantity:** Line item pricing details.
- **AdditionalInfo:** Custom fields added during checkout.
details
summary
An example OrderRequest message
### OrderRequest
JSON
```json
{
"SellTo": {
"Company": null,
"Person": {
"CustomerCode": "CUST0001",
"CompanyCode": null,
"FirstName": "John",
"LastName": "Doe",
"JobTitle": null,
"PrivatePhone": "0701234567",
"CellPhone": "0707654321",
"WorkPhone": null,
"Email": "john.doe@example.com",
"SSN": null,
"Address": {
"Type": null,
"Line1": "123 Example Street",
"Line2": null,
"Box": "",
"ZipCode": "12345",
"City": "Anytown",
"Region": null,
"Country": "SE",
"CareOf": null,
"ShippingPhoneNumber": null,
"Gln": null,
"ExtensionData": null
},
"AdditionalInfo": [],
"IsActive": null
}
},
"BillTo": {
"Company": null,
"Person": {
"CustomerCode": "BILL0002",
"CompanyCode": null,
"FirstName": "Jane",
"LastName": "Smith",
"JobTitle": null,
"PrivatePhone": "0812345678",
"CellPhone": "0709876543",
"WorkPhone": null,
"Email": "jane.smith@example.com",
"SSN": null,
"Address": {
"Type": null,
"Line1": "456 Invoice Lane",
"Line2": null,
"Box": "",
"ZipCode": "54321",
"City": "Billingville",
"Region": null,
"Country": "SE",
"CareOf": null,
"ShippingPhoneNumber": null,
"Gln": null,
"ExtensionData": null
},
"AdditionalInfo": [],
"IsActive": null
}
},
"ShipTo": {
"Company": null,
"Person": {
"CustomerCode": "SHIP0003",
"CompanyCode": null,
"FirstName": "Alice",
"LastName": "Johnson",
"JobTitle": null,
"PrivatePhone": "0105555555",
"CellPhone": "0705555555",
"WorkPhone": null,
"Email": "alice.johnson@example.com",
"SSN": null,
"Address": {
"Type": null,
"Line1": "789 Shipping Blvd",
"Line2": null,
"Box": "",
"ZipCode": "67890",
"City": "Shipville",
"Region": null,
"Country": "SE",
"CareOf": null,
"ShippingPhoneNumber": null,
"Gln": null,
"ExtensionData": null
},
"AdditionalInfo": [],
"IsActive": null
}
},
"SalesContactCode": "SALES001",
"SalesContactDivision": "Division A",
"DoHold": false,
"ClientOrderRef": "REF12345",
"SubmitDate": "2024-12-18T12:00:00+01:00",
"CustomerOrderRef": "ORDER123",
"CustomerOrderComment": "Please handle with care.",
"CurrencyCode": "SEK",
"ReferId": null,
"Payments": [
{
"PaymentCode": 10001,
"PaymentMethodCode": "credit_card",
"PaymentRef": "PAYREF123",
"Amount": 1500.00,
"CurrencyCode": "SEK",
"AdditionalInfo": [
{
"Id": 1,
"Code": "CardType",
"Value": "Visa"
},
{
"Id": 2,
"Code": "CardHolder",
"Value": "John Doe"
}
],
"PaymentName": "Credit Card Payment"
}
],
"Discounts": [],
"ShippingAdvice": {
"DeliveryMethodCode": "PostNord",
"DoSMSNotify": true,
"PickupStore": {
"Code": "STORE001",
"Name": "Central Warehouse",
"IsDropPoint": true
},
"IsFeeChargedOnce": true,
"IsComplete": true,
"ShipAdvisorOrderCode": null,
"TmsReference": null
},
"Items": [
{
"LineNo": 1,
"ParentLineNo": null,
"Type": "ErpStandard",
"TypeGroup": "Physical",
"PartNo": "ITEM001",
"ErpPartNo": "ITEM001",
"InternalProductId": "10001",
"Description": "Example Product 1",
"Quantity": 2,
"UnitOfMeasure": "pcs",
"UnitPrice": 300.00,
"UnitPriceOriginal": 300.00,
"Discount": 0.00,
"UnitVat": 75.00,
"PriceListNo": 1,
"VatRate": 25.00,
"Comment": "Urgent delivery",
"AdditionalInfo": [
{
"Id": 1,
"Code": "Warranty",
"Value": "2 years"
}
],
"PriceLists": [
{
"PriceListName": "Standard List",
"QtyBreak": 1,
"UnitPrice": 300.00,
"IsStandardPriceList": true,
"IsActive": true
}
],
"Promotions": [],
"ManufacturerCode": "example_manufacturer",
"Quantity2": 2.000
}
],
"Fees": [],
"Header": {
"ApplicationKey": "123e4567-e89b-12d3-a456-426614174000"
},
"OrderType": 1,
"Source": "Online",
"CustomerInvoiceRef": "INV12345",
"DiscountCode": "DISCOUNT2024",
"ExtensionData": null
}
```
XML
```xml
CUST0001
John
Doe
0701234567
0707654321
john.doe@example.com
123 Example Street
12345
Anytown
SE
BILL0002
Jane
Smith
0812345678
0709876543
jane.smith@example.com
456 Invoice Lane
54321
Billingville
SE
SHIP0003
Alice
Johnson
0105555555
0705555555
alice.johnson@example.com
789 Shipping Blvd
67890
Shipville
SE
SALES001
Division A
false
REF12345
ORDER123
Please handle with care.
2024-12-18T12:00:00+01:00
SEK
10001
credit_card
PAYREF123
1500.00
SEK
1
CardType
Visa
2
CardHolder
John Doe
PostNord
true
STORE001
Central Warehouse
true
true
true
1
ErpStandard
Physical
ITEM001
ITEM001
10001
Example Product 1
2
pcs
300.00
300.00
0.00
75.00
1
25.00
Urgent delivery
Standard List
1
300.00
true
true
1
Warranty
2 years
123e4567-e89b-12d3-a456-426614174000
Order
```
Read more about the [OrderRequest](/api-reference/schemas/connectorder#orderrequest)
in the Norce Commerce Connect API Reference.
## OrderResponse Message Structure
Your service must return an [OrderResponse](/api-reference/schemas/connectorder#orderresponse) in JSON or XML. Norce Commerce expects HTTP 200 and a well-formed response. Otherwise, it will retry the request every 10 minutes for up to six hours.
**Response scenarios:**
- **OK, without ERP order number:**
Order is being processed asynchronously. Status in Norce is set to `Allocated`. You must later confirm using [SendOrderStatus](/api-reference/connect/orderservice/openapi/order/sendorderstatus).
- **OK, with ERP order number:**
Order is confirmed synchronously. Status in Norce is set to `Confirmed`.
- **Failed:**
Order processing failed. The error is logged in Norce, and no retry occurs.
- **Other HTTP status codes:**
Triggers Norce Commerce retry logic.
details
summary
OrderResponse message examples JSON
Ok - with ErpOrderNo
```JSON
{
"StatusCode": "OK",
"Description": "No error, order status is set to confirmed.",
"HasErpOrderNo": true,
"ErpOrderNo": "ErpNo_5670588"
}
```
Ok - without ErpOrderNo
```JSON
{
"StatusCode": "OK",
"Description": "No error, order status is set to allocated.",
"HasErpOrderNo": false,
"ErpOrderNo": null
}
```
Error
```JSON
{
"StatusCode": "Failed",
"Description": "Managed Error, this message is logged in Norce Commerce, no retry.",
"HasErpOrderNo": false,
"ErpOrderNo": null
}
```
details
summary
OrderResponse message examples XML
Ok - with ErpOrderNo
```XML
OK
No error, order status is set to confirmed.
true
ErpNo_5670588
```
Ok - without ErpOrderNo
```XML
OK
No error, order status is set to allocated.
false
```
Error
```XML
Failed
Managed Error, this message is logged in Norce Commerce, no retry.
false
```
Read more about
the [OrderResponse](/api-reference/schemas/connectorder#orderresponse) in the Connect
API Reference.
## Customization
You can add custom information to the order during checkout using configurable info types. These appear in the `AdditionalInfo` collections in the OrderRequest.
**Configure info types in Admin UI:**
- [Customer and companies](https://norce-open-demo.admin-se.playground.norce.tech/customer/settings/infotypes/customer)
- [Baskets](https://norce-open-demo.admin-se.playground.norce.tech/shopping/settings/infotypes/basket)
- [Basket items](https://norce-open-demo.admin-se.playground.norce.tech/shopping/settings/infotypes/basketitem)
## Receiving an OrderRequest
The order receiver service must expose HTTP POST endpoints to accept OrderRequest messages in JSON or XML.
**OrderRequest structure:**
Contains customer, shipping, payment, and item details. Norce Commerce sends the request to your endpoint.
### Example Endpoints
details
summary
JSON Endpoint Example:
JSON Example
```csharp
///
/// Receive an OrderRequest from Norce in JSON format
///
/// Norce will POST an Enferno.Services.StormConnect.Contracts.Order.OrderRequest
/// ERP order data mapped to Enferno.Services.StormConnect.Contracts.Order.OrderResponse
[HttpPost("json", Name = "ReceiveOrderRequestJson")]
[Consumes("application/json")] // Specifies JSON as input format
[Produces("application/json")] // Returns JSON response
public async Task PostJson(Enferno.Services.StormConnect.Contracts.Order.OrderRequest norceOrderRequest)
{
_logger.LogInformation("Order request received for {ClientOrderRef}", norceOrderRequest.ClientOrderRef);
// Process the order and send a response
var orderResponse = new Enferno.Services.StormConnect.Contracts.Order.OrderResponse
{
StatusCode = "Ok",
HasErpOrderNo = true,
ErpOrderNo = Guid.NewGuid().ToString() // Set to order number from Erp
};
return Ok(orderResponse);
}
```
XML Example
```csharp
///
/// Receive an OrderRequest from Norce in XML format
///
/// Norce will POST an Enferno.Services.StormConnect.Contracts.Order.OrderRequest in XML
/// ERP order data mapped to Enferno.Services.StormConnect.Contracts.Order.OrderResponse
[HttpPost("xml", Name = "ReceiveOrderRequestXml")]
[Consumes("application/xml")] // Specifies XML as input format
[Produces("application/xml")] // Returns XML response
public async Task PostXml([FromBody] Enferno.Services.StormConnect.Contracts.Order.OrderRequest norceOrderRequest)
{
_logger.LogInformation("XML Order request received for {ClientOrderRef}", norceOrderRequest.ClientOrderRef);
// Process the order and send a response
var orderResponse = new Enferno.Services.StormConnect.Contracts.Order.OrderResponse
{
StatusCode = "Ok",
HasErpOrderNo = true,
ErpOrderNo = Guid.NewGuid().ToString() // Set to order number from Erp
};
return Ok(orderResponse);
}
```
**Explanation:**
- Use `[Consumes]` and `[Produces]` attributes to specify input/output formats.
- Log the `ClientOrderRef` for traceability.
- Return an OrderResponse with appropriate status and ERP order number.
### Required NuGet Package
To use the `OrderRequest` and `OrderResponse` types, install the [Enferno.Services.StormConnect.Contracts NuGet package](https://www.nuget.org/packages/Enferno.Services.StormConnect.Contracts):
```cmd
Install-Package Enferno.Services.StormConnect.Contracts
```
## Recommended Practices
### Duplicate Detection
Design your integration to handle retries. Use `ClientOrderRef` as a unique key to detect and ignore duplicate orders.
### Error Handling
Return a `Failed` status for business or integration errors. Only rely on Norce Commerce retry logic for endpoint or service downtime.
### Service Downtime
If your ERP or integration is unavailable, return an appropriate HTTP status (e.g., `ServiceUnavailable`). Norce Commerce will retry automatically.
## Further Reading
- [Shopping integration](/developer-portal/system-integration/shopping-integrations)
- [Customers and Companies integration](/developer-portal/system-integration/customer-and-company-integrations)
- [Norce Commerce Connect API Reference](/api-reference)