Versioning and compatibility
The API version is in the path: every resource URL starts with https://api.brellium.com/v2/, and no request header selects a version. A change that a correct v2 client could not handle ships under a new path prefix instead of /v2. Brellium has not published a formal compatibility policy for v2 yet, so the rules below describe current practice.
Changes Brellium may make without notice
These changes ship under /v2, so your client must handle each one:
- New endpoints and new query parameters on existing endpoints.
- New fields on any response object, including inside
error.details. - New values for string fields that have no fixed list: audit
status, documentstatus, coding evaluationstatus,em_evaluation.uncodable_reason, theflags[]insideem_evaluationandicd_evaluation, anderror.type. Today auditstatusis one oftodo,processing,in_progress,completing,completeorerror, anderror.typeis one ofinvalid_request_error,authentication_error,not_found_error,conflict_error,rate_limit_errororapi_error. - New error codes and new
messagewording. An existingerror.typeorerror.codekeeps its meaning, whileerror.messageanderror.detailscan change (Rate limits and errors). - The order of fields in a JSON object.
Breaking changes
Each of these changes ships under a new path prefix:
- Removing or renaming a field, an endpoint or a query parameter.
- Changing a field's type or nullability.
- Changing the meaning of an existing
error.typeorerror.code, or the HTTP status an existing code returns. - Changing the meaning of an existing
statusvalue, or the pagination rules (limit,starting_after,ending_before,has_more).
Code defensively
These rules keep your client working when a change ships without notice:
- Ignore fields you do not recognize, because a strict deserializer breaks when the API adds a field.
- Expect new values in every string field. Any audit
statusother thancompletemeansscoreandflagsare not final. - Branch on
error.typeanderror.code, never onerror.message. - Treat ids as opaque strings that you compare but never parse.
- Check
objectbefore you use a successful response. Every resource has one, for exampleaudit,userorquestion_set, and every list envelope haslist. An error response has noobjectfield, onlyerror.
The requests below fetch the sample audit a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d with an access token in $BRELLIUM_ACCESS_TOKEN (Authenticate with OAuth2 client credentials). A sandbox key returns that audit. With a live key, take an audit_id from GET /v2/audits?status=complete&limit=1 instead; the response then contains protected health information (PHI).
The curl request returns the audit; read object, status, score and flags first:
curl "https://api.brellium.com/v2/audits/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d" \
--header "Authorization: Bearer $BRELLIUM_ACCESS_TOKEN"
{
"audit_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
// check this before reading anything else
"object": "audit",
// branch on this; any other value means score and flags are not final
"status": "complete",
"score": 0.6666666666666666,
"flags": ["Failed", "Missing Signature"]
/* ... the other eight keys; see Understand an audit */
}
The samples below make the same request and parse the response so that an unknown field or a new status value cannot break them:
// Keep credentials on the server; never in a browser or mobile app.
const token = process.env.BRELLIUM_ACCESS_TOKEN;
if (!token) throw new Error("BRELLIUM_ACCESS_TOKEN is not set");
const auditId = "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d";
async function main() {
const res = await fetch(`https://api.brellium.com/v2/audits/${auditId}`, {
headers: { Authorization: `Bearer ${token}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
// Only the fields this code uses are typed; everything else is ignored.
const audit = (await res.json()) as {
object: string;
status: string;
score: number | null;
flags: string[];
};
if (audit.object !== "audit") throw new Error("unexpected object");
switch (audit.status) {
case "complete":
console.log("score", audit.score, "flags", audit.flags);
break;
case "error":
console.log("audit failed; check back later");
break;
default:
// todo, processing, in_progress, completing, or a value added later
console.log("not final yet:", audit.status);
}
}
main();
import BrelliumClient from "@brellium/api-client";
const client = new BrelliumClient({ oAuth2: process.env.BRELLIUM_ACCESS_TOKEN });
const audit = await client.audits.retrieve("a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d");
if (audit.object !== "audit") throw new Error("unexpected object");
switch (audit.status) {
case "complete":
console.log("score", audit.score, "flags", audit.flags);
break;
case "error":
console.log("audit failed; check back later");
break;
default:
// todo, processing, in_progress, completing, or a value added later
console.log("not final yet:", audit.status);
}
import os
from brellium_api_client import BrelliumClient
client = BrelliumClient(o_auth2=os.environ["BRELLIUM_ACCESS_TOKEN"])
audit = client.audits.retrieve("a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d")
if audit.object != "audit":
raise ValueError("unexpected object")
if audit.status == "complete":
print("score", audit.score, "flags", audit.flags)
elif audit.status == "error":
print("audit failed; check back later")
else:
# todo, processing, in_progress, completing, or a value added later
print("not final yet:", audit.status)
# Keep credentials on the server; never in a browser or mobile app.
import os
import requests
token = os.environ["BRELLIUM_ACCESS_TOKEN"]
audit_id = "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
res = requests.get(
f"https://api.brellium.com/v2/audits/{audit_id}",
headers={"Authorization": f"Bearer {token}"},
timeout=30,
)
res.raise_for_status()
audit = res.json() # unknown fields are kept and ignored
if audit.get("object") != "audit":
raise ValueError("unexpected object")
status = audit.get("status")
if status == "complete":
print("score", audit["score"], "flags", audit["flags"])
elif status == "error":
print("audit failed; check back later")
else:
# todo, processing, in_progress, completing, or a value added later
print("not final yet:", status)
Every sample checks the HTTP status before it reads object: the TypeScript fetch and Python requests samples throw on a 401 UNAUTHORIZED, 404 NOT_FOUND or 429 RATE_LIMITED, and the SDK samples raise an error on the same statuses (Rate limits and errors).
Detect changes with the OpenAPI document
https://api.brellium.com/v2/openapi.json is the OpenAPI 3.1 document of the running API, and the API reference is built from it. Fetch it again before you regenerate a client, and diff it against your copy when a response carries a field or value your code did not expect.
v1 deprecation policy
Brellium has not yet published a deprecation policy for v1 and has committed to no dates, notice periods or support windows. Contact Brellium support before you plan a migration deadline.
v1 keeps running while you migrate. A key created in the dashboard works on v2 only (Authenticate with OAuth2 client credentials). A v1 key that shows an API v1 badge in the dashboard mints tokens for both APIs with the same client id and secret.
Next
Migrate from v1
Move an integration from the v1 API to v2, one resource at a time.
Clients and SDKs
Use an official SDK, call the API over HTTPS, generate a typed client, or start from a minimal hand-written client.