β±οΈ Time to Complete: 2-3 hours
jobAccountNumber saved (from Step 5)A construction company may have multiple projects (job accounts) at the same branch, each with different billing and shipping addresses.
jobAccountNumber in customer sessionGET /branches/v2/customerBranchLocations/{customerCode}https://services-qa.roofhub.pro/branches/v2/customerBranchLocations/CUST12345Authorization: Bearer {token}Content-Type: application/json[
{
"branchCode": "CORAC", // πͺ Branch identifier
"branchName": "AMERICAN ROOFING SUPPLY - RAPID CITY", // π’ Branch display name
"distanceFromShipToInMiles": 499.403, // π Distance from customer ship-to address
"jobAccounts": [ // π CRITICAL - Job accounts for this customer at this branch
{
"jobAccountNumber": 43, // π― Required for Step 8 order submission!
"jobAccountName": "TUSING BUILDERS & RFG (SOLON)" // π Job account description
}
]
},
{
"branchCode": "CORMN",
"branchName": "AMERICAN ROOFING SUPPLY - MINNEAPOLIS",
"distanceFromShipToInMiles": 234.567,
"jobAccounts": [
{
"jobAccountNumber": 89, // π― Required for Step 8!
"jobAccountName": "CONSTRUCTION PROJECT A"
},
{
"jobAccountNumber": 90, // π― Multiple job accounts possible
"jobAccountName": "REMODELING PROJECT B"
}
]
}
]jobAccountNumber: Required for order submission in Step 8 (numeric value)branchCode: Branch identifier for product/pricing queriesdistanceFromShipToInMiles: Helps select nearest branchjobAccounts: Array - customers can have multiple job accounts per branchjobAccountNumber from the desired job account - you'll need it for Step 8! Note: It's a numeric value, not a string.A roofing shingle may be available in 15 colors at one branch but only 8 colors at another. This endpoint tells you exactly what's available where.
productImageUrl)null imagesGET /branches/v2/activeBranchProducts/{branchCode}https://services-qa.roofhub.pro/branches/v2/activeBranchProducts/ATLAuthorization: Bearer {token}Content-Type: application/json[
{
"productId": 6706, // π Unique product identifier
"productName": "Atlas GlassMaster 30 Shingles", // π¦ Product display name
"productOptions": [ // π¨ Available color/size options
"36\" x 12\" Black Shadow",
"36\" x 12\" Hearthstone Gray",
"36\" x 12\" Weathered Wood"
],
"productVariant": [ // π Variants with UOM details
{
"variantId": 0,
"selectedOption": "36\" x 12\" Black Shadow",
"uoMs": ["SQ", "BD"] // π Available units of measure
},
{
"variantId": 0,
"selectedOption": "36\" x 12\" Hearthstone Gray",
"uoMs": ["SQ", "BD"]
},
{
"variantId": 0,
"selectedOption": "36\" x 12\" Weathered Wood",
"uoMs": ["BD", "SQ"]
}
],
"productDescription": "High-quality architectural shingles", // π Product description
"productFeatures": [ // β¨ Key selling points
"30-year warranty",
"Wind resistance up to 130 mph",
"Class A fire rating"
],
"productUOM": ["SQ", "BD"], // π All available UOMs
"productCategory": "Shingles", // ποΈ Category
"manufacturer": "Atlas", // π Manufacturer name
"productImageUrl": "https://example.com/image.jpg", // πΌοΈ Product image (or null)
"allowSubstitution": true, // π Can substitute if out of stock
"primaryItem": true // β Is this the primary/default item
},
{
"productId": 94860,
"productName": "Atlas Pinnacle Impact IR Shingle",
"productOptions": [
"14\" x 42\" Desert Shake",
"14\" x 42\" Weathered Wood"
],
"productVariant": [
{
"variantId": 0,
"selectedOption": "14\" x 42\" Desert Shake",
"uoMs": ["BD"]
},
{
"variantId": 0,
"selectedOption": "14\" x 42\" Weathered Wood",
"uoMs": ["BD"]
}
],
"productDescription": "Impact-resistant shingles with IR technology",
"productFeatures": [
"Impact resistant",
"Energy efficient",
"Premium warranty"
],
"productUOM": ["BD"],
"productCategory": "Shingles",
"manufacturer": "Atlas",
"productImageUrl": null,
"allowSubstitution": false,
"primaryItem": false
}
]productId: Use this for pricing (Step 7) and order submission (Step 8)productOptions: Available color/size variantsproductVariant: Maps options to available UOMsproductUOM: Available units of measure (SQ=Square, BD=Bundle)allowSubstitution: Whether alternative products can be substitutedCustomer A gets 18/square (standard rate). Same product, different pricing!
| messageCode | Meaning | Action |
|---|---|---|
0 | Success | Proceed with order |
> 0 | Warning/Error | Check message field |
price = 0 | No pricing | Contact SRS or choose different product |
availableStatus = "Call" | Limited stock | Warn user, allow order |
POST /products/v2/priceAuthorization: Bearer {token}Content-Type: application/json{
"sourceSystem": "SOURCENAME", // π Your integration identifier
"customerCode": "DEMO001", // π€ Customer account number
"branchCode": "HWPLY", // πͺ Branch code
"transactionId": "SPR-1", // π― Unique transaction ID
"jobAccountNumber": 1, // π Job account number (numeric)
"productList": [
{
"productId": 77673, // π¦ Product ID from Step 6
"productName": "Ace Insulation Plates",
"productOptions": ["N/A"],
"quantity": 1,
"uom": "PC"
}
]
}[
{
"itemCode": "ACEACEPLT3INI", // π Internal item code
"productId": 77673, // π¦ Matches request product ID
"productName": "Ace Insulation Plates", // π Product name
"productOptions": ["N/A"], // π¨ Selected options
"priceUOM": "PC", // π Base unit of measure for pricing
"requestedUOM": "PC", // π Requested unit of measure
"uomConversionFactor": 1, // π Conversion factor (1 = no conversion)
"price": 0.25, // π° CRITICAL - Unit price for this customer
"availableStatus": "Call for Availability", // β
Stock status
"transactionId": "SPR-1", // π― Matches request transaction ID
"message": "", // π’ Additional messages (empty if no issues)
"messageCode": 0 // π’ Message code (0 = success)
}
]price: Current unit price for this customeravailableStatus: Stock availability ("In Stock", "Call for Availability", etc.)priceUOM: Base unit of measure for pricinguomConversionFactor: Conversion multiplier between requested and price UOMmessageCode: 0 = success, other values indicate warnings/errors| Aspect | Synchronous | Asynchronous |
|---|---|---|
| Processing | Immediate | Queued |
| Response Time | 1-3 seconds | Instant (queued) |
| Order ID | Immediate | Via webhook later |
| During Maintenance | β May fail | β Queued safely |
| Retry Logic | Manual | Automatic |
| Best For | Testing, low volume | Production, high volume |
| Webhook Required | No | Yes |
| Reliability | Medium | High |
| Synchronous (Staging & Production) | Asynchronous (Production Only - Recommended) |
|---|---|
| How it works: Order processed immediately Instant Order ID response Best for: Staging environment testing Low-volume integrations Simple implementations | How it works: Order queued for processing Status updates via webhooks Best for: Production deployments High-volume integrations Maximum reliability Requires webhook setup |
POST /orders/v2/submitAuthorization: Bearer {token}Content-Type: application/jsonasync flag in the request.{
"sourceSystem": "SOURCENAME", // π REQUIRED - Your integration identifier
"customerCode": "DEMO001", // π REQUIRED - From Step 3
"jobAccountNumber": 1, // π REQUIRED - Numeric value from Step 5!
"branchCode": "BRRIV", // π REQUIRED - Branch code
"accountNumber": "DEMO001", // π REQUIRED - Customer account number
"transactionID": "3932cdd6-38e7-4d19-a05c-cd866473bdea", // π REQUIRED - Unique transaction ID
"transactionDate": "2023-05-11T10:49:34.187", // π REQUIRED - ISO 8601 format
"notes": "", // π REQUIRED - Order notes (can be empty string)
"shipTo": { // π REQUIRED - Ship-to address
"name": "John", // π REQUIRED
"addressLine1": "1234 COUNTY LINE ROAD", // π REQUIRED
"addressLine2": "", // π REQUIRED (can be empty)
"addressLine3": "", // π REQUIRED (can be empty)
"city": "ONTARIO", // π REQUIRED
"state": "NY", // π REQUIRED
"zipCode": "14519" // π REQUIRED
},
"poDetails": { // π REQUIRED - PO and delivery details
"poNumber": "5641-8Test", // π REQUIRED - Purchase order number
"reference": "5641: 7GP", // π REQUIRED - Reference (can be empty)
"jobNumber": "", // π REQUIRED - Job number (can be empty)
"orderDate": "2021-04-12", // π REQUIRED - Order date (YYYY-MM-DD)
"expectedDeliveryDate": "2021-04-15", // π REQUIRED - Delivery date (YYYY-MM-DD)
"expectedDeliveryTime": "Anytime", // π REQUIRED - Delivery time (can be "Anytime")
"orderType": "WHSE", // π REQUIRED - "WHSE" (delivery) or "WILLCALL" (pickup)
"shippingMethod": "Ground Drop" // π REQUIRED - Shipping method
},
"orderLineItemDetails": [ // π REQUIRED - Line items array
{
"productId": 75664, // π REQUIRED - Product ID from Step 6
"productName": "CertainTeed Presidential Solaris Shingles", // π REQUIRED - Product name
"option": "Country Gray", // π REQUIRED - Selected color/option
"quantity": 1, // π REQUIRED - Quantity (integer)
"price": 12, // π REQUIRED - Price (integer)
"customerItem": "XXXX", // π REQUIRED - Customer reference
"uom": "SQ" // π REQUIRED - Unit of measure
},
{
"productId": 1443,
"productName": "CertainTeed Landmark Solaris Non-AR Shingles",
"option": "Burnt Sienna",
"quantity": 1,
"price": 12,
"customerItem": "XXXX",
"uom": "SQ"
},
{
"productId": 75621,
"productName": "CertainTeed SwiftStart Starter",
"option": "N/A",
"quantity": 1,
"price": 12,
"customerItem": "XXXX",
"uom": "BD"
}
],
"customerContactInfo": { // π REQUIRED - Customer contact details
"customerContactName": "John Dough", // π REQUIRED - Contact name
"customerContactPhone": "9876543210", // π REQUIRED - Phone number
"customerContactEmail": "jdough@example.com", // π REQUIRED - Email
"customerContactAddress": { // π REQUIRED - Contact address
"addressLine1": "123 Main St",
"city": "Salt Lake City",
"state": "Utah",
"zipCode": "84121"
},
"additionalContactEmails": [ // π REQUIRED - Additional emails array (can be empty)
"test@example.com"
]
}
}400 Bad Request - Missing required field: jobAccountNumber// β Wrong
{
"customerCode": "DEMO001"
// jobAccountNumber missing
}
// β
Correct
{
"customerCode": "DEMO001",
"jobAccountNumber": 1 // Required numeric value
}Order submission failed - Invalid job account// β Wrong - String value
{
"jobAccountNumber": "1" // Wrong: string
}
// β Wrong - Non-existent number
{
"jobAccountNumber": 999 // Doesn't exist for this customer
}
// β
Correct - Valid numeric value from Step 5
{
"jobAccountNumber": 43 // From customerBranchLocations response
}Product not found at branchInvalid date format// β Wrong formats
{
"orderDate": "04/12/2021", // MM/DD/YYYY not accepted
"expectedDeliveryDate": "2021.04.15" // Wrong separator
}
// β
Correct format: YYYY-MM-DD
{
"orderDate": "2021-04-12",
"expectedDeliveryDate": "2021-04-15"
}Invalid orderType value// β Wrong
{
"orderType": "Delivery", // Wrong: must be code
"shippingMethod": "Ground" // Incomplete
}
// β
Correct
{
"orderType": "WHSE", // For delivery (or "WILLCALL" for pickup)
"shippingMethod": "Ground Drop" // From branch shippingMethods array
}Price validation failedInvalid shipping address// β
All fields required (can be empty string but must exist)
{
"shipTo": {
"name": "John Doe", // Required
"addressLine1": "123 Main St", // Required
"addressLine2": "", // Required (can be empty)
"addressLine3": "", // Required (can be empty)
"city": "Denver", // Required
"state": "CO", // Required (2-letter code)
"zipCode": "80202" // Required (5 or 9 digits)
}
}jobAccountNumber from Step 5jobAccountNumber is numeric (not string)orderType is "WHSE" or "WILLCALL"shippingMethod matches branch available methodsquantity are integersprice are integers (e.g., 12 not 12.00)state is 2-letter code ("CO" not "Colorado")orderID from responsetransactionID from responsequeueID if async{
"message": "Order Submitted", // β
Order successfully submitted
"transactionID": "ANY-UNIQUE-STRING-02.19.2024.v2.4", // π― Your unique transaction ID (matches request)
"orderID": "35818786", // π SAVE THIS! - SRS order ID for tracking
"queueID": "queue-abc123" // π Queue identifier (null for sync, value for async)
}message - Confirmation messagetransactionID - Your unique transaction ID (from request)orderID - SRS order identifier - Use this to track order status via API or webhooksqueueID - Queue identifier (null for synchronous, has value for asynchronous processing)| Metric | Target | How to Measure |
|---|---|---|
| API Response Time | < 500ms avg | Log timestamps per request |
| Order Success Rate | > 99% | (Successful / Total) * 100 |
| Authentication Failures | < 0.1% | 401 errors / total requests |
| Price Cache Hit Rate | > 80% | Cached / Total price requests |
| Token Refresh Rate | β 1/day | Token refresh events per day |
| Order Processing Time | < 5 sec (sync) | Submit to confirmation time |
| Webhook Delivery | < 30 sec | Event to webhook receipt time |
| Event | Description | When Triggered |
|---|---|---|
order.queued | Order accepted to queue | Immediately after submission |
order.processing | Order being prepared | When warehouse starts |
order.shipped | Order dispatched | When truck leaves |
order.delivered | Order completed | Upon delivery |
order.error | Order failed | If processing error |
order.cancelled | Order cancelled | If customer/SRS cancels |
{
"eventType": "order.shipped",
"orderID": "35818786",
"transactionID": "YOUR-TRANSACTION-ID",
"status": "SHIPPED",
"timestamp": "2026-02-27T14:30:00Z",
"trackingNumber": "1Z999AA10123456784",
"carrier": "UPS",
"estimatedDelivery": "2026-02-28"
}| Error Type | HTTP Code | Retry? | Action |
|---|---|---|---|
| Validation Errors | 400 | No | Fix request and resubmit |
| Authentication | 401 | Yes (once) | Refresh token and retry |
| Forbidden | 403 | No | Contact SRS support |
| Not Found | 404 | No | Verify endpoint URL |
| Rate Limit | 429 | Yes | Wait and retry with backoff |
| Server Error | 500 | Yes | Retry with exponential backoff |
| Service Unavailable | 503 | Yes | Retry after delay |
π Integration Health Dashboard
ββββββββββββββββββββββββββββββ
Today's Orders: 157 (β 12% vs yesterday)
Success Rate: 99.4% (π’ Target: 99%)
Avg Response Time: 342ms (β
Target: <500ms)
Webhook Delivery: 28s (β
Target: <30s)
Errors (24h): 1 (β
Target: <2%)
Top Products:
1. Shingles (45%)
2. Underlayment (22%)
3. Flashing (18%)
Peak Hours: 9-11 AM, 2-4 PMaccountNumber = Customer account identifier (from Step 3)jobAccountNumber = Specific job/project within that account (from Step 5)12 not 12.00). This is by design to avoid floating-point precision issues."2026-02-27").5. GET CUSTOMER BRANCHES
β
GET /branches/v2/customerBranchLocations/{code}
β
Save: jobAccountNumber (REQUIRED for Step 8!)
6. GET PRODUCTS
β
GET /branches/v2/activeBranchProducts/{branchCode}
β
Save: productId, productUOM
7. GET PRICING
β
POST /products/v2/price
Body: { customerCode, branchCode, productList }
β
Save: price, availableStatus
8. SUBMIT ORDER
β
POST /orders/v2/submit
Body: { All required fields from Steps 1-7 }
β
Receive: orderID, transactionID
β
π SUCCESS!| Step | Save This | Type | Example | Use In |
|---|---|---|---|---|
| 5 | jobAccountNumber | number | 43 | Step 8 |
| 5 | branchCode | string | "BRRIV" | Steps 6,7,8 |
| 6 | productId | number | 75664 | Steps 7,8 |
| 6 | productUOM | array | ["SQ","BD"] | Steps 7,8 |
| 7 | price | number | 12 | Step 8 |
| 7 | availableStatus | string | "In Stock" | Display |
| 8 | orderID | string | "35818786" | Tracking |
Step 3 (Auth Guide) Step 5
ββββββββββββββββββ ββββββββββββββββββ
β customerCode βββββββΆβ jobAccountNum β
β accountNumber β β branchCode βββββββΌ
ββββββββββββββββββ ββββββββββββββββββ
β
Step 6 β Step 7
βββββββββββββββββββββ
β productId β
β productUOM ββββββΆβββββββββββββ
ββββββββββββββββββββ β price β
β available β
ββββββββ¬ββββββ
β
Step 8 βΌ
βββββββββββββ
β ALL DATA β
β Submit! β
ββββββββ¬ββββββ
β
βΌ
βββββββββββββ
β orderID β
β π SUCCESS β
βββββββββββββjobAccountNumber as string instead of number{
"sourceSystem": "YOUR_SYSTEM_NAME",
"customerCode": "FROM_STEP_3",
"jobAccountNumber": 0, // FROM_STEP_5 - NUMERIC!
"branchCode": "FROM_STEP_5",
"accountNumber": "FROM_STEP_3",
"transactionID": "UNIQUE_ID_" + Date.now(),
"transactionDate": new Date().toISOString(),
"notes": "Test order",
"shipTo": {
"name": "Customer Name",
"addressLine1": "123 Main St",
"addressLine2": "",
"addressLine3": "",
"city": "City",
"state": "ST",
"zipCode": "12345"
},
"poDetails": {
"poNumber": "PO-" + Date.now(),
"reference": "Ref 123",
"jobNumber": "Job 456",
"orderDate": "2026-02-27",
"expectedDeliveryDate": "2026-03-01",
"expectedDeliveryTime": "Anytime",
"orderType": "WHSE",
"shippingMethod": "Ground Drop"
},
"orderLineItemDetails": [
{
"productId": 0, // FROM_STEP_6
"productName": "FROM_STEP_6",
"option": "FROM_STEP_6",
"quantity": 1,
"price": 0, // FROM_STEP_7 - INTEGER!
"customerItem": "Your SKU",
"uom": "FROM_STEP_6" // Must be valid for product
}
],
"customerContactInfo": {
"customerContactName": "Contact Name",
"customerContactPhone": "1234567890",
"customerContactEmail": "email@example.com",
"customerContactAddress": {
"addressLine1": "123 Contact St",
"city": "City",
"state": "ST",
"zipCode": "12345"
},
"additionalContactEmails": []
}
}jobAccountNumber is number, not stringproductId is number, not stringquantity is integerprice is integer (12 not 12.00)state is 2-letter codetransactionID is uniquepoNumber is uniqueorderType is "WHSE" or "WILLCALL"