Integration Best Practices

This page provides best practices and recommendations for integrating with the Solar Procurement Services API. It is intended to help developers design robust, efficient, and scalable integrations by correctly handling catalog data, product lifecycle, pricing, inventory, and order processing.

Handling the Full Product Catalog

When using the Solar Procurement Services API, you will receive the full product catalog, including products in all statuses.

This is by design and ensures that your system always has a complete and up-to-date view of the assortment, including any lifecycle changes. The API supports returning either the full catalog or only changes depending on how it is used.

To handle this correctly in your solution, it is important to actively use the product status as part of your integration logic.

The product statuses are:

  • 10 – Active

  • 11 – Active (stocked in another central warehouse)

  • 33 – Being phased out

  • 40 – Phased out

✅ Recommended approach

  • Compare with your previous data
    Retrieve the catalog and compare it with your previous dataset to identify changes in product status.

  • Handle phased-out products
    Products with status 40 should be removed or marked as inactive in your system.

  • Filter for downstream usage
    When requesting price and availability:

    • Include products with status 10, 11, 33

    • Exclude products with status 40

This ensures that your system remains aligned with Solar’s product assortment while avoiding processing products that are no longer available.

Use Delta Synchronization (lastChanged)

The product API supports retrieving only changed data using the lastChanged parameter.

If provided, only products changed after a specific timestamp will be returned. If omitted, the full product catalog is returned.

✅ Recommended approach

  • Use a full synchronization during initial load

  • Store the lastChanged timestamp per product

  • Use delta requests for ongoing synchronization

  • Combine with product status handling to detect lifecycle changes

This reduces data volume and improves performance.

Handle Pagination Correctly

Several endpoints (e.g. categories and products) use pagination with:

  • limit (maximum number of records)

  • nextPage token in the response

✅ Recommended approach

  • Always process responses until isLastPage = true

  • Use the nextPage value provided in the response for subsequent calls

  • Avoid assuming that all data is returned in a single request

This ensures completeness of data retrieval.

Authentication and Security

All API requests require authentication using a token retrieved via the authentication endpoint.

The API requires:

  • Authorization header (Bearer token)

  • Subscription key (header or query parameter)

✅ Recommended approach

  • Securely store credentials (ClientId and Secret)

  • Cache and reuse tokens until expiration

  • Handle token expiration gracefully by refreshing the token

Use Consistent Product Identification

The API supports multiple product identifiers such as:

  • ElectricalNumber

  • HWSNumber

  • EANNumber

  • SAPMaterialNumber

For pricing and ordering, SAPMaterialNumber is the only identifier supported.

✅ Recommended approach

  • Internally standardize on SAPMaterialNumber

  • Convert other identifiers to SAPMaterialNumber where needed

  • Ensure consistency across catalog, pricing, inventory, and ordering

Requesting Price and Availability

Pricing and availability are not included in the catalog response and must be retrieved via dedicated endpoints:

  • /products/prices

  • /products/atp

When using the Price API you will need an accountId parameter.

Why is Account ID Required?

Solar pricing is customer-specific.
The returned prices depend on:

  • Customer agreements

  • Discounts

  • Country

  • Account setup

  • Commercial conditions

For this reason, the API requires an accountId to determine the correct prices to return.

Retrieving the Account ID

The available account IDs depend on the user associated with the access token.

Before requesting prices, you must first retrieve the list of accounts available to your integration by calling the Get Accounts endpoint.

Step 1: Retrieve Available Accounts

GET /accounts
Authorization: Bearer {access_token}

Example response:

[ 
{
"accountId": "123456",
"accountName": "Solar Installation A/S",
"accountName2": "Copenhagen Branch"
},
{
"accountId": "789012",
"accountName": "Solar Installation A/S",
"accountName2": "Aarhus Branch"
}
]

The response contains all accounts that the authenticated user has access to.

Step 2: Select the Appropriate Account

Choose the account that should be used for Pricing

Example:

{
  "accountId": "123456",
  "accountName": "Solar Installation A/S",
  "accountName2": "Copenhagen Branch"
}

Step 3: Use the Account ID When Requesting Prices

Example request:

POST /products/prices?accountId=123456&countrycode=dk
Authorization: Bearer {access_token}
Content-Type: application/json

Request body:

{
  "productIdentifier": "SAPMaterialNumber",
  "products": [
    {
      "productId": "1200521672"
    },
    {
      "productId": "1200468795"
    }
  ]
}

Recommended Approach

  1. Retrieve the list of available accounts once after authentication.

  2. Let the user select the desired account if multiple accounts are available.

  3. Store the selected account ID in your application.

  4. Use the same account ID when requesting Prices

This ensures that all information returned by the Procurement Services APIs is consistent and based on the same customer account.

✅ Recommended approach

  • Always request price and ATP (availability) as separate calls

  • Batch requests where possible (respect limits, e.g. max 500 products for pricing)

  • Filter out irrelevant products (e.g. status 40) before requesting

Understanding Prices, Quantities and Units

The pricing API returns prices together with the quantity and unit to which the price applies.

Price Fields

  • Price: The price amount in the specified currency.

  • PriceQuantity: The quantity to which the price applies.

  • UnitCode: The unit of measure associated with the price.

  • Currency: Currency of the returned price.

How to Interpret Prices

The returned price always applies to the quantity specified in PriceQuantity and the unit specified in UnitCode.

Example 1: Product Sold per Meter

Response:

{
    "Price": 6687.17,
    "PriceType": "NetPrice",
    "PriceQuantity": 1,
    "UnitCode": "MTR",
    "Currency": "DKK"
}

Interpretation:

Net price is 6687.17 DKK for 1 meter (MTR)
Effective unit price:
6687.17 DKK per MTR

Example 2: Product Sold per Package

Response:

{
    "Price": 834,
    "PriceType": "NetPrice",
    "PriceQuantity": 1,
    "UnitCode": "PK",
    "Currency": "DKK"
}

Interpretation:

Net price is 834 DKK for 1 package (PK)
Effective unit price:
834 DKK per PK

Example 3: Price for Multiple Units

Response:

{
    "Price": 800,
    "PriceQuantity": 10,
    "UnitCode": "PC",
    "Currency": "DKK"
}

Interpretation:

Price is 800 DKK for 10 pieces
Effective unit price:
800 / 10 = 80 DKK per PC

⚠️ Important

Data returned by the Price API must only be interpreted together with the fields returned by the Price API itself.

Consumers must not combine pricing calculations with catalog fields such as:

  • minimumOrderQuantity

  • multiplum

  • packageSize

  • baseUnitofMeasure

The fields Price, PriceQuantity, and UnitCode completely describe how the returned price should be interpreted.

Ordering constraints such as minimum quantities and order increments are described separately in the Product Catalog API and should only be used when validating order quantities.

Location-Specific Inventory Handling

For certain countries, inventory requests require additional information:

  • Postal code is required when multiple warehouses exist (e.g. Sweden)

✅ Recommended approach

  • Always include postal code where applicable

  • Treat inventory as location-dependent

  • Ensure correct delivery context when querying availability

Respect Units, Multiples, and Quantities

Products include fields such as:

  • unit (sales unit)

  • baseUnitofMeasure

  • salesUnitofMeasure

  • multiplum (order increment)

  • minimumOrderQuantity

✅ Recommended approach

Before placing orders, your system should validate requested quantities against these values to ensure that orders can be processed successfully.

Example 1: Product Sold in Packages

Product Data

{
  "baseUnitofMeasure": "PCE",
  "salesUnitofMeasure": "PK",
  "packageSize": 10,
  "minimumOrderQuantity": 1,
  "multiplum": 1
}

Interpretation

The product is stored as individual pieces (PCE) but sold in packages (PK). Each package contains 10 pieces.

Valid Orders

  • 1 PK

  • 2 PK

  • 5 PK

Invalid Order

  • 5 PCE

Always use the salesUnitofMeasure when this field is available and you want to display prices, quantities, and creating orders.

Example 2: Minimum Order Quantity

Product Data

{
  "salesUnitofMeasure": "PCE",
  "minimumOrderQuantity": 25,
  "multiplum": 1
}

Valid Orders

  • 25 PCE

  • 50 PCE

  • 100 PCE

Invalid Orders

  • 1 PCE

  • 10 PCE

  • 24 PCE

The ordered quantity must always be greater than or equal to the specified minimumOrderQuantity.

Example 3: Order Multiples (Multiplum)

Product Data

{
  "salesUnitofMeasure": "M",
  "minimumOrderQuantity": 10,
  "multiplum": 5
}

Valid Orders

  • 10 M

  • 15 M

  • 20 M

  • 25 M

Invalid Orders

  • 11 M

  • 18 M

  • 22 M

Quantities must be ordered in increments defined by the multiplum value.

Example 4: Cable Sold by Length

Product Data

{
  "salesUnitofMeasure": "M",
  "cableCut": true,
  "minimumOrderQuantity": 10,
  "multiplum": 1
}

Valid Orders

  • 10 M

  • 11 M

  • 25 M

  • 100 M

Because cableCut is set to true, the product can be ordered in custom lengths as long as the minimum order quantity is respected.

Example 5: Quantity Validation Logic

Product Data

{
  "salesUnitofMeasure": "PCE",
  "minimumOrderQuantity": 20,
  "multiplum": 5
}

Validation Rule

Requested Quantity >= Minimum Order Quantity
AND
(Requested Quantity - Minimum Order Quantity) is divisible by Multiplum

Valid Orders

  • 20 PCE

  • 25 PCE

  • 30 PCE

  • 35 PCE

Invalid Orders

  • 15 PCE

  • 21 PCE

  • 28 PCE

  • 33 PCE

Recommended Validation Flow

  1. Read salesUnitofMeasure

  2. Read minimumOrderQuantity

  3. Read multiplum

  4. Validate the requested quantity

  5. Display quantities using the sales unit returned by the API

  6. Reject or adjust quantities that do not comply with the product's ordering rules

Following this approach ensures that orders comply with Solar's sales and logistics requirements and reduces the risk of order validation errors.

Order Creation Best Practices

Orders are created via the /orders endpoint and require:

  • Account ID

  • Product identifiers (SAPMaterialNumber)

  • Quantity

  • Delivery information

✅ Recommended approach

  • Validate product data before placing orders

  • Ensure correct delivery address selection

  • Include customer references for traceability

  • Handle errors and confirmation responses properly

General Integration Principles

  • Design for eventual consistency (catalog vs price vs inventory)

  • Treat the catalog as the source of truth for product metadata

  • Use stateless API calls combined with local caching

  • Monitor for changes using lastChanged + status transitions

  • Implement retry logic and error handling for resilience