Documentation
Everything you need to integrate Matthews Aurora Solution Center into your application.
Overview
SCX (Solution Center Exchange) enables seamless integration between your application and the Matthews Aurora Solution Center product catalog using industry-standard PunchOut protocols.
Integration Flow
- Your application sends a setup request with customer credentials to SCX
- SCX authenticates your request, maps your customer ID to a Solution Center account, and creates a session
- SCX returns a session URL (e.g.,
/shop/{token}) that you redirect or embed - User browses the catalog with their contract pricing and filtered catalog types
- User builds their cart and clicks "Return Cart"
- Cart data is returned to your application via your configured callback method (redirect, POST, iframe postMessage, or form POST)
Display Modes
Choose how the catalog appears to your users:
Full-page redirect to SCX. Best for mobile and simple integrations.
Embed the catalog within your application. Users never leave your interface.
Opens in a new window. Users can keep their main workflow visible.
Quick Start
Here's the simplest way to create a PunchOut session using the REST API:
curl -X POST https://scx.example.com/api/punchout/setup \
-H "X-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"customerId": "YOUR-CUSTOMER-ID",
"serviceCenterId": "YOUR-SERVICE-CENTER",
"returnUrl": "https://your-app.com/cart/receive"
}'Response:
{
"success": true,
"sessionToken": "abc123def456...",
"sessionUrl": "https://scx.example.com/shop/abc123def456",
"expiresAt": "2024-01-15T12:30:00Z"
}
Redirect the user to sessionUrl (or embed it in an iframe). When they complete their cart, the data will be returned to your returnUrl via your configured callback method.
Authentication
SCX supports multiple authentication methods. The method used depends on your integration protocol.
API Keys
The recommended authentication method for REST API integrations. Generate API keys in your partner portal.
# Header authentication (recommended)
X-Api-Key: your-api-key-here
# Or as Bearer token
Authorization: Bearer your-api-key-here
API keys are stored as SHA-256 hashes. An 8-character prefix is used for fast lookup. You can configure expiration dates and scope keys to specific integrations via the partner portal.
Basic Authentication
Standard HTTP Basic Auth is also supported. Provide your partner ID and shared secret as the username and password:
# Basic Auth (Base64 encoded partner-id:shared-secret)
Authorization: Basic cGFydG5lci1pZDpzaGFyZWQtc2VjcmV0
# Using curl
curl -u "partner-id:shared-secret" \
-X POST https://scx.example.com/api/punchout/setup
IP Whitelisting
For additional security, you can restrict API access to specific IP addresses. Configure allowed IPs in your integration settings.
# Supported formats
192.168.1.100 // Exact IP address
10.0.0.0/24 // CIDR notation (10.0.0.0 - 10.0.0.255)
203.0.113.0/28 // Smaller subnet rangesIf no IP whitelist is configured, requests are accepted from any IP address. When configured, requests from non-whitelisted IPs are rejected with an authentication error.
Protocols
Choose the protocol that best fits your technology stack and integration requirements.
REST API
Recommended for Modern AppsJSON-based API for easy integration with any programming language.
Create Session
POST /api/punchout/setup
Content-Type: application/json
X-Api-Key: your-api-key
{
"customerId": "FH-12345",
"serviceCenterId": "SC-001", // optional
"returnUrl": "https://your-app.com/cart",
"displayMode": "redirect", // redirect, iframe, popup
"operation": "create", // create, edit, inspect
"buyerCookie": "your-session-ref", // optional tracking ID
"browserFormPostUrl": "https://...", // optional, for cXML-style form POST
"sessionPingUrl": "https://...", // optional, keep-alive ping URL
"metadata": { // optional key-value pairs
"orderId": "PO-12345"
}
}
Get Session Status
GET /api/punchout/session/{token}
X-Api-Key: your-api-key
Get Session Response
{
"token": "abc123...",
"status": "Active", // Active, Completed, Expired, Cancelled
"customerId": "FH-12345",
"serviceCenterId": "SC-001",
"expiresAt": "2024-01-15T14:30:00Z",
"createdAt": "2024-01-15T10:30:00Z",
"cartData": "{ ... }" // JSON string with cart contents
}
Update Cart
PUT /api/punchout/session/{token}/cart
X-Api-Key: your-api-key
Content-Type: application/json
{
"items": [
{
"productId": "PROD-001",
"sku": "SKU-12345",
"name": "Tribute Memorial",
"quantity": 2,
"unitPrice": 99.99,
"currency": "USD"
}
],
"subtotal": 199.98,
"currency": "USD"
}
Complete Session
POST /api/punchout/session/{token}/complete
X-Api-Key: your-api-key
cXML
Enterprise StandardIndustry-standard protocol for enterprise procurement systems like Ariba, Coupa, and Jaggaer.
PunchOut Setup Request
POST /api/cxml
Content-Type: text/xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cXML.org/schemas/cXML/1.2.053/cXML.dtd">
<cXML payloadID="unique-id" timestamp="2024-01-15T10:30:00-05:00">
<Header>
<From>
<Credential domain="NetworkId">
<Identity>buyer-id</Identity>
</Credential>
</From>
<To>
<Credential domain="NetworkId">
<Identity>SCX</Identity>
</Credential>
</To>
<Sender>
<Credential domain="NetworkId">
<Identity>your-partner-id</Identity>
<SharedSecret>your-shared-secret</SharedSecret>
</Credential>
</Sender>
</Header>
<Request>
<PunchOutSetupRequest operation="create">
<BuyerCookie>session-id-from-your-system</BuyerCookie>
<Extrinsic name="CustomerID">FH-12345</Extrinsic>
<Extrinsic name="ServiceCenterID">SC-001</Extrinsic>
<Extrinsic name="SessionPingUrl">https://your-app.com/ping</Extrinsic>
<BrowserFormPost>
<URL>https://your-app.com/cxml/receive</URL>
</BrowserFormPost>
</PunchOutSetupRequest>
</Request>
</cXML>
cXML Extrinsic Fields
SCX extracts customer and session data from Extrinsic elements. The following names are recognized (case-insensitive):
| Extrinsic Name | Description |
|---|---|
CustomerID | Your external customer identifier (required) |
ServiceCenterID | Service center identifier (optional) |
SessionPingUrl | URL for session keep-alive pings (optional) |
FirstName, LastName | Buyer's name (optional, stored as metadata) |
UserEmail | Buyer's email address (optional) |
UniqueName | Buyer's unique identifier (optional) |
BusinessUnit | Buyer's business unit (optional) |
CostCenter | Buyer's cost center (optional) |
cXML Setup Response
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.053/cXML.dtd">
<cXML payloadID="response-id" timestamp="2024-01-15T10:30:01-05:00">
<Response>
<Status code="200" text="OK">Success</Status>
<PunchOutSetupResponse>
<StartPage>
<URL>https://scx.example.com/shop/abc123def456</URL>
</StartPage>
</PunchOutSetupResponse>
</Response>
</cXML>
OCI (Open Catalog Interface)
SAP CompatibleFor SAP and systems using OCI-based procurement. Supports both GET and POST requests.
Setup Request
GET /api/oci?
HOOK_URL=https://your-app.com/oci/receive&
USERNAME=your-partner-id&
PASSWORD=your-shared-secret&
CUSTOMER_ID=FH-12345&
SERVICE_CENTER_ID=SC-001&
FUNCTION=CREATEOCI Parameters
| Parameter | Required | Description |
|---|---|---|
HOOK_URL | Yes | URL where cart data will be form-POSTed |
USERNAME | No | Buyer identifier (for logging) |
PASSWORD | Yes | Shared secret for authentication |
CUSTOMER_ID | Yes | Your external customer identifier |
SERVICE_CENTER_ID | No | Service center identifier |
FUNCTION | No | Operation type (see below). Default: CREATE |
OCI Functions
| Function | Description |
|---|---|
CREATE | Start a new shopping session (default) |
EDIT | Resume and edit an existing cart. Send current items as NEW_ITEM-* parameters. |
INSPECT | View a cart in read-only mode |
VALIDATE | Validate items and return current catalog data/pricing. Send items as NEW_ITEM-MATNR[n] parameters. |
BACKGROUND_SEARCH | Search the catalog by keyword. Use the SEARCHSTRING parameter. Returns up to 100 matching items. |
Background Search Example
GET /api/oci?
HOOK_URL=https://your-app.com/oci/receive&
PASSWORD=your-shared-secret&
CUSTOMER_ID=FH-12345&
FUNCTION=BACKGROUND_SEARCH&
SEARCHSTRING=memorialCart data is returned as OCI form fields (NEW_ITEM-*) auto-POSTed to your HOOK_URL via a self-submitting HTML form.
Operations
All protocols support three operation types for managing PunchOut sessions:
Create
Start a new shopping session with an empty cart. This is the default operation.
Edit
Resume a session with a pre-populated cart. The user can add, remove, or modify items before returning.
Inspect
View a cart in read-only mode. The user can browse but cannot modify items. A "Close" button replaces "Return Cart".
For Edit and Inspect operations, include the existing cart items in your setup request. In REST, use the existingCartItems array. In cXML, include ItemOut elements. In OCI, send NEW_ITEM-* parameters.
Cart Return
When the user completes their cart, data is returned to your application. The delivery method depends on your configured callback method and protocol.
JSON Format (REST API)
For redirect and HTTP POST callback methods, cart data is sent as JSON:
POST {your-return-url}
Content-Type: application/json
{
"sessionToken": "abc123...",
"customerId": "98765",
"serviceCenterId": "42",
"items": [
{
"productId": "PROD-001",
"sku": "SKU-12345",
"name": "Tribute Memorial",
"description": "Premium tribute memorial product",
"quantity": 2,
"unitPrice": 99.99,
"currency": "USD",
"unitOfMeasure": "EA",
"imageUrl": "https://...",
"attributes": {
"color": "Blue",
"size": "Large"
}
}
],
"subtotal": 199.98,
"currency": "USD"
}
For redirect callbacks, the session token is appended as a query parameter: {returnUrl}?token={token}
PostMessage (iframe Mode)
When using iframe display mode with PostMessage callback, cart data is sent via window.postMessage to the parent window:
// Message posted to parent window
{
"type": "scx-cart-return",
"data": {
"sessionToken": "abc123...",
"customerId": "98765",
"serviceCenterId": "42",
"items": [ ... ],
"subtotal": 199.98,
"currency": "USD"
}
}
Listen for the message in your application:
window.addEventListener("message", function(event) {
if (event.data.type === "scx-cart-return") {
const cart = event.data.data;
console.log("Cart received:", cart.items);
// Process the cart data
}
});
cXML PunchOutOrderMessage
For cXML integrations, cart data is returned as a PunchOutOrderMessage document, form-posted to your BrowserFormPost URL as the field cXML-urlencoded.
<cXML payloadID="..." timestamp="..." xml:lang="en-US">
<Header>...</Header>
<Message>
<PunchOutOrderMessage>
<BuyerCookie>your-buyer-cookie</BuyerCookie>
<PunchOutOrderMessageHeader operationAllowed="edit">
<Total>
<Money currency="USD">199.98</Money>
</Total>
</PunchOutOrderMessageHeader>
<ItemIn quantity="2">
<ItemID>
<SupplierPartID>SKU-12345</SupplierPartID>
<SupplierPartAuxiliaryID>token:PROD-001</SupplierPartAuxiliaryID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">99.99</Money>
</UnitPrice>
<Description xml:lang="en-US">Tribute Memorial</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
<Classification domain="UNSPSC">39121031</Classification>
</ItemDetail>
</ItemIn>
</PunchOutOrderMessage>
</Message>
</cXML>
99999999 is used. UOM (Unit of Measure) values are resolved using partner-specific mappings with a global fallback, defaulting to EA.
OCI Format
For OCI integrations, cart data is returned as standard OCI form fields auto-submitted to your HOOK_URL:
NEW_ITEM-DESCRIPTION[1]=Tribute Memorial
NEW_ITEM-MATNR[1]=PROD-001
NEW_ITEM-QUANTITY[1]=2
NEW_ITEM-UNIT[1]=EA
NEW_ITEM-PRICE[1]=99.99
NEW_ITEM-CURRENCY[1]=USD
NEW_ITEM-VENDOR[1]=SCX
NEW_ITEM-VENDORMAT[1]=SKU-12345
NEW_ITEM-MATGROUP[1]=39121031 // UNSPSC code
NEW_ITEM-LONGTEXT_1:132[]=Product descriptionWebhooks
Receive real-time HTTP notifications when events occur in your PunchOut sessions. Configure webhooks in your partner portal.
Event Types
| Event | Description |
|---|---|
session.started | A new PunchOut session was created |
session.completed | A session was completed with cart data returned |
session.expired | A session expired without completion |
cart.updated | The cart contents were modified during a session |
Webhook Payload
POST {your-webhook-url}
Content-Type: application/json
X-SCX-Signature: sha256=abcdef123456...
X-SCX-Event: session.completed
X-SCX-Delivery-Id: d290f1ee-6c54-4b01-90e6...
X-SCX-Timestamp: 1705312200
{
"id": "d290f1ee-6c54-4b01-90e6...",
"event": "session.completed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"sessionId": "...",
"customerId": "98765",
"serviceCenterId": "42",
"items": [
{ "sku": "SKU-12345", "name": "Tribute Memorial", "quantity": 2, "unitPrice": 99.99 }
],
"subtotal": 199.98,
"currency": "USD",
"completedAt": "2024-01-15T10:35:00Z"
}
}
Verifying Signatures
Verify webhook authenticity by computing an HMAC-SHA256 signature of the raw request body using your webhook signing secret:
// Compute expected signature
const crypto = require('crypto');
const expectedSig = 'sha256=' + crypto
.createHmac('sha256', webhookSecret)
.update(rawBody)
.digest('hex');
// Compare with X-SCX-Signature header
if (expectedSig === req.headers['x-scx-signature']) {
// Signature valid — process the webhook
}
Error Handling
When a request fails, the response includes an error message and error code to help diagnose the issue.
REST API Error Response
{
"success": false,
"error": "Customer ID not found in partner mappings",
"errorCode": "INVALID_CUSTOMER"
}
Error Codes
| Error Code | Description |
|---|---|
AUTH_FAILED | Invalid API key, shared secret, or credentials |
MISSING_CUSTOMER_ID | The customerId field was not provided |
INVALID_CUSTOMER | Customer ID not found in partner mappings |
INVALID_SERVICE_CENTER | Service center not found for the given customer |
cXML Error Response
<cXML>
<Response>
<Status code="401" text="Unauthorized">Authentication failed</Status>
</Response>
</cXML>
Session Timeout
Sessions expire after 4 hours by default. Expired sessions cannot be completed and return an error. Use the SessionPingUrl feature to implement keep-alive pings—SCX will ping the provided URL every 60 seconds while the session is active.