Code Examples
Working examples for common SDX API operations in Python, JavaScript (Node.js), Ruby, and cURL.
Configuration
All examples use the sandbox environment. Replace sdx_test_YOUR_KEY with your actual sandbox API key, and change the base URL to https://api.sdx.dev/v1 for production.
Create a property and building
Python
import requests
BASE_URL = "https://sandbox.api.sdx.dev/v1"
HEADERS = {
"Authorization": "Bearer sdx_test_YOUR_KEY",
"Content-Type": "application/json",
}
# Create property
property_resp = requests.post(f"{BASE_URL}/properties", headers=HEADERS, json={
"name": "100 King Street",
"address": {
"street": "100 King Street",
"city": "Melbourne",
"state": "VIC",
"postal_code": "3000",
"country": "AU",
},
"type": "office",
})
property_id = property_resp.json()["data"]["id"]
# Create building
building_resp = requests.post(
f"{BASE_URL}/properties/{property_id}/buildings",
headers=HEADERS,
json={
"name": "Main Tower",
"primary_use_type": "office",
"gfa_m2": 25000,
"year_built": 2015,
"floors": 20,
},
)
building_id = building_resp.json()["data"]["id"]
print(f"Created building: {building_id}")
JavaScript (Node.js)
const BASE_URL = "https://sandbox.api.sdx.dev/v1";
const HEADERS = {
Authorization: "Bearer sdx_test_YOUR_KEY",
"Content-Type": "application/json",
};
async function createPropertyAndBuilding() {
const propertyRes = await fetch(`${BASE_URL}/properties`, {
method: "POST",
headers: HEADERS,
body: JSON.stringify({
name: "100 King Street",
address: {
street: "100 King Street",
city: "Melbourne",
state: "VIC",
postal_code: "3000",
country: "AU",
},
type: "office",
}),
});
const { data: property } = await propertyRes.json();
const buildingRes = await fetch(
`${BASE_URL}/properties/${property.id}/buildings`,
{
method: "POST",
headers: HEADERS,
body: JSON.stringify({
name: "Main Tower",
primary_use_type: "office",
gfa_m2: 25000,
year_built: 2015,
floors: 20,
}),
}
);
const { data: building } = await buildingRes.json();
console.log(`Created building: ${building.id}`);
}
createPropertyAndBuilding();
Ruby
require "net/http"
require "json"
require "uri"
BASE_URL = "https://sandbox.api.sdx.dev/v1"
HEADERS = {
"Authorization" => "Bearer sdx_test_YOUR_KEY",
"Content-Type" => "application/json",
}
def post(path, body)
uri = URI("#{BASE_URL}#{path}")
req = Net::HTTP::Post.new(uri, HEADERS)
req.body = body.to_json
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
JSON.parse(res.body)
end
property = post("/properties", {
name: "100 King Street",
address: { street: "100 King Street", city: "Melbourne", state: "VIC", postal_code: "3000", country: "AU" },
type: "office",
})
property_id = property["data"]["id"]
building = post("/properties/#{property_id}/buildings", {
name: "Main Tower",
primary_use_type: "office",
gfa_m2: 25000,
year_built: 2015,
floors: 20,
})
puts "Created building: #{building['data']['id']}"
Submit meter readings in batch
Python
# Create meter
meter_resp = requests.post(
f"{BASE_URL}/buildings/{building_id}/meters",
headers=HEADERS,
json={"type": "electricity", "name": "Grid Supply", "unit": "kWh"},
)
meter_id = meter_resp.json()["data"]["id"]
# Submit 12 months of readings
readings = []
for month in range(1, 13):
import calendar
last_day = calendar.monthrange(2025, month)[1]
readings.append({
"start_date": f"2025-{month:02d}-01",
"end_date": f"2025-{month:02d}-{last_day:02d}",
"consumption": 80000 + (month * 2000),
})
batch_resp = requests.post(
f"{BASE_URL}/buildings/{building_id}/meters/{meter_id}/readings/batch",
headers=HEADERS,
json={"readings": readings},
)
result = batch_resp.json()["data"]
print(f"Accepted: {result['accepted']}, Rejected: {result['rejected']}")
cURL
curl -X POST "https://sandbox.api.sdx.dev/v1/buildings/bld_xyz/meters/mtr_abc/readings/batch" \
-H "Authorization: Bearer sdx_test_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"readings": [
{"start_date": "2025-01-01", "end_date": "2025-01-31", "consumption": 82000},
{"start_date": "2025-02-01", "end_date": "2025-02-28", "consumption": 84000},
{"start_date": "2025-03-01", "end_date": "2025-03-31", "consumption": 86000}
]
}'
Retrieve benchmark scores
Python
benchmarks = requests.get(
f"{BASE_URL}/buildings/{building_id}/benchmarks",
headers=HEADERS,
).json()["data"]
print(f"EUI: {benchmarks['eui_kwh_m2']} kWh/m2")
for score in benchmarks["scores"]:
if score.get("score"):
print(f"{score['standard']}: {score['score']}")
elif score.get("grade"):
print(f"{score['standard']}: {score['grade']}")
cURL
curl https://sandbox.api.sdx.dev/v1/buildings/bld_xyz/benchmarks \
-H "Authorization: Bearer sdx_test_YOUR_KEY"
Webhook signature verification
Python
import hmac
import hashlib
def verify_sdx_webhook(payload_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
payload_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
# In your webhook handler:
# is_valid = verify_sdx_webhook(request.body, request.headers["X-SDX-Signature"], WEBHOOK_SECRET)
JavaScript
const crypto = require("crypto");
function verifySdxWebhook(payloadBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(payloadBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(`sha256=${expected}`),
Buffer.from(signature)
);
}
Error handling
Python
resp = requests.post(f"{BASE_URL}/buildings/bld_xyz/meters/mtr_abc/readings",
headers=HEADERS,
json={"start_date": "2025-01-01", "end_date": "2025-01-31", "consumption": -100},
)
if resp.status_code == 422:
error = resp.json()["error"]
print(f"Validation error: {error['message']}")
for detail in error.get("details", []):
print(f" - {detail['field']}: {detail['issue']}")
elif resp.status_code == 429:
retry_after = int(resp.headers.get("Retry-After", 1))
print(f"Rate limited. Retry after {retry_after} seconds.")