StrataWorx
Developers

Developer guide

StrataWorx has a REST API, signed webhooks and an MCP server for AI assistants. Use them to connect StrataWorx to your strata software, automation tools such as Zapier, Make or Power Automate, or assistants such as Claude.

Authentication

Create an API key in StrataWorx under Integrations. Keys start with ll_live_ and are shown once, so store them somewhere safe. Send the key as a bearer token on every request:

Authorization: Bearer ll_live_YOUR_KEY
StatusMeaning
401Missing, invalid or revoked API key
403The key doesn't have the scope this endpoint needs
402The firm's subscription or trial is inactive
429Over the limit of 120 requests per minute per key
404The email or work order wasn't found in your account
400Invalid input. The message says what to fix.

Errors come back as { "error": { "message": "..." } }. Keys only ever see their own firm's data.

REST API

All endpoints are under https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1, accept and return JSON, and support limit and offset on lists.

GET

/api/v1/messages

read scope

List emails, newest first.

Query parameterDescription
statusopen (awaiting a reply), sent, dismissed or triage_failed
categoryrepairs, levies, bylaws, records, bookings, insurance or other
urgencyurgent, soon or routine
schemeStrata plan number, e.g. SP 70412. Returns an empty list if the scheme isn't found.
sinceISO 8601 date or time. Only emails received on or after it.
limit1 to 100, default 25
offsetNumber of rows to skip, default 0

Example

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/messages?status=open&urgency=urgent&limit=10" \
  -H "Authorization: Bearer ll_live_YOUR_KEY"

Response

{ "data": [ { "id", "from_email", "subject", "category", "urgency", "summary", "request", "status", "received_at", "scheme", "lot" } ] }
GET

/api/v1/messages/{id}

read scope

Read one email in full, with its body, the drafted reply and any suggested work order. Returns 404 if the email doesn't exist.

Example

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/messages/MESSAGE_ID" \
  -H "Authorization: Bearer ll_live_YOUR_KEY"

Response

{ "data": { ...list fields, "body", "draft_reply", "suggested_job" } }
POST

/api/v1/messages/{id}/reply

write scope

Send a reply to the sender and mark the email as sent. Text is limited to 10,000 characters. Fails if the email has already been answered.

Request body

{ "text": "Thanks Priya, a plumber will attend today between 2 and 4pm." }

Example

curl -X POST "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/messages/MESSAGE_ID/reply" \
  -H "Authorization: Bearer ll_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Thanks Priya, a plumber will attend today between 2 and 4pm."}'

Response

{ "ok": true }
GET

/api/v1/jobs

read scope

List work orders, newest first.

Query parameterDescription
statusactive (open or in progress), open, in_progress or done
limit1 to 100, default 25
offsetNumber of rows to skip, default 0

Example

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/jobs?status=active" \
  -H "Authorization: Bearer ll_live_YOUR_KEY"

Response

{ "data": [ { "id", "title", "details", "status", "due_date", "scheme", "lot", "trade": { "name", "trade" } | null, "message_id", "created_at", "completed_at", "work_order_sent_at" } ] }
POST

/api/v1/jobs

write scope

Create a work order. Only title is required. Creating a work order doesn't contact anyone. due_date must be YYYY-MM-DD, and message_id must be an email in your account.

Request body

{ "title": "Replace foyer light", "details": "...", "scheme": "SP 70412", "lot": "3", "due_date": "2026-11-30", "message_id": "..." }

Example

curl -X POST "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/jobs" \
  -H "Authorization: Bearer ll_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Replace foyer light","scheme":"SP 70412","due_date":"2026-11-30"}'

Response

{ "data": { ...job } }
PATCH

/api/v1/jobs/{id}

write scope

Change a work order's status. Setting done records the completion time.

Request body

{ "status": "open" | "in_progress" | "done" }

Example

curl -X PATCH "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer ll_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"done"}'

Response

{ "data": { ...job } }
GET

/api/v1/lots

read scope

Look up lots with their owner and tenant details.

Query parameterDescription
schemeStrata plan number, e.g. SP 70412
emailOwner or tenant email address
limit1 to 100, default 25
offsetNumber of rows to skip, default 0

Example

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/lots?scheme=SP%2070412" \
  -H "Authorization: Bearer ll_live_YOUR_KEY"

Response

{ "data": [ { "scheme", "lot_number", "unit", "owner_name", "owner_email", "tenant_name", "tenant_email", "unit_entitlement" } ] }
POST

/api/v1/lots

write scope

Create or update 1 to 1,000 lots in one call, matched on scheme and lot number. New schemes are created as needed. Rows without a scheme or lot_number are skipped. Your billed lot count updates to match.

Request body

{ "lots": [ { "scheme": "SP 70412", "lot_number": "3", "unit": "3", "owner_name": "...", "owner_email": "...", "tenant_name": "...", "tenant_email": "...", "unit_entitlement": 12 } ] }

Example

curl -X POST "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/lots" \
  -H "Authorization: Bearer ll_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"lots":[{"scheme":"SP 70412","lot_number":"3","owner_name":"Tom Becker","owner_email":"tom@example.com"}]}'

Response

{ "upserted": 1, "skipped": 0 }
GET

/api/v1/schemes

read scope

List every scheme in your account.

Example

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/schemes" \
  -H "Authorization: Bearer ll_live_YOUR_KEY"

Response

{ "data": [ { "number", "name", "address" } ] }

Webhooks

Add a webhook under Integrations with a public https URL and choose the events it receives. StrataWorx sends a POST with a JSON body for each event. You'll get a signing secret when you create it.

EventSent when
message.receivedA new email arrives and has been sorted
message.sentA reply is sent from StrataWorx, the API or an AI assistant
message.dismissedAn email is dismissed without a reply
job.createdA work order is created
job.updatedA work order's status changes
lot.updatedA lot's tenant or managing agent is changed on the strata roll

Payload

Every delivery has the same shape. id is the delivery ID, which stays the same on retries, so you can use it to skip duplicates.

{
  "id": 1842,
  "event": "job.created",
  "created_at": "2026-10-15T21:04:12.000Z",
  "data": {
    "id": "6f1c...",
    "title": "Leak from Lot 18 into Lot 14 bathroom",
    "status": "open",
    "scheme": "SP 81234",
    "lot": "14",
    ...
  }
}

Verifying the signature

Each request includes a Lotline-Event header and a Lotline-Signature header:

Lotline-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of `${t}.${body}` using your signing secret>

Compute the HMAC over the raw request body, before any JSON parsing, and compare in constant time. Reject old timestamps to stop replays.

import crypto from "node:crypto";

// secret: the signing secret shown when you created the webhook
// rawBody: the request body exactly as received, as a string
export function verifyLotline(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(
    header.split(",").map((p) => p.split("=", 2))
  );
  const t = Number(parts.t);
  if (!t || !parts.v1) return false;
  if (Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody}`)
    .digest("hex");

  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(parts.v1, "hex");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

// Example with Express:
// app.post("/lotline", express.text({ type: "application/json" }), (req, res) => {
//   if (!verifyLotline(req.body, req.get("Lotline-Signature"), process.env.LOTLINE_SECRET)) {
//     return res.sendStatus(401);
//   }
//   const event = JSON.parse(req.body);
//   res.sendStatus(200);
// });

Retries

Reply with any 2xx status within 10 seconds. Redirects are not followed. If delivery fails, StrataWorx retries after 1, 5, 30, 120 and 720 minutes, then stops.

MCP: use StrataWorx inside Claude and other AI assistants

Premium

StrataWorx runs a Model Context Protocol (MCP) server, so assistants such as Claude can search your inbox, work orders, strata roll, documents, arrears, compliance items and meetings, and act on them. It's part of the Premium plan and the free trial.

EndpointUse it when
https://main.dtu6scqlpzz7e.amplifyapp.com/api/mcpYour client can send an Authorization: Bearer header
https://main.dtu6scqlpzz7e.amplifyapp.com/api/mcp/k/{key}Your client only accepts a URL. Treat this URL like a password.

Tip: start with a read-only key. Create a separate write key once you're comfortable with how the assistant works.

Add StrataWorx to Claude

  1. In StrataWorx, open Integrations and create an API key. Copy it.
  2. In Claude, open Settings > Connectors and choose Add custom connector.
  3. Give it the name StrataWorx and paste the URL with your key in it:
    https://main.dtu6scqlpzz7e.amplifyapp.com/api/mcp/k/ll_live_YOUR_KEY
  4. Save, then turn the connector on in a new chat.
  5. Ask something like "What's urgent across my schemes today?" or "Which work orders for SP 70412 are still open?"

Claude's menu names may change over time. If you can't find them, look for connectors or integrations in Claude's settings.

Add StrataWorx to Claude Code

claude mcp add --transport http lotline https://main.dtu6scqlpzz7e.amplifyapp.com/api/mcp \
  --header "Authorization: Bearer ll_live_YOUR_KEY"

Other clients

Any client that supports MCP over Streamable HTTP can connect. StrataWorx answers POST requests with JSON responses and doesn't need a session. A 402 response means the firm isn't on Premium or its subscription is inactive.

Agent-to-agent (A2A)

StrataWorx's assistant speaks the A2A protocol (JSON-RPC, version 0.3), so other AI agents such as Microsoft Copilot, Salesforce Agentforce, SAP Joule, Google agents or your own can work with a firm's StrataWorx data. Premium only.

Agent card: https://main.dtu6scqlpzz7e.amplifyapp.com/.well-known/agent-card.json. Endpoint: https://main.dtu6scqlpzz7e.amplifyapp.com/api/a2a with Authorization: Bearer <API key>. Read-only keys can only look things up; write keys can also raise work orders and start StrataWorx's agents (whose emails still wait for approval).

curl https://main.dtu6scqlpzz7e.amplifyapp.com/api/a2a -H "Authorization: Bearer ll_live_YOUR_KEY" -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0", "id": 1, "method": "message/send",
  "params": { "message": { "role": "user", "messageId": "m1",
    "parts": [{ "kind": "text", "text": "Which work orders at SP 70412 are overdue?" }] } }
}'

The reply is a completed task with the answer as a text artifact. Send the returned contextId with your next message to continue the conversation.

Data feed for BI tools

Pull data into Power BI, Excel, Tableau, Microsoft Fabric, Databricks or BigQuery with a read key. Datasets: messages, work orders, schemes, lots, compliance, arrears, usage. Add format=csv for CSV and since=YYYY-MM-DD to limit by date (up to 50,000 rows per call).

curl "https://main.dtu6scqlpzz7e.amplifyapp.com/api/v1/feed/jobs?format=csv&since=2026-01-01" -H "Authorization: Bearer ll_live_YOUR_KEY"

Power BI: Get data › Web › Advanced. URL parts: the address above. HTTP request header: Authorization = Bearer <key>.

SCIM 2.0 provisioning

Base URL https://main.dtu6scqlpzz7e.amplifyapp.com/scim/v2, bearer token from Business systems › Identity. Supports Users (list with userName, externalId or emails.value eq filters, create, get, PUT, PATCH, DELETE) and three fixed Groups for roles: admin (StrataWorx Admins), manager (StrataWorx Managers) and viewer (StrataWorx Read-only). Setting active to false or deleting a user removes their access.

Business-system connectors

Firms connect SAP S/4HANA (maintenance notifications via API_MAINTNOTIFICATION), SAP BTP, AWS, Azure and Google Cloud (see below), Salesforce (Cases), ServiceNow (incidents or any table), Dynamics 365 / Dataverse (any table), Snowflake (nightly MERGE into VARIANT tables through the SQL API with key-pair authentication), Microsoft Teams and Slack, and any other REST API with a JSON template. Work orders created or updated in StrataWorx are sent within seconds; failures retry for up to 14 hours and are listed with each connector.

Cloud platform connectors

Events (job.created, job.updated, message.received) are published as CloudEvents 1.0 with type au.lotline.<event> to SAP BTP Event Mesh (topic <prefix>/job/created, QoS 1), SAP BTP Integration Suite (HTTPS iFlow, OAuth client credentials), AWS EventBridge (DetailType = event, Detail = record), Amazon SQS (FIFO supported), Azure Event Grid (CloudEvents or Event Grid schema), Azure Service Bus (SAS, Label = event) and Google Cloud Pub/Sub (attribute event). AWS requests use Signature V4, Google uses service-account JWTs, Azure uses SAS.

Nightly exports to Amazon S3, Azure Blob Storage / Data Lake and Google Cloud Storage write <folder>/<dataset>/<yyyy-mm-dd>.jsonl and latest.jsonl for messages, work orders, schemes, lots, compliance and arrears.

Data imports and signed push

Firms pull data from SAP (S/4HANA, Business One, ByDesign, SuccessFactors, Datasphere), Oracle Fusion, NetSuite (SuiteQL, token-based auth), Dynamics 365 (Business Central, Finance & Operations, Dataverse), Workday (RaaS), Infor, Epicor, IFS, Acumatica, Sage Intacct, Odoo, Xero, MYOB, Salesforce (SOQL), ServiceNow, Snowflake, BigQuery, files in S3 / Azure Blob / Cloud Storage, and any OData or REST API, into schemes, lots, trades, compliance, arrears, work orders or work order status.

To push instead, create an import with the source "Push from your systems" and send:

POST https://main.dtu6scqlpzz7e.amplifyapp.com/api/imports/<import id>
Content-Type: application/json
Lotline-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with the signing secret>

{"rows": [{"SupplierId": "V-1001", "Name": "Harbour Plumbing", "Email": "work orders@harbourplumbing.com.au"}]}

Up to 5,000 rows or 5 MB per request. Signatures older than 5 minutes, and repeated requests, are refused (401 / 409). The reply lists rows read, saved and skipped. A sample script is in starter-kit/push/push.mjs.

Extensions

An extension is your own service that adds buttons to emails and work orders, AI tools for the StrataWorx assistant, and event handlers. Create one under Extensions to get a client ID, client secret and signing secret.

StrataWorx → your extension

POST <your endpoint>
Lotline-Signature: t=<unix>,v1=<hex HMAC-SHA256 of "<t>.<body>">
Lotline-Request-Id: <uuid, unique; reject repeats>
Lotline-Request-Type: manifest | ping | event | action | tool

{"id": "...", "type": "action", "name": "raise_po", "org": {"id": "...", "name": "..."},
 "user": {"id": "...", "role": "manager"}, "data": {"on": "work order", "record": {...}}}

Reply to manifest with {"events": [...], "actions": [{"id", "label", "on": "message" | "work order"}], "tools": [{"name", "description", "input_schema", "kind": "read" | "action"}]}; to an action with {"message", "open_url"}; to a tool with {"content"}. Read tools run when the assistant needs them; action tools are confirmed by a person first.

Your extension → StrataWorx

POST https://main.dtu6scqlpzz7e.amplifyapp.com/api/ext/token
grant_type=client_credentials&client_id=llx_client_...&client_secret=llx_secret_...

→ {"access_token": "llx_...", "token_type": "Bearer", "expires_in": 900, "scope": "read write"}

Use the token on the REST API, MCP and A2A. It carries only the scopes the admin ticked, and pausing the extension or rotating its secret revokes it at once. A one-file starter kit with no dependencies is in starter-kit/extension.

Questions about the API? Email your account contact, or see the StrataWorx home page.