Aurabox REST API
Aurabox REST API
What This Skill Does
Generates correct, working client code for the Aurabox Cloud REST API. Knows the full API surface -- patients, cases, studies -- including authentication, pagination, and error handling. Produces idiomatic code in Python, TypeScript/JavaScript, PHP, and curl.
Prerequisites
- An Aurabox account with API access enabled
- An API key (generated from the Aurabox dashboard under your team settings)
- Familiarity with REST APIs
Quick Reference
Base URL
https://au.aurabox.cloud
Authentication
All requests require a Bearer token in the Authorization header:
Authorization: Bearer {YOUR_AUTH_KEY}
Content-Type: application/json
Accept: application/json
API keys are generated in the Aurabox web interface. They are scoped to a team realm.
Security: API keys are sensitive. Never commit them to source control. Use environment variables or a secrets manager.
OpenAPI / Postman
Machine-readable specs are available:
- OpenAPI:
https://au.aurabox.app/docs/openapi.yaml - Postman collection:
https://au.aurabox.app/docs/collection.json
API Surface
Patients
Full CRUD for patient records within the authenticated team realm.
Data Model
{
"id": "003fb6c7-a399-46de-8199-ac51e031bd10",
"given_names": "Jessica",
"family_name": "Jones",
"date_of_birth": "1985-06-15",
"sex": "female",
"address": {
"street": "123 Main Street",
"city": "Sydney",
"region": "NSW",
"postcode": "2000",
"country": "au"
},
"status": "active",
"archived": false,
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/patients |
List patients (paginated, searchable, sortable) |
POST |
/api/v1/patients |
Create a patient |
GET |
/api/v1/patients/{id} |
Retrieve a patient |
PUT |
/api/v1/patients/{id} |
Update a patient |
DELETE |
/api/v1/patients/{id} |
Delete a patient |
List Parameters
| Parameter | Type | Values |
|---|---|---|
per_page |
integer | 1-100 |
search |
string | Max 255 chars |
sort |
string | name, created_at, updated_at, date_of_birth |
direction |
string | asc, desc |
archived |
boolean | true, false |
Create/Update Fields
| Field | Type | Required (create) | Notes |
|---|---|---|---|
given_names |
string | Yes | Max 255 chars |
family_name |
string | Yes | Max 255 chars |
date_of_birth |
string | Yes | Date format, must be before today |
sex |
string | Yes | male, female, other, unknown |
address |
object | No | Contains street, city, region, postcode (max 20), country (max 2, ISO) |
Cases (De-identified Patients)
Cases are patients whose identity has been removed. Only a label and non-identifying metadata are stored.
Data Model
{
"id": "003fb6c7-a399-46de-8199-ac51e031bd10",
"label": "CASE-00142",
"status": "deidentified",
"archived": false,
"created_at": "2025-01-15T10:30:00.000000Z",
"updated_at": "2025-01-15T10:30:00.000000Z"
}
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/cases |
List cases (paginated, searchable, sortable) |
POST |
/api/v1/cases |
Create a case |
GET |
/api/v1/cases/{patient_id} |
Show a case |
PUT |
/api/v1/cases/{patient_id} |
Update a case |
DELETE |
/api/v1/cases/{patient_id} |
Delete a case |
List Parameters
| Parameter | Type | Values |
|---|---|---|
per_page |
integer | 1-100 |
search |
string | Max 255 chars (searches label) |
sort |
string | label, created_at, updated_at, date_of_birth |
direction |
string | asc, desc |
archived |
boolean | true, false |
Create/Update Fields
| Field | Type | Required (create) | Notes |
|---|---|---|---|
label |
string | Yes | Max 255 chars |
sex |
string | No | male, female, other, unknown |
date_of_birth |
string | No | Date format, must be before today |
Studies
Studies are nested under patients. Each study represents a medical imaging study (e.g., a CT scan, MRI, X-ray).
Endpoints
| Method | Path | Description |
|---|---|---|
GET |
/api/v1/patients/{patient_id}/studies |
List studies for a patient |
POST |
/api/v1/patients/{patient_id}/studies |
Create a study |
GET |
/api/v1/patients/{patient_id}/studies/{id} |
Retrieve a study |
PUT |
/api/v1/patients/{patient_id}/studies/{id} |
Update a study |
DELETE |
/api/v1/patients/{patient_id}/studies/{id} |
Delete a study |
Pagination
All list endpoints return paginated responses using Laravel-style pagination:
{
"data": [ ... ],
"links": {
"first": "https://au.aurabox.cloud/api/v1/patients?page=1",
"last": "https://au.aurabox.cloud/api/v1/patients?page=5",
"prev": null,
"next": "https://au.aurabox.cloud/api/v1/patients?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 5,
"per_page": 25,
"to": 25,
"total": 112
}
}
To paginate, follow the links.next URL or increment the page query parameter.
Code Examples
Python Client
import requests
import os
BASE_URL = "https://au.aurabox.cloud"
class AuraboxClient:
"""Client for the Aurabox REST API."""
def __init__(self, api_key: str):
self.base_url = BASE_URL
self.session = requests.Session()
self.session.headers.update({
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
})
def _request(self, method: str, path: str, **kwargs) -> dict:
url = f"{self.base_url}{path}"
response = self.session.request(method, url, **kwargs)
response.raise_for_status()
if response.status_code == 204:
return {}
return response.json()
# --- Patients ---
def list_patients(self, search: str = None, per_page: int = 25,
sort: str = "created_at", direction: str = "desc",
archived: bool = False) -> dict:
params = {"per_page": per_page, "sort": sort,
"direction": direction, "archived": archived}
if search:
params["search"] = search
return self._request("GET", "/api/v1/patients", params=params)
def get_patient(self, patient_id: str) -> dict:
return self._request("GET", f"/api/v1/patients/{patient_id}")
def create_patient(self, given_names: str, family_name: str,
date_of_birth: str, sex: str,
address: dict = None) -> dict:
body = {
"given_names": given_names,
"family_name": family_name,
"date_of_birth": date_of_birth,
"sex": sex,
}
if address:
body["address"] = address
return self._request("POST", "/api/v1/patients", json=body)
def update_patient(self, patient_id: str, **fields) -> dict:
return self._request("PUT", f"/api/v1/patients/{patient_id}", json=fields)
def delete_patient(self, patient_id: str) -> dict:
return self._request("DELETE", f"/api/v1/patients/{patient_id}")
# --- Cases (de-identified patients) ---
def list_cases(self, search: str = None, per_page: int = 25,
sort: str = "created_at", direction: str = "desc",
archived: bool = False) -> dict:
params = {"per_page": per_page, "sort": sort,
"direction": direction, "archived": archived}
if search:
params["search"] = search
return self._request("GET", "/api/v1/cases", params=params)
def get_case(self, case_id: str) -> dict:
return self._request("GET", f"/api/v1/cases/{case_id}")
def create_case(self, label: str, sex: str = None,
date_of_birth: str = None) -> dict:
body = {"label": label}
if sex:
body["sex"] = sex
if date_of_birth:
body["date_of_birth"] = date_of_birth
return self._request("POST", "/api/v1/cases", json=body)
def update_case(self, case_id: str, **fields) -> dict:
return self._request("PUT", f"/api/v1/cases/{case_id}", json=fields)
def delete_case(self, case_id: str) -> dict:
return self._request("DELETE", f"/api/v1/cases/{case_id}")
# --- Studies (nested under patients) ---
def list_studies(self, patient_id: str) -> dict:
return self._request("GET", f"/api/v1/patients/{patient_id}/studies")
def get_study(self, patient_id: str, study_id: str) -> dict:
return self._request("GET",
f"/api/v1/patients/{patient_id}/studies/{study_id}")
def create_study(self, patient_id: str, **fields) -> dict:
return self._request("POST",
f"/api/v1/patients/{patient_id}/studies", json=fields)
def update_study(self, patient_id: str, study_id: str, **fields) -> dict:
return self._request("PUT",
f"/api/v1/patients/{patient_id}/studies/{study_id}", json=fields)
def delete_study(self, patient_id: str, study_id: str) -> dict:
return self._request("DELETE",
f"/api/v1/patients/{patient_id}/studies/{study_id}")
# --- Pagination helper ---
def paginate(self, method, *args, **kwargs):
"""Iterate through all pages of a paginated endpoint."""
response = method(*args, **kwargs)
while True:
yield from response.get("data", [])
next_url = response.get("links", {}).get("next")
if not next_url:
break
response = self.session.get(next_url).json()
# Usage
client = AuraboxClient(api_key=os.environ["AURABOX_API_KEY"])
patients = client.list_patients(search="Jones")
TypeScript Client
const AURABOX_BASE_URL = "https://au.aurabox.cloud";
class AuraboxClient {
private baseUrl: string;
private headers: Record<string, string>;
constructor(apiKey: string) {
this.baseUrl = AURABOX_BASE_URL;
this.headers = {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
Accept: "application/json",
};
}
private async request<T>(
method: string,
path: string,
options?: { body?: unknown; params?: Record<string, unknown> },
): Promise<T> {
let url = `${this.baseUrl}${path}`;
if (options?.params) {
const searchParams = new URLSearchParams();
for (const [key, value] of Object.entries(options.params)) {
if (value !== undefined && value !== null) {
searchParams.set(key, String(value));
}
}
const qs = searchParams.toString();
if (qs) url += `?${qs}`;
}
const response = await fetch(url, {
method,
headers: this.headers,
body: options?.body ? JSON.stringify(options.body) : undefined,
});
if (!response.ok) {
throw new Error(`Aurabox API error: ${response.status} ${response.statusText}`);
}
if (response.status === 204) return {} as T;
return response.json();
}
// Patients
listPatients(params?: ListParams) {
return this.request<PaginatedResponse<Patient>>("GET", "/api/v1/patients", { params });
}
getPatient(id: string) {
return this.request<{ data: Patient }>("GET", `/api/v1/patients/${id}`);
}
createPatient(patient: CreatePatient) {
return this.request<{ data: Patient }>("POST", "/api/v1/patients", { body: patient });
}
updatePatient(id: string, fields: Partial<CreatePatient>) {
return this.request<{ data: Patient }>("PUT", `/api/v1/patients/${id}`, { body: fields });
}
deletePatient(id: string) {
return this.request<void>("DELETE", `/api/v1/patients/${id}`);
}
// Cases
listCases(params?: ListParams) {
return this.request<PaginatedResponse<Case>>("GET", "/api/v1/cases", { params });
}
getCase(id: string) {
return this.request<{ data: Case }>("GET", `/api/v1/cases/${id}`);
}
createCase(caseData: CreateCase) {
return this.request<{ data: Case }>("POST", "/api/v1/cases", { body: caseData });
}
// Studies
listStudies(patientId: string) {
return this.request<PaginatedResponse<Study>>("GET",
`/api/v1/patients/${patientId}/studies`);
}
getStudy(patientId: string, studyId: string) {
return this.request<{ data: Study }>("GET",
`/api/v1/patients/${patientId}/studies/${studyId}`);
}
}
// Types
interface Patient {
id: string;
given_names: string;
family_name: string;
date_of_birth: string;
sex: "male" | "female" | "other" | "unknown";
address?: Address;
status: string;
archived: boolean;
created_at: string;
updated_at: string;
}
interface Case {
id: string;
label: string;
status: "deidentified";
archived: boolean;
created_at: string;
updated_at: string;
}
interface Study {
id: string;
[key: string]: unknown; // Study fields vary
}
interface Address {
street?: string;
city?: string;
region?: string;
postcode?: string;
country?: string;
}
interface CreatePatient {
given_names: string;
family_name: string;
date_of_birth: string;
sex: "male" | "female" | "other" | "unknown";
address?: Address;
}
interface CreateCase {
label: string;
sex?: "male" | "female" | "other" | "unknown";
date_of_birth?: string;
}
interface ListParams {
per_page?: number;
search?: string;
sort?: string;
direction?: "asc" | "desc";
archived?: boolean;
}
interface PaginatedResponse<T> {
data: T[];
links: { first: string; last: string; prev: string | null; next: string | null };
meta: { current_page: number; from: number; last_page: number; per_page: number; to: number; total: number };
}
curl
# List patients
curl -s "https://au.aurabox.cloud/api/v1/patients" \
-H "Authorization: Bearer $AURABOX_API_KEY" \
-H "Accept: application/json" | jq
# Create a case
curl -s -X POST "https://au.aurabox.cloud/api/v1/cases" \
-H "Authorization: Bearer $AURABOX_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"label": "STUDY-2025-001"}' | jq
# Get studies for a patient
curl -s "https://au.aurabox.cloud/api/v1/patients/{patient_id}/studies" \
-H "Authorization: Bearer $AURABOX_API_KEY" \
-H "Accept: application/json" | jq
Error Handling
The API returns standard HTTP status codes:
| Code | Meaning |
|---|---|
200 |
Success |
201 |
Created |
204 |
Deleted (no content) |
401 |
Unauthorized (bad or missing API key) |
404 |
Not found |
422 |
Validation error (check response body for details) |
429 |
Rate limited |
500 |
Server error |
Error responses include a message field:
{
"message": "Not found"
}
Validation errors include field-level detail:
{
"message": "The given data was invalid.",
"errors": {
"given_names": ["The given names field is required."],
"family_name": ["The family name field is required."]
}
}
Common Patterns
Iterate All Patients
# Python: paginate through all patients
all_patients = list(client.paginate(client.list_patients))
Search and Filter
# Find active patients named "Smith"
results = client.list_patients(search="Smith", archived=False)
Bulk Case Creation (Research)
# Create cases for a research cohort
import csv
with open("cohort.csv") as f:
for row in csv.DictReader(f):
client.create_case(
label=row["study_id"],
sex=row.get("sex"),
date_of_birth=row.get("dob"),
)
Gotchas
- IDs are UUIDs -- not sequential integers. Always use the
idfield from API responses. - Patient vs Case -- Patients have PII (names, addresses). Cases are de-identified (label only). Use cases for research data.
- Studies are nested -- Study endpoints require a
patient_idin the URL path. You cannot query studies globally. - Dates must be before today -- The API rejects future dates for
date_of_birth. - Country is 2-char ISO -- The
address.countryfield accepts ISO 3166-1 alpha-2 codes only (e.g.,au).