Overview
Limble CMMS is a cloud maintenance system for work orders, preventive maintenance (PMs), work requests, assets, parts and purchasing. This connector lets the broker open a work order when an alarm fires, feed run hours, cycle counts and sensor values into asset fields that drive meter-based and threshold PMs, and log machine events on the asset, so maintenance sees what the plant sees without manual entry. The template has two connectors:- LimbleCmmsApi (
LimbleCmmsRestApi.lot), a client connector onhttps://api.limblecmms.comwith 31 events: 13 writes and 18 reads. It has noDELETEevents. - LimbleCmmsWebhookReceiver (
cmms_limble-cmms_webhook.lot), an optional server connector on port9010that receives Limble webhooks and publishes them on MQTT.
Limble serves a machine-readable OpenAPI 3.1 spec without authentication at
https://api.limblecmms.com/openapi.json, and publishes the same reference as Postman docs. The events were picked by hand from it (the API has more than 200 operations), and every method and path was checked against it.Events
Replies arrive on the same topic with
/response appended.
Prerequisites
- A Limble account and API keys. A Super Administrator creates them under Settings > Configuration > API Settings > Generate API Keys. The client secret is shown only once.
- The API host of your account’s region. The connector uses the default host; for other regions change
BASE_ADDRESS:
- Outbound HTTPS from the broker to that host.
- For webhooks only: a public HTTPS URL that forwards to the broker’s port
9010.
Authentication
Limble uses HTTP Basic authentication with the API Client ID and Client Secret. Every event sendsAuthorization: Basic {value.json.basic_auth}, so each payload carries the base64 string in basic_auth:
GetMe (GET /v2/me) returns customerName and customerPlan. Use it to check the keys.
Answers seen from the real API without valid keys: no Authorization header returns 401 {"error":401,"success":false,"msg":"No Credentials Provided"}; wrong keys return 403 {"error":403,"success":false,"msg":"Invalid credentials."}.
Payload conventions
basic_auth: base64 ofclient_id:client_secret.id: the numeric Limble ID in the path:taskID,assetID,valueID(an asset field value, not the asset),webhookIDorworkRequestSubmissionID.query: the whole query string for list events, already URL-encoded, or""for none. For examplestatus=0&type=2,4&locations=205&limit=100&page=1for open work orders.body: the JSON request body, sent unchanged onPOST,PATCHandPUTevents.
201 with the new ID (for example {"taskID": 8261}); PATCH and PUT answer an empty 200.
Task types are 1 PM, 2 unplanned work order, 4 planned work order and 6 work request. The status filter on ListTasks is 0 (incomplete) or 1 (complete); custom statuses such as “In Progress” filter with statusIDs.
Create a work order from an alarm (priority must be one of the priorityLevel values from ListPriorities):
assignment and assignmentType):
Meter readings
Limble keeps meters as asset fields (Number fields such as “Hours Ran”). PMs set to “Every X number of units” or to a threshold on that field create tasks when a new value arrives. To push a reading:- Find the field’s
valueIDwithListAssetFields(query:assets=<assetID>). If the asset does not have the field yet, attach it withAttachAssetField. - Write the value with
UpdateAssetFieldValue, using thevalueIDasid. The value must match the field type (a number for a Number field). Each write adds an entry to the field history (ListAssetFieldHistory).
BatchUpdateAssetFields (Text, Date, Number and Currency fields only, 20 calls per hour). It returns {"success": false, "updates": [...]} with a reason per row if any row fails, so check the body as well as the HTTP status.
Webhook receiver
Deploycmms_limble-cmms_webhook.lot only if you want Limble to push changes to the broker. It opens HTTP port 9010.
Each webhook in Limble has one type (
asset, assetField, location, part, po, poItem, task or instruction). Register one per type with CreateWebhook (or in Settings > Configuration > API Settings), using the public URL of the matching path:
{"taskID": 8203, "status": "COMPLETE", "category": "task", "user": "..."}. Read the full object back with ListTasks (query: tasks=8203) or the matching list event. Limble needs at least one active API key for webhooks to work. Your endpoint must answer within 10 seconds; Limble retries after 10 minutes, 1, 2 and 4 hours and then disables the webhook. Send UpdateWebhook with {"enabled": 1} to turn it back on.
Connector
Example actions
These actions check the keys every hour, open a work order when a compressor alarm is raised, push run hours into a meter field, log machine state changes on the asset, and poll open work orders.Notes
- The catalog hint
PATCH assets/{id}/fieldsdoes not exist in the Limble API. Meter values are written per field value withPATCH /v2/assets/fields/{valueID};PUT /v2/assets/{assetID}/fieldsonly attaches a field to an asset. UpdateTaskcannot setstatusIDto1(Open) or2(Complete); usestatus0/1for that. Itspriorityaccepts0to6(6is “On Hold”).- Limble’s reference also lists
name,locationID,due,typeandtemplateIDas query parameters ofPOST /v2/tasks. Its description and example send them in a JSON body, which is what the connector does. - Pagination uses
limit+page(the reply hasNext-Page/Last-Pageheaders) ororderBy+cursor, never both. Alimitabove the endpoint maximum returns422. Limble plans to deprecate cursor paging on tasks and assets. - Rate limits per account: GET 4000 per hour (360 per minute), PATCH 2000 per hour, POST and PUT 1000 per hour, batch requests 20 per hour. Every reply carries
X-RateLimit-*headers; over the limit you get429. Poll lists every few minutes, not per message. api.limblecmms.comsits behind Cloudflare, which rejects some client signatures (the Pythonurllibdefault user agent gets403 error code: 1010). Requests with no user agent, or a normal one, pass.- Writes start Limble’s own follow-ups: assignment notifications, meter and threshold PMs, workflow automations and webhooks.
- Errors come back on the response topic as
{"error": <code>, "success": false, "msg": "..."}:400validation,401/403auth,404unknown ID,409conflict,422limit too high,429rate limit.
Not covered
Deletes, images and files, creating assets, locations, parts, vendors, users, roles and teams, task instructions and invoices, purchase orders, bills, budgets and general ledgers, suggested field definitions and dropdown options, regions, tags, units of measure, and user capacity. All are in the Limble API and can be added to a fork.Status
Technical preview, blocked. The template passes 369 of 369 smoke checks: static checks of both connectors against Limble’s OpenAPI spec and Postman docs, every event against a local mock of the Limble API v2, negative controls, and calls to the real Limble hosts without valid keys. The live/openapi.json lists every packaged method and path, the regional hosts answer, and every packaged call with fake keys was refused at the auth check (403 Invalid credentials.). Limble checks keys before it connectors a request, so those calls cannot prove a path exists on their own. No call has run yet with real Limble API keys.
To finish testing, use a Limble account (ideally a test location) with API keys: set LIMBLE_CLIENT_ID and LIMBLE_CLIENT_SECRET (or LIMBLE_BASIC_AUTH), LIMBLE_HOST for a non-default region, LIMBLE_TEST_LOCATION, and optionally LIMBLE_TEST_USER and LIMBLE_TEST_VALUE_ID, then run LIMBLE_ALLOW_WRITE=1 python3 smoke_limble_cmms.py. It reads every list, creates a work order called “Coreflux smoke test (safe to delete)”, comments on it, reads it back, closes it, and writes one asset field value. Then deploy the connector on a broker and do an MQTT round trip.

