NAV
javascript shell

Introduction

ListSMRT will be building an API integration with client’s existing systems, enabling them to use output generated from ListSMRT to their system. With this API, clients can:

General Flow

  1. The client will need to add a new button into their CMS that is basically just a URL (https://api-app.listsmrt.com/api/v1/client/authorize/?api_key=meowmeowmeow ) pointing to Listsmrt based on our provided format.

  2. When the user clicks the URL, it will redirect them to Listsmrt platform.

  3. Users will follow the usual flow (log in if they haven't) and generate the content.

  4. The webhook is then triggered and sends the data to the client system.

  5. The webhook will be triggered when the user manually clicks the button "Send data to CRM" to confirm.

  6. Developers on the client side will need to implement their solution for receiving our webhook data and storing it into their system.

Preparation Steps

To seamlessly integrate with ListSMRT's Generation Page and automate the property listing generation process, follow these steps:

Generate API Key

Please contact admin to generate an API Key. This key will serve as the authentication token for accessing ListSMRT's API.

API Key: DjEzRb8PkMvFY5YXgQhaW6dTySKcV5tmpepuV630Kn4xe5TRfFxNYkv0HnFkh4hH

Whitelist Domains

The user admin must whitelist the domain(s) that will be making API requests to ListSMRT (Please contact admin to whitelist the domain(s)). This ensures secure communication between the client's CMS system and ListSMRT.

Domain: https://example.com

Configure Webhook

The user admin should set up a webhook URL and a secret key. This URL will be used to receive data generated by ListSMRT (Please contact admin to set up a webhook URL and a secret key). The secret key adds an extra layer of security to the webhook communication.

Webhook URL: https://api-example.com/property-notification-handler

Secret Key: Ba2R1DUHZy7avEvM7ty2zLYX

Integration Steps

Follow these steps to seamlessly integrate ListSMRT's Generation Page:

Implement Button Element HTML

The client needs to implement an HTML button element that redirects to the authorization page:

https://api-app.listsmrt.com/api/v1/client/authorize/?api_key=DjEzRb8PkMvFY5YXgQhaW6dTySKcV5tmpepuV630Kn4xe5TRfFxNYkv0HnFkh4hH&address=SydneyNSW,Australia&type=House&bed=2&bath=1&garage=1&parking=1&metadata=propertyId:1,userId:1

The following are the parameters that the user needs to include in the URL's details

Params Description Value
api_key Required. An API key generated by the user admin Type: String
highlight Optional. A brief highlight or title for the property listing Type: String
campaign_type Optional. Specifies the type of campaign for the property Type: Enum
Options: Residential Sale, Residential Lease, Commercial Sale, Commercial Lease
address Optional. The location address of the property Type: String
type Optional. The type of property Type: Enum
Options: Property Types
Example: Apartment/Unit
land_size Optional. The size of the land associated with the property Type: String
strata_rates Optional. The strata fees or rates associated with the property Type: String
land_rates Optional. The rates or taxes for the land Type: String
water_rates Optional. The water usage rates or fees for the property Type: String
weekly_rent Optional. The weekly rent amount for the property Type: String
bed Optional. The number of bedrooms in the property Type: Number 0 - 10
Default: 0
bath Optional. The number of bathrooms in the property Type: Number 0 - 10
Default: 0
garage Optional. The number of garage spaces available Type: Number 0 - 10
Default: 0
parking Optional. The number of parking spaces available Type: Number 0 - 10
Default: 0
land_status Optional. The status of the land Type: Enum
Options: New Construction, Established Property
feature_details_id Optional. Specific feature details associated with the property Type: String
Options: Feature List
*Feature detail IDs separated by commas
Example: 1,3,5
perfect_for Optional. The target audience or groups that the property Type: String
Options: First Home Buyers, Singles, Upsizers, Young Couples, Downsizers, Families, Investors, Retirees
*Perfect for separated by commas
Example: Singles,Upsizers
tone_of_voice Optional. Specifies the preferred tone of voice for the property description Type: Enum
Default: Neutral
Options: Formal, Luxurious, Professional, Neutral, Friendly, Calm, Excited, Informal, Jovial
language_input Optional. The language used as input Type: Enum
Default: en
Options: en, es, fr, de, zh, zhtw, ja, ko, ru, ar, it, nl, pt, sv, da, no, fi, he, hi, id, tr, el, th, pl, hu, ro
language_output Optional. The desired language for the output Type: Enum
Default: en
Options: en, es, fr, de, zh, zhtw, ja, ko, ru, ar, it, nl, pt, sv, da, no, fi, he, hi, id, tr, el, th, pl, hu, ro
metadata Optional. The additional parameters from user requirements Type: String
Format: key1:value1,key2:value2

Property Types

The specific property types can vary depending on the campaign type. In this documentation, we will outline the property types associated with two common campaign types: Residential Sale/Lease and Commercial Sale/Lease.

1. Residential Property Types:

Property Type
House
Apartment/Unit
Townhouse
Villa
Land
Retirement Living
Acreage
Semi/Duplex
Semi
Duplex

2. Commercial Property Types:

Property Type
Offices
Serviced Offices
Shop & Retail
Factory
Warehouse
Industrial
Land
Development Site
Hotel
Motel
Leisure
Medical
Consulting
Commercial Farming & Rural
Showroom & large Format Retail
Other

Features

Below is a list of features available in the ListSMRT system:

Feature Detail ID Feature Name
1 Ensuite
2 Dishwasher
3 Study
4 Built in wardrobes
5 Alarm system
6 Broadband
7 Floorboards
8 Gym
9 Rumpus room
10 Workshop
11 Indoor spa
12 Fireplace
13 Intercom
14 Pay TV
15 Air conditioning
16 Solar panels
17 Heating
18 High energy efficiency
19 Water tank
20 Solar hot water
21 Gas
22 Swimming pool
23 Garage
24 Balcony
25 Outdoor area
26 Undercover parking
27 Shed
28 Fully fenced
29 Outdoor spa
30 Pet friendly
31 Courtyard

Generate Content

Trigger Notification

Example of how the HTTP notification will be sent from ListSMRT side:

// This example is built with Node.js

const axios = require('axios');

const url = 'https://api-example.com/property-notification-handler/';
const headers = {
  'User-Agent': 'ListSMRT',
  'ListSMRT-Signature': 't=1693446511,v1=15af584462edbb5052d302600bb2f832be45f608a5479a9209e324e4f7458233',
  'Content-type': 'application/json',
};

const data = {
  "created": "2023-09-25T06:38:50.180Z",
  "type": "property.generate-content",
  "data": {
    "bed": 3,
    "bath": 4,
    "type": "Townhouse",
    "garage": 2,
    "address": "111 Harrington Street",
    "parking": 3,
    "highlight": "Strategic location",
    "land_size": "",
    "land_rates": "",
    "land_status": "",
    "perfect_for": null,
    "tenure_type": "",
    "water_rates": "",
    "weekly_rent": "",
    "strata_rates": "",
    "the_location": true,
    "campaign_type": "Sale",
    "land_area_max": "",
    "land_area_min": "",
    "tone_of_voice": "Neutral",
    "floor_area_max": "",
    "floor_area_min": "",
    "language_input": "en",
    "language_output": "en",
    "feature_details_id": "1,7,15,19",
    "nabers_energy_rating": "",
    "metadata": {
      "requestId": "mUvZ3voNOQwzcmuJjnR2GXccd8looWlo",
      "secretKey": "IvXfgldQYokWHcgM7b9E664NeemPAylj"
    },
  },
  "result": "Check out this spacious 3 bed, 4 bath townhouse with a strategic location! Don't miss your chance to own it. #ForSale #Townhouse"
}

axios.post(url, data, { headers })
  .then((response) => {
    console.log('Response:', response.data);
  })
  .catch((error) => {
    console.error('Error:', error);
  });

curl --request POST \
  --url https://api-example.com/property-notification-handler \
  --header 'Content-Type: application/json' \
  --header 'ListSMRT-Signature: t=1693446511,v1=15af584462edbb5052d302600bb2f832be45f608a5479a9209e324e4f7458233' \
  --header 'User-Agent: ListSMRT' \
  --data '{
    "created": "2023-09-25T06:38:50.180Z",
    "type": "property.generate-content",
    "data": {
      "bed": 3,
      "bath": 4,
      "type": "Townhouse",
      "garage": 2,
      "address": "111 Harrington Street",
      "parking": 3,
      "highlight": "Strategic location",
      "land_size": "",
      "land_rates": "",
      "land_status": "",
      "perfect_for": null,
      "tenure_type": "",
      "water_rates": "",
      "weekly_rent": "",
      "strata_rates": "",
      "campaign_type": "Sale",
      "land_area_max": "",
      "land_area_min": "",
      "tone_of_voice": "Neutral",
      "floor_area_max": "",
      "floor_area_min": "",
      "language_input": "en",
      "language_output": "en",
      "feature_details_id": "1,7,15,19",
      "nabers_energy_rating": "",
      "metadata": {
        "requestId": "mUvZ3voNOQwzcmuJjnR2GXccd8looWlo",
        "secretKey": "IvXfgldQYokWHcgM7b9E664NeemPAylj"
      },
    },
    "result": "Check out this spacious 3 bed, 4 bath townhouse with a strategic location! Don'\''t miss your chance to own it. #ForSale #Townhouse"
  }'

Webhook

To ensure a secure and reliable data exchange between client's CMS system and ListSMRT, follow these guidelines for setting up and managing the webhook integration:

URL and Security

Signature

Validate Signature

Example of how to validate signature:

// This example is built with Node.js

const crypto = require("crypto");
const express = require("express");
const bodyParser = require("body-parser");

const app = express();

// Middleware to parse JSON payloads
app.use(bodyParser.json());

// Your endpoint's signing secret
const API_KEY =
  "DjEzRb8PkMvFY5YXgQhaW6dTySKcV5tmpepuV630Kn4xe5TRfFxNYkv0HnFkh4hH";

// Your custom middleware to verify the signature
app.use((req, res, next) => {
  const header = req.get("ListSMRT-Signature");
  const elements = header.split(",");

  let timestamp;
  let receivedSignature;

  // Step 1: Extract timestamp and signatures from the header
  for (const element of elements) {
    const [prefix, value] = element.split("=");
    if (prefix === "t") {
      timestamp = value;
    }
    if (prefix === "v1") {
      receivedSignature = value;
    }
  }

  // Step 2: Prepare the signed_payload string
  const payload = JSON.stringify(req.body);
  const signedPayload = `${timestamp}.${payload}`;

  // Step 3: Determine the expected signature
  const hmac = crypto.createHmac("sha256", API_KEY);
  const expectedSignature = hmac.update(signedPayload).digest("hex");

  // Step 4: Compare the signatures
  let isValid = false;
  if (
    crypto.timingSafeEqual(
      Buffer.from(expectedSignature),
      Buffer.from(receivedSignature)
    )
  ) {
    const currentTimestamp = Math.floor(Date.now() / 1000);
    if (Math.abs(currentTimestamp - timestamp) < 300) {
      // 5 minutes tolerance
      isValid = true;
    }
  }

  if (isValid) {
    next();
  } else {
    res.status(401).send("Invalid signature");
  }
});

app.post("/property-notification-handler", (req, res) => {
  res.send("Payload verified");
});

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});

Example of how to validate signature from ListSMRT:

Step 1: Extract the timestamp and signatures from the header

Step 2: Prepare the signed_payload string

Step 3: Determine the expected signature

Step 4: Compare the signatures