Calling the API
Addresses, request and response format, errors, and examples for calling Bramble from outside the platform.
Everything the Bramble apps do, they do through HTTP APIs, and you can call the same APIs from your own scripts, servers and products.
#Addresses
Use your organisation's address. Every API lives under it:
https://<your-org>.brambleit.cloud/api/v1/... BRM-API (platform API)
https://<your-org>.brambleit.cloud/api/v2/... BRM-API (newer RMM endpoints)
https://<your-org>.brambleit.cloud/<app>/api/... an app's own API, e.g. /warden/api/overviewEach page in the API reference gives the full address of every
route. Paths with :name in them take a value there, e.g.
/api/v1/app/psa/tickets/:id → /api/v1/app/psa/tickets/1234.
#Which API to use from a script
| You want to… | Use | Sign in with |
|---|---|---|
| Work with people, groups, licences, admin settings | BRM-API /api/v1/... |
API key |
| RMM, PSA, Projects, WiKi, Forms, To Do | BRM-API /api/v1/app/..., /api/v2/app/... |
API key |
| Files (Drive) or Sites | /drive/api/v2/..., /sites/api/v2/... |
API key |
| Warden, Atlas, HR, Flows, Paper, Mail, SimpleBooks | that app's /<app>/api/... |
browser session (see below) |
The apps in the last row currently accept a signed-in browser session only. From outside the platform, the supported routes are:
- Flows: build the automation in Flows itself and trigger it from outside with a webhook. Flows' Bramble steps can call those apps for you.
- Calendar and contacts: CalDAV, CardDAV and
.icslinks (see Webhooks & integrations). - Events out of Bramble: Flows triggers on app events (new ticket, device enrolled, alert raised…) and can call your system.
#Requests
- Send and receive JSON (
Content-Type: application/json), unless the route says it takes a file upload (multipart/form-data) or returns a file. - Times are ISO 8601 (
2026-11-12T09:30:00Z) unless the route says otherwise; dates areYYYY-MM-DD. - IDs are numbers for most records; devices in RMM use a 32-character
device_idstring. - Lists usually take
limitandoffset(orpage) in the query; the reference lists the query parameters each route reads.
#Responses and errors
Successful calls return 200 (or 201 for some creates) with a JSON body.
The reference shows the fields each route returns, e.g.
200 { ticket, messages, activity }.
Errors return a JSON body with a human-readable message:
{ "message": "Ticket not found" }| Status | Meaning |
|---|---|
400 |
The request is missing something or a value isn't valid. message says what. |
401 |
Not signed in, or the session expired. |
403 |
Signed in, but not allowed: no licence for that app, a missing role or permission, an expired or revoked API key, or a turned-off account. |
404 |
Not found, or not in your organisation (Bramble never reveals other organisations' records). |
409 |
Conflicts with the current state (e.g. someone else changed it first). |
413 |
Upload too large. |
429 |
Too many requests. Wait and try again; Retry-After says how long when sent. |
5xx |
Something went wrong on Bramble's side. Safe to retry reads; check before retrying writes. |
#Examples
#curl
export BRAMBLE=https://<your-org>.brambleit.cloud
export BRAMBLE_KEY=... # Hub → Account → API keys
# Who am I, and which organisation?
curl -s -H "X-API-Key: $BRAMBLE_KEY" $BRAMBLE/api/v1/user
curl -s -H "X-API-Key: $BRAMBLE_KEY" $BRAMBLE/api/v1/tenant/info
# PSA: list tickets, then open one
curl -s -H "X-API-Key: $BRAMBLE_KEY" "$BRAMBLE/api/v1/app/psa/tickets"
curl -s -H "X-API-Key: $BRAMBLE_KEY" "$BRAMBLE/api/v1/app/psa/tickets/1234"
# PSA: raise a ticket
curl -s -X POST -H "X-API-Key: $BRAMBLE_KEY" -H "Content-Type: application/json" \
-d '{"subject":"Printer offline","body":"The 2nd floor printer is offline.","priority":"high"}' \
"$BRAMBLE/api/v1/app/psa/tickets"
# To Do: your lists
curl -s -H "X-API-Key: $BRAMBLE_KEY" "$BRAMBLE/api/v1/app/todo/lists"#Node.js
const BASE = 'https://<your-org>.brambleit.cloud';
const KEY = process.env.BRAMBLE_KEY;
async function bramble(method, path, body) {
const res = await fetch(BASE + path, {
method,
headers: { 'X-API-Key': KEY, ...(body ? { 'Content-Type': 'application/json' } : {}) },
body: body ? JSON.stringify(body) : undefined,
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(`${res.status}: ${data.message || res.statusText}`);
return data;
}
const { tickets } = await bramble('GET', '/api/v1/app/psa/tickets');
console.log(tickets.length, 'tickets');#Python
import os, requests
BASE = "https://<your-org>.brambleit.cloud"
s = requests.Session()
s.headers["X-API-Key"] = os.environ["BRAMBLE_KEY"]
r = s.get(f"{BASE}/api/v1/tenant/users")
r.raise_for_status()
for u in r.json().get("users", []):
print(u["email"])#Good practice
- Keep keys out of source code: environment variables or a secret store.
- Use a dedicated Bramble user for each integration, with only the licences and roles it needs, so you can see its changes in the audit log and turn it off on its own.
- Every change made with your key is recorded in the organisation's audit log under your name.
- Don't poll faster than you need. Use Flows triggers for "tell me when X happens" instead of polling.
#The full list of routes
The API reference is generated from the source code of every
service, so it lists every route that exists, including the ones without
hand-written descriptions. A machine-readable copy is at
routes.json.
Was this page helpful?
Thanks for your feedback.