Quickstart
Everything you need to make an authenticated read from a server-side integration. Client secrets must never ship in a browser, mobile bundle or public repository.
1. Get credentials
The Huddle team creates a consumer record for your application and hands over a client_id and client_secret once. The secret is stored hashed and cannot be recovered — if it is lost, ask for a rotation.
2. Call the API
curl
# 1. Exchange credentials for a token
TOKEN=$(curl -s -X POST \
https://huddle-api.parentweb.online/api/public/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{"client_id":"'$HUDDLE_CLIENT_ID'","client_secret":"'$HUDDLE_CLIENT_SECRET'"}' \
| grep -o '"access_token":"[^"]*' | cut -d'"' -f4)
# 2. Read data
curl -s "https://huddle-api.parentweb.online/api/public/v1/<resource>?limit=25" \
-H "Authorization: Bearer $TOKEN"JavaScript (Node 18+)
const BASE = "https://huddle-api.parentweb.online";
let cached = { token: "", expiresAt: 0 };
async function getToken() {
if (cached.token && Date.now() < cached.expiresAt - 30_000) return cached.token;
const res = await fetch(`${BASE}/api/public/v1/auth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: process.env.HUDDLE_CLIENT_ID,
client_secret: process.env.HUDDLE_CLIENT_SECRET,
}),
});
if (!res.ok) throw new Error(`Auth failed: ${res.status}`);
const data = await res.json();
cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return cached.token;
}
export async function read(path, params = {}) {
const url = new URL(`${BASE}/api/public/v1/${path}`);
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, String(v)));
const res = await fetch(url, { headers: { Authorization: `Bearer ${await getToken()}` } });
if (!res.ok) {
const { error } = await res.json().catch(() => ({ error: { message: res.statusText } }));
throw new Error(`${res.status} ${error?.code}: ${error?.message}`);
}
return res.json();
}3. Query parameters
| limit | Page size, 1-100. Defaults to 25. |
|---|---|
| offset | Records to skip, for paging through results. |
| sort | Column to sort by — allowed values are listed per resource in the reference. |
| order | asc or desc. Defaults to desc. |
| <column> | Exact-match filter, for columns marked filterable on that resource. |
4. Errors
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed body, or an unsupported sort/pagination value. |
| 401 | invalid_client | client_id / client_secret did not match an active consumer. |
| 401 | unauthorized | Bearer token missing, malformed or expired — request a new token. |
| 403 | forbidden | Your credentials lack the scope for that resource. |
| 404 | not_found | Unknown resource, or no record with that id. |
| 429 | rate_limited | Rate limit hit; honour the Retry-After header. |
| 503 | not_configured | The API is not yet connected to the database. |
Full endpoint-by-endpoint details live in the API reference.
