Skip to main content

Supplier Webhooks

Our webhook system allows third‑party Suppliers to receive real‑time notifications about key events in our platform. By subscribing to these webhooks, your systems can react immediately to important events such as new user connections, orders placed, and changes to supplier quotes.


Authentication​

Requests must include a bearer token in the HTTP Authorization header.


Supplier Event Webhook (User Connected / Order Placed)​

The event webhook URL is set on the linked distributor resource. It receives user_connected and order_placed events.

Endpoints​

MethodEndpointDescription
PUT/api/orgs/:org_id/linked_distributorSet webhook URL
GET/api/orgs/:org_id/linked_distributorGet webhook URL
  • :org_id - your OpenSolar Organization ID

Configuring Webhook URL​

Request Body

{
"event_webhook_url": "<url>"
}

Success Response — 200 OK

{
"id": "<string>",
"org": "<url>",
"org_name": "<string>",
"filter_key": "<string>",
"name": "<string>",
"countries": "<country_code>",
"is_enabled": true,
"event_webhook_url": "<url>",
"logo_url": null,
"description": "<string>",
"privacy_policy_url": "<url>",
"terms_of_use_url": "<url>"
}

Note: Privacy Policy and Terms of Use links can be updated via the Configuration page under Suppliers in your Control area on the OpenSolar platform.

Webhook Events​

User Connected​

Triggered when a user submits their details to your Organization via the OpenSolar platform.

Fields Returned

FieldTypeDescription
emailstringUser's email address.
phonestringUser's phone number.
first_namestringUser's given name.
family_namestringUser's surname.
job_titlestringUser's job title.
org_namestringName of the Organization the user belongs to.
org_idstringUnique identifier of the Organization.
addressstringStreet address of the Organization.
zipstringPostal/ZIP code of the Organization's address.
statestringState or region of the Organization's address.

Example Payload

{
"event": "user_connected",
"details": {
"email": "susan.rays@example.com",
"phone": "+1-555-987-6543",
"first_name": "Susan",
"family_name": "Rays",
"job_title": "Sales Manager",
"org_name": "Acme Solar Solutions",
"org_id": "5678",
"address": "456 Green Energy Blvd",
"zip": "90210",
"state": "CA"
}
}

Order Placed​

Triggered when a customer places a new order.

Fields Returned

FieldTypeDescription
org_idintegerOpenSolar's unique identifier of the Organization.
order_idintegerOpenSolar's unique identifier generated for the order.
seller_org_referencestringThe Supplier's identifier of the Organization if set.
preferred_supplier_locationstringDefault location set for the supplier.
total_itemsintegerNumber of items in the order.
itemsarrayList of items in the order.
subtotal_pricestringTotal price before tax.
total_pricestringTotal price including tax.
total_taxstringTotal tax amount. Omitted for US orders (see note below).
project_idsarrayRelated project IDs, if any.
shipping_infoobjectShipping and delivery details.
contact_infoobjectDelivery contact details.
supplier_idintegerUnique organization identifier of the Supplier.
discountsobject | nullDeals and discounts applied to the order, or null if none. See Deals & Discounts.
shipping_costobject | nullShipping cost details, or null if none.

For orders placed in the United States:

  • subtotal_price and total_price will always be the same value, as sales tax is not calculated.
  • The total_tax field will not be included in the payload.

shipping_info Object

FieldTypeDescription
payment_optionstringSelected payment method for the order (e.g. "cash", "credit").
delivery_datestringScheduled date for delivery or collection.
delivery_timestring (optional)Preferred delivery time from checkout, HH:MM:SS±HH:MM when set.
collection_locationstring (optional)Chosen pickup location when delivery method is collection.
delivery_instructionsstringAdditional instructions provided for delivery.
delivery_methodstringMethod of fulfillment: "delivery" or "collection".
addressobjectDelivery address details for the order.

Note: The collection_location field is optional, and will be visible only when the delivery method is Collection and a Supplier has multiple locations defined.

discounts Object

Contains information about discounts applied to the order, including the currency, discount applications, and the allocation of discount amounts. For Deal types, Supplier Assist, and worked examples, see Deals & Discounts.

FieldTypeDescription
currencystringThe ISO currency code in which discount amounts are expressed.
total_discount_amountstringThe total value of all discounts applied to the order.
discount_applicationsarrayA list of discounts applied to the order. See Discount application below.
Each application has a corresponding allocation (see Discount allocation below).
discount_allocationsarrayA list showing how each discount is allocated to line items or the order. See Discount allocation below.
Each allocation references a discount application (see above).

Each item in discount_applications has the following fields:

FieldTypeDescription
idstringA unique identifier for the discount application.
sourcestringIdentifies the system or mechanism that created or provided the discount.
typestringThe type of discount, such as percentage or fixed_amount.
titlestringA short, user-facing name for the discount.
descriptionstring | nullAn optional description providing additional information about the discount.
targetstringSpecifies what the discount applies to, such as line_item or order.
valueobjectDefines the value of the discount. See value object below.
priorityinteger | nullDetermines the order in which applicable discounts are processed. Lower values indicate higher priority.

value object (within each discount application)

FieldTypeDescription
kindstringSpecifies how the discount value is interpreted, such as percentage or fixed_amount.
amountstringThe discount value. For a percentage discount, this represents the percentage; for a fixed amount, it represents the monetary amount.

Each item in discount_allocations has the following fields:

FieldTypeDescription
discount_application_idstringReferences the id of the discount application responsible for the allocation.
targetstringSpecifies what the allocation applies to, such as line_item or order.
skustring | nullThe SKU of the line item receiving the discount. null when the discount applies to the entire order.
amountstringThe monetary amount of the discount allocated to the specified target.

shipping_cost Object

FieldTypeDescription
labelstring | nullDisplay label for the shipping method (e.g. "Standard Delivery").
costnumber | nullThe shipping cost amount in currency.

Example Payload

{
"event": "order_placed",
"details": {
"org_id": 1018,
"order_id": 1234,
"seller_org_reference": 123,
"preferred_supplier_location": "nottingham_warehouse",
"supplier_id": 1056,
"total_items": 1,
"subtotal_price": "20.00",
"total_tax": "4.00",
"total_price": "24.00",
"project_ids": [],
"items": [
{
"quantity": 1,
"title": "Aiko Neostar 2S 455W N0Type ABC, 54 Cell, Mono Glass All Black, Gen 2",
"product_code": "AIKO-A455-MAH54Mb/2S",
"total_price": "20.00",
"distributor_product_code": "AIKO-A455-MAH54Mb/2S"
}
],
"shipping_info": {
"payment_option": "cash",
"delivery_date": "07/31/2025",
"delivery_time": "09:30:00-07:00",
"delivery_instructions": "Deliver to doorstep",
"delivery_method": "delivery",
"address": {
"address": "123 Solar Drive",
"locality": "Los Angeles",
"state": "CA",
"zip": "90210",
"country_name": "United States of America"
}
},
"contact_info": {
"email": "susanrays@solartest.com",
"phone_number": "+1-555-555-1234",
"first_name": "Susan",
"last_name": "Rays",
"org_name": "Solar Inc"
},
"discounts": {
"currency": "GBP",
"total_discount_amount": "48.00",
"discount_applications": [
{
"id": "deal:3",
"source": "deal",
"type": "percentage",
"title": "10% off",
"description": "10% off on Panels",
"target": "line_item",
"value": {
"kind": "percentage",
"amount": "10.00"
},
"priority": 1
},
{
"id": "deal:1",
"source": "deal",
"type": "percentage",
"title": "Bundle deal",
"description": "Bundle deal",
"target": "line_item",
"value": {
"kind": "percentage",
"amount": "20.00"
},
"priority": 10
}
],
"discount_allocations": [
{
"discount_application_id": "deal:3",
"target": "line_item",
"sku": "635654",
"amount": "10.00"
},
{
"discount_application_id": "deal:1",
"target": "line_item",
"sku": "635654",
"amount": "18.00"
},
{
"discount_application_id": "deal:1",
"target": "line_item",
"sku": "654995",
"amount": "10.00"
}
]
},
"shipping_cost": {
"label": "Standard Delivery",
"cost": 25.0
}
}
}
(Optional) Redirect User After Order Is Placed​

The order_placed webhook supports an optional redirect feature that can send customers to a custom URL after checkout.

The checkout_url must be returned in the JSON body of the same HTTP 200 OK response sent to acknowledge the webhook.

Example Response:

{
"checkout_url": "https://yourstore.com/thank-you"
}

When a valid checkout_url is provided, customers are redirected to this location after order completion. This can be used to redirect to a payment processing flow, a custom confirmation page, your order portal, and more.


Quote and Quote Activity Log Webhooks​

Suppliers can subscribe to real-time webhooks for Quote and Quote Activity Log changes. These use the platform's standard webhook infrastructure (documented in the API webhooks section) but are configured through a dedicated distributor endpoint rather than the general webhooks API. Quote webhooks fire on CREATE, UPDATE, and DELETE events; Quote Activity Log webhooks fire on CREATE and DELETE only (activity logs are immutable).

Key differences from the general webhooks API
  • Scope is fixed — you subscribe to Quote and/or QuoteActivityLog as a whole. There is no per-field control over trigger_fields or payload_fields; both are always quote.* and/or quoteactivitylog.*.
  • Configuration via UI or distributor API — these webhooks can be managed through the Seller Configuration UI in OpenSolar or via the distributor webhook API below.
  • Org targeting — webhooks fire to the supplier org when its org is the supplier on the quote.

Endpoints​

MethodEndpointDescription
GET/api/orgs/:org_id/distributor_webhooksList quote-related webhooks
POST/api/orgs/:org_id/distributor_webhooksCreate or update a webhook
DELETE/api/orgs/:org_id/distributor_webhooks?endpoint=<url>Delete a webhook by endpoint
  • :org_id - your OpenSolar Organization ID
  • Only admin users can manage webhooks.

Creating a webhook​

Request Body

{
"endpoint": "https://yourapp.com/webhooks/opensolar",
"headers": {
"Authorization": "Bearer your-secret-token"
},
"webhook_types": ["Quote", "QuoteActivityLog"],
"enabled": true
}
FieldTypeRequiredDescription
endpointstring (URL)YesThe URL that will receive webhook POST requests.
headersobject | nullNoCustom HTTP headers sent with each webhook request (e.g. auth tokens).
webhook_typesarray of stringsYesOne or both of "Quote" and "QuoteActivityLog". At least one is required.
enabledbooleanNoWhether the webhook is active. Defaults to true.

Response — 201 Created

{
"endpoint": "https://yourapp.com/webhooks/opensolar",
"headers": {
"Authorization": "Bearer your-secret-token"
},
"webhook_types": ["Quote", "QuoteActivityLog"],
"enabled": true
}

Updating an existing webhook​

To update an existing webhook, POST with an original_endpoint field alongside the new values.

{
"original_endpoint": "https://yourapp.com/webhooks/opensolar",
"endpoint": "https://yourapp.com/webhooks/v2",
"headers": {
"Authorization": "Bearer new-token"
},
"webhook_types": ["Quote"],
"enabled": true
}

Deleting a webhook​

DELETE /api/orgs/:org_id/distributor_webhooks?endpoint=https://yourapp.com/webhooks/opensolar

Response — 204 No Content

Webhook types​

Quote​

Fires when a quote is created, updated, or deleted. The payload follows the standard webhook structure with model set to "Quote". See Quote webhook payload for the full field reference.

QuoteActivityLog​

Fires when activity is logged on a quote — messages, file uploads, and system events such as status changes. Activity logs are immutable, so only CREATE and DELETE events are fired (never UPDATE). The payload has model set to "QuoteActivityLog". See Quote Activity Log webhook payload for the full field reference.