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

limitPage size, 1-100. Defaults to 25.
offsetRecords to skip, for paging through results.
sortColumn to sort by — allowed values are listed per resource in the reference.
orderasc or desc. Defaults to desc.
<column>Exact-match filter, for columns marked filterable on that resource.

4. Errors

StatusCodeMeaning
400invalid_requestMalformed body, or an unsupported sort/pagination value.
401invalid_clientclient_id / client_secret did not match an active consumer.
401unauthorizedBearer token missing, malformed or expired — request a new token.
403forbiddenYour credentials lack the scope for that resource.
404not_foundUnknown resource, or no record with that id.
429rate_limitedRate limit hit; honour the Retry-After header.
503not_configuredThe API is not yet connected to the database.

Full endpoint-by-endpoint details live in the API reference.