Add-ons: Technical reference

Technical reference for building a Storeganise Add-on, covering webhook structure, authentication, data fetching patterns, and access control conventions.

Note: For the full development process and partnership overview, see the Add-on: Partner guide.

Webhook event structure

Anatomy of a webhook POST request
When an event occurs in Storeganise, your Add-on receives a POST request containing four fields:
  • type   : the event that triggered the webhook, for example user.created    or job.unit_moveIn.completed   
  • data   : an object containing relevant IDs for the event, for example { userId }   or{ jobId }  . IDs vary depending on the event type.
  • apiUrl   : the base URL for making API calls back to the operator's Storeganise instance
  • addonId   : your Add-on's unique ID for that installation. Use this to retrieve the operator's configuration and credentials.
// Get the event data from the request body
const {
  type, // The event type, e.g. `user.created`, `job.unit_moveIn.completed`
  data = {}, // An object of event data; contains IDs depending on the event type, e.g. userId, jobId
  apiUrl, // The base URL of Storeganise API
  addonId, // The ID of the addon which called this webhook; the addon contains the business-specific customFields/settings
} = req.body;
Your endpoint must respond with a 200   status within 30 seconds. For a full list of available events, see Webhooks.

Authentication

How Add-on authentication works
Each webhook request includes the apiUrl   and addonId   for the operator's installation. You combine the addonId   with your sgApiKey   to authenticate API requests back to Storeganise. The sgApiKey   is not a global key; it comes from the operator's custom fields, set when they installed and configured your Add-on.
Auth header format
Authorization: Addon ${addonId}|${sgApiKey}
Where sgApiKey comes from
When an operator installs your Add-on, they enter their credentials into the custom fields you defined. Fetch the Add-on record using addonId    to retrieve those fields, including the sgApiKey    for that operator.

Fetching data from the API

Why webhooks contain IDs, not full objects
Webhook payloads are intentionally lightweight. Storeganise sends only the IDs relevant to the event, and your handler fetches the full object data it needs via the API. This keeps payloads fast and gives you control over what data you retrieve.
StoreganiseApi helper pattern
Use this helper to make authenticated requests from your webhook handler:
function StoreganiseApi({ apiUrl, addonId }) {
  return function fetchSg(path, {
    method = 'GET',
    body,
  } = {}) {
    return fetch(`${apiUrl}${path}`, {
      method,
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Addon ${addonId}|${config.sgApiKey}`,
      },
      body: body && JSON.stringify(body),
    })
      .then(async response => {
        const data = await response.json().catch(() => ({}));
        if (!response.ok) {
          console.error(`Error calling ${method} ${apiUrl}${path}: ${response.status} ${response.statusText}`);
          const err = Object.assign(new Error(), data.error);
          err.status = response.status;
          throw err;
        }
        return data;
      });
  }
}
Fetching Add-on details
Fetch the Add-on record to access the operator's custom fields, including their credentials:
const fetchSg = StoreganiseApi(req.body); const addon = await fetchSg(`/v1/admin/addons/${addonId}`);
Use addon.customFields    to retrieve the credentials or configuration the operator entered during installation.
Handling a move-in event
Use the IDs from the webhook payload to fetch the full record. For example, on a move-in event:
const { unitRentalId } = data; const rental = await fetchSg(`/v1/admin/unit-rentals/${unitRentalId}?include=unit,owner,customFields`); // Now call your remote API using addon.customFields for the credentials, and rental data to sync
For guidance on making efficient API requests, see API best practices.

Tracking installations across operators

Why /v1/admin/addons won't give you a cross-account view
The GET /v1/admin/addons    endpoint lists Add-ons from the perspective of a single operator account. It is not designed for Add-on developers to discover all installations across different accounts.Instead, track installations by recording the apiUrl   and addonId    from incoming webhook requests. Together these identify a specific installation.
Using addon.dailyEvent.started as a daily ping
Subscribe to the addon.dailyEvent.started    event. This fires at 3:00 AM daily for each enabled instance of your Add-on. By logging these events you can maintain an up-to-date list of active installations and detect when an Add-on has been disabled or removed, as the daily ping will stop arriving.
Using addon.installed for new installation events
Subscribe to addon.installed    to be notified immediately when a new operator installs your Add-on.

Technical requirements

Your Add-on must meet these requirements before it can be certified for production.Required capabilities:
  • Webhook endpoint that accepts POST requests with Storeganise event data
  • OAuth flow implementation for authenticating with your service
  • Comprehensive error handling and retry logic for network failures and API errors
  • Multi-site support tested, if your Add-on applies to operators managing multiple facilities
Performance:
  • Webhook responses must complete within 30 seconds
  • Handle API rate limits appropriately and minimise the number of requests where possible
  • Implement proper error recovery for 4xx and 5xx API responses

Quality standards

Your Add-on should:
  • Work reliably for all supported use cases
  • Handle errors gracefully with clear feedback to operators
  • Follow Storeganise UI and UX patterns
  • Respond to webhooks within the timeout limit
  • Make efficient use of the Storeganise API
Your operator-facing documentation should:
  • Use clear, jargon-free language
  • Include step-by-step instructions with screenshots
  • Explain all configuration parameters
  • Provide troubleshooting guidance for common issues
  • Follow Storeganise helpdoc formatting standards

Common technical pitfalls

  • Webhook responses that exceed the 30-second timeout
  • Insufficient error handling for API failures and network errors
  • Rate limiting not properly implemented, causing excessive API requests
  • Not handling all relevant webhook events for your integration type
  • Assuming GET /v1/admin/addons   provides a cross-account view of installations

Access control conventions

If you're building an access control integration, follow these conventions for consistency across the platform.Note: {prefix}    is your Add-on name, for example pti   , bearbox   , or noke   .
Unit name override (prefix_id)
If unit.customFields.{prefix}_id    is set, it overrides unit.name    as the unit identifier synced to your remote API.
Skipping sync (prefix_id set to NONE)
If unit.customFields.{prefix}_id    is set to NONE   , synchronisation is skipped for that unit.
Overlocking status (prefix_overlocked)
Use unit.customFields.{prefix}_overlocked    (Boolean) for the overlock status of the unit.
Access codes (prefix_accessCode, prefix_pinCode)
Use unit.customFields.{prefix}_accessCode   , {prefix}_pinCode   , or another relevant name for access codes. Generate codes randomly with at least six digits.
Resync trigger (prefix_resync)
Use unit.customFields.{prefix}_resync    (Boolean) to trigger a manual resync for a specific unit.
Related articles
API FAQ
Webhooks
API best practices
Add-on: Partner guide
Add-ons: Technical reference