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).
Resources
More from aurabx/skills
medical imaging pipelines
Build automated pipelines for medical imaging data: format conversion (DICOM to NIfTI, PNG, HDF5), batch processing, ML dataset preparation, research data export, and imaging ETL workflows. Use when converting DICOM to other formats, preparing imaging datasets for machine learning, building research data pipelines, batch processing medical images, extracting imaging features, or automating imaging workflows.
12dicom processing
Work with DICOM medical imaging files programmatically using pydicom, dcmtk, and related tools. Read, write, modify, and validate DICOM tags, pixel data, and metadata. Use when reading DICOM files, extracting metadata, modifying tags, working with pixel data, converting transfer syntaxes, validating DICOM conformance, or scripting bulk DICOM operations.
11dicomweb protocol
Build DICOMweb clients and integrations using WADO-RS (retrieve), STOW-RS (store), and QIDO-RS (query) protocols. Handles multipart MIME encoding, content negotiation, query parameters, and authentication. Use when building DICOMweb clients, querying a DICOMweb server, uploading DICOM via STOW-RS, retrieving imaging via WADO-RS, or integrating with any DICOMweb-compliant system including Aurabox, Orthanc, dcm4chee, or Google Cloud Healthcare API.
7