NDSS CRM Manual / Technical / Chapter 19: API Reference & Integration
V3.8 · 2024/2025

Chapter 19: API Reference & Integration

Complete technical reference for the NDSS CRM RESTful API, including authentication, CRUD endpoints for all major entities, Python service endpoints, PHP integration connectors, real-time subscriptions, webhooks, error handling, and rate limiting.

19.1 API Overview

The NDSS CRM platform exposes a comprehensive RESTful API that enables external systems, custom integrations, and third-party tools to interact programmatically with all major platform entities. The API is built on top of the Next.js API Routes layer (located in src/app/api/) with additional service endpoints provided by Python (for data processing, analytics, and report generation) and PHP (for legacy system connectors, data synchronisation, and bulk import/export operations).

19.1.1 Base URL

All API requests are made against the following base URL:

Production: https://app.newdawnsupport.com.au/api Staging: https://staging.newdawnsupport.com.au/api Development: http://localhost:3000/api

19.1.2 API Design Principles

  • RESTful Resource Naming: All endpoints follow REST conventions. Resources are plural nouns (e.g., /api/clients, /api/staff, /api/shifts). Actions that do not map directly to CRUD operations use verb suffixes (e.g., /api/shifts/:id/approve).
  • JSON Request/Response: All request bodies and response payloads use application/json content type. Dates follow ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ).
  • Consistent Envelope: Every response is wrapped in a standard envelope containing success, data, message, and meta fields.
  • Pagination: List endpoints support cursor-based and offset-based pagination via page, limit, cursor, and sort query parameters.
  • Filtering: List endpoints accept query parameters for field-level filtering (e.g., ?status=active&region=NSW).
  • Versioning: The current API version is v1. The version is included in the base path: /api/v1/. All endpoints documented in this chapter are V1 unless otherwise stated.
  • CORS: Cross-Origin Resource Sharing is configured to allow requests from authorised domains only. Custom integrations must be registered in the Admin Settings panel.

19.1.3 Authentication

All API requests (except POST /api/auth/login, POST /api/auth/register, and POST /api/auth/forgot-password) require a valid Bearer token in the Authorization header. Tokens are obtained by calling the login endpoint and are valid for 60 minutes. Refresh tokens are valid for 30 days.

// Required header for authenticated requests Authorization: Bearer <access_token> Content-Type: application/json

19.1.4 Standard Response Envelope

Every API response follows this structure:

{ "success": true, "data": { ... }, "message": "Operation completed successfully", "meta": { "page": 1, "limit": 25, "total": 247, "totalPages": 10, "hasNext": true, "hasPrev": false } }

19.1.5 Rate Limiting Overview

All API endpoints are rate-limited to protect platform stability. The default rate limit is 100 requests per minute per authenticated user. Certain high-cost endpoints (report generation, bulk operations) have lower limits. Rate limit headers are included in every response. See Section 19.13 for full details.

NDSS CRM - API Architecture Overview
+------------------------------------------------------------------+ | EXTERNAL CONSUMERS | | [ Mobile App ] [ Third-Party ] [ Webhook Receivers ] | +--------+-----------------+------------------+--------------------+ | | | v v v +------------------------------------------------------------------+ | API GATEWAY (Next.js) | | +-------------------+ +------------------+ +--------------+ | | | Auth Middleware | | Rate Limiter | | CORS | | | +-------------------+ +------------------+ +--------------+ | +------------------------------------------------------------------+ | | | v v v +------------------------------------------------------------------+ | ROUTE HANDLERS | | /api/auth/* /api/clients/* /api/staff/* /api/shifts/* | | /api/invoices/* /api/incidents/* /api/webhooks/* | +------------------------------------------------------------------+ | | | v v v +------------------------------------------------------------------+ | SERVICE LAYER (TypeScript + Python + PHP) | | +-----------------+ +------------------+ +----------------+ | | | Next.js/TS | | Python Services | | PHP Connectors | | | | Core CRUD | | Analytics | | Legacy Sync | | | | Validation | | Report Gen | | Data Import | | | | Business Logic | | Data Processing | | Bulk Export | | | +-----------------+ +------------------+ +----------------+ | +------------------------------------------------------------------+ | | | v v v +------------------------------------------------------------------+ | DATA LAYER | | +---------------------------+ +-----------------------------+ | | | PostgreSQL (Supabase / Oracle) | | Supabase / Oracle Real-Time | | | | Tables, Views, Functions | | Subscriptions, Broadcasts | | | +---------------------------+ +-----------------------------+ | +------------------------------------------------------------------+

19.2 Authentication API

The Authentication API handles user login, registration, logout, token refresh, and password recovery. All authentication endpoints are prefixed with /api/auth/. These endpoints interact directly with Supabase / Oracle Auth and the NDSS CRM user profiles table in PostgreSQL.

19.2.1 POST /api/auth/login

POST /api/auth/login

Authenticates a user with email and password. Returns an access token, refresh token, and user profile information including the assigned role.

Request Body:

{ "email": "admin@newdawnsupport.com.au", "password": "SecureP@ssw0rd!" }

Success Response (200 OK):

{ "success": true, "data": { "accessToken": "eyJhbGciOiJIUzI1NiIs...", "refreshToken": "v1.MjAyNC0wNi0xNVQx...", "expiresIn": 3600, "tokenType": "Bearer", "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "admin@newdawnsupport.com.au", "firstName": "Sarah", "lastName": "Mitchell", "role": "master_admin", "status": "active", "lastLogin": "2025-01-15T09:23:41.000Z" } }, "message": "Login successful" }

Error Response (401 Unauthorized):

{ "success": false, "error": { "code": "AUTH_INVALID_CREDENTIALS", "message": "Invalid email or password", "statusCode": 401 } }

19.2.2 POST /api/auth/register

POST /api/auth/register

Creates a new user account. This endpoint is restricted to administrators who can register new staff members. Self-registration is not permitted. The new user receives an email verification link.

Request Body:

{ "email": "jane.smith@newdawnsupport.com.au", "password": "TempP@ssw0rd123!", "firstName": "Jane", "lastName": "Smith", "role": "support_worker", "phone": "+61412345678", "department": "Community Support", "employmentType": "full_time", "startDate": "2025-02-01" }

Success Response (201 Created):

{ "success": true, "data": { "id": "660e8400-e29b-41d4-a716-446655440001", "email": "jane.smith@newdawnsupport.com.au", "role": "support_worker", "status": "pending_verification", "createdAt": "2025-02-01T10:00:00.000Z" }, "message": "User registered successfully. Verification email sent." }

19.2.3 POST /api/auth/logout

POST /api/auth/logout

Invalidates the current session and revokes the refresh token. Requires a valid access token in the Authorization header.

Request Headers:

Authorization: Bearer <access_token>

Success Response (200 OK):

{ "success": true, "message": "Logout successful. Session terminated." }

19.2.4 POST /api/auth/refresh

POST /api/auth/refresh

Exchanges a valid refresh token for a new access token and refresh token pair. The old refresh token is invalidated immediately to prevent token reuse attacks.

Request Body:

{ "refreshToken": "v1.MjAyNC0wNi0xNVQx..." }

Success Response (200 OK):

{ "success": true, "data": { "accessToken": "eyJhbGciOiJIUzI1NiIs...", "refreshToken": "v1.MjAyNC0wNy0xNVQx...", "expiresIn": 3600 }, "message": "Token refreshed successfully" }

19.2.5 POST /api/auth/forgot-password

POST /api/auth/forgot-password

Initiates a password reset flow by sending a time-limited reset link to the registered email address. The reset token expires after 60 minutes.

Request Body:

{ "email": "jane.smith@newdawnsupport.com.au" }

Success Response (200 OK):

{ "success": true, "message": "If an account with that email exists, a password reset link has been sent." }
Security Note

The forgot-password endpoint always returns a success response regardless of whether the email exists in the system. This prevents email enumeration attacks. The actual reset email is only sent if the account exists and is in an active state.

19.3 Client API

The Client API provides full CRUD operations for managing NDIS participant records. All client endpoints require authentication and are subject to role-based access control. Only users with roles that include client management permissions (e.g., master_admin, administrator, service_coordinator, support_worker) can access these endpoints.

19.3.1 GET /api/clients

GET /api/clients

Retrieves a paginated list of clients. Supports filtering by status, region, service type, NDIS plan status, and assigned coordinator.

Query Parameters:

Parameter Type Default Description
pageinteger1Page number for pagination
limitinteger25Number of records per page (max 100)
statusstring-Filter by status: active, inactive, waitlist, discharged
regionstring-Filter by service region (e.g., NSW, VIC, QLD)
coordinatorIdUUID-Filter by assigned service coordinator
serviceTypestring-Filter by NDIS service category
searchstring-Full-text search across name, NDIS number, email
sortstringlastName:ascSort field and direction (e.g., createdAt:desc)

Success Response (200 OK):

{ "success": true, "data": [ { "id": "c001-uuid", "ndisNumber": "431234567", "firstName": "Michael", "lastName": "Thompson", "dateOfBirth": "1985-03-22", "status": "active", "region": "NSW", "primaryDisability": "Intellectual Disability", "planStartDate": "2024-07-01", "planEndDate": "2025-06-30", "totalBudget": 85000.00, "budgetUsed": 42350.75, "coordinatorId": "s001-uuid", "coordinatorName": "Lisa Chen", "createdAt": "2024-07-01T00:00:00.000Z", "updatedAt": "2025-01-10T14:30:00.000Z" } ], "meta": { "page": 1, "limit": 25, "total": 247, "totalPages": 10 } }

19.3.2 GET /api/clients/:id

GET /api/clients/:id

Retrieves a single client record by UUID. Returns the full client profile including personal details, NDIS plan information, funding allocations, service agreements, goals, and document references.

Success Response (200 OK):

{ "success": true, "data": { "id": "c001-uuid", "ndisNumber": "431234567", "firstName": "Michael", "lastName": "Thompson", "dateOfBirth": "1985-03-22", "gender": "male", "email": "m.thompson@email.com", "phone": "+61400111222", "address": { "street": "42 Wattle Drive", "suburb": "Parramatta", "state": "NSW", "postcode": "2150" }, "primaryDisability": "Intellectual Disability", "secondaryDisabilities": ["Epilepsy"], "status": "active", "ndisPlan": { "planNumber": "PLN-2024-00891", "startDate": "2024-07-01", "endDate": "2025-06-30", "managementType": "plan_managed", "totalBudget": 85000.00, "categories": [ { "code": "01", "name": "Assistance with Daily Life", "budget": 45000.00 }, { "code": "04", "name": "Assistance with Social and Community Participation", "budget": 25000.00 }, { "code": "15", "name": "Improved Daily Living Skills", "budget": 15000.00 } ] }, "emergencyContact": { "name": "Margaret Thompson", "relationship": "Mother", "phone": "+61400333444" }, "riskLevel": "medium", "coordinatorId": "s001-uuid", "createdAt": "2024-07-01T00:00:00.000Z", "updatedAt": "2025-01-10T14:30:00.000Z" } }

19.3.3 POST /api/clients

POST /api/clients

Creates a new client record. Requires at minimum: first name, last name, date of birth, NDIS number, and primary disability. All other fields are optional at creation and can be populated later.

Request Body (minimum required fields):

{ "firstName": "David", "lastName": "Wilson", "dateOfBirth": "1990-08-15", "ndisNumber": "439876543", "primaryDisability": "Autism Spectrum Disorder", "region": "VIC", "coordinatorId": "s002-uuid" }

Success Response (201 Created):

{ "success": true, "data": { "id": "c002-uuid", "ndisNumber": "439876543", "firstName": "David", "lastName": "Wilson", "status": "active", "createdAt": "2025-01-20T11:00:00.000Z" }, "message": "Client created successfully" }

19.3.4 PUT /api/clients/:id

PUT /api/clients/:id

Updates an existing client record. Supports partial updates (only fields included in the request body are modified). The id and ndisNumber fields cannot be changed after creation.

Request Body (partial update example):

{ "phone": "+61400555666", "address": { "street": "88 Eucalyptus Lane", "suburb": "Richmond", "state": "VIC", "postcode": "3121" }, "riskLevel": "low" }

19.3.5 DELETE /api/clients/:id

DELETE /api/clients/:id

Soft-deletes a client record by setting status to archived and deletedAt to the current timestamp. Client data is retained for audit and compliance purposes in accordance with NDIS data retention requirements (minimum 7 years). Only master_admin and administrator roles can perform this operation.

Success Response (200 OK):

{ "success": true, "message": "Client archived successfully. Data retained for compliance." }

19.4 Staff API

The Staff API provides endpoints for managing employee records, including personal details, qualifications, certifications, availability, and employment information. Access is restricted based on role permissions.

19.4.1 GET /api/staff

GET /api/staff

Retrieves a paginated list of staff members. Supports filtering by role, status, department, qualification, and availability.

Query Parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
limitinteger25Records per page (max 100)
rolestring-Filter by role identifier
statusstring-active, inactive, on_leave, terminated
departmentstring-Filter by department name
qualificationstring-Filter by qualification type
availableDatestring-ISO date to check availability
searchstring-Full-text search across name, email

Success Response (200 OK):

{ "success": true, "data": [ { "id": "s001-uuid", "firstName": "Lisa", "lastName": "Chen", "email": "l.chen@newdawnsupport.com.au", "role": "service_coordinator", "department": "Community Support", "status": "active", "employmentType": "full_time", "ndisWorkerScreening": { "status": "cleared", "expiryDate": "2024-03-15" }, "qualifications": [ "Certificate IV in Disability", "First Aid Certificate" ], "createdAt": "2024-01-15T00:00:00.000Z" } ], "meta": { "page": 1, "limit": 25, "total": 86, "totalPages": 4 } }

19.4.2 GET /api/staff/:id

GET /api/staff/:id

Returns the full staff profile including personal details, employment history, qualifications, certifications, training records, availability schedule, and assigned clients.

19.4.3 POST /api/staff

POST /api/staff

Creates a new staff record. This endpoint also triggers the user registration process (see Section 19.2.2). Required fields: first name, last name, email, role, and employment type.

Request Body:

{ "firstName": "Tom", "lastName": "Nguyen", "email": "t.nguyen@newdawnsupport.com.au", "phone": "+61400777888", "role": "support_worker", "department": "SIL Services", "employmentType": "part_time", "startDate": "2025-03-01", "qualifications": [ "Certificate III in Individual Support", "NDIS Worker Orientation Module" ], "availability": { "monday": { "available": true, "start": "07:00", "end": "15:00" }, "tuesday": { "available": true, "start": "07:00", "end": "15:00" }, "wednesday": { "available": false }, "thursday": { "available": true, "start": "14:00", "end": "22:00" }, "friday": { "available": true, "start": "07:00", "end": "15:00" }, "saturday": { "available": false }, "sunday": { "available": false } } }

19.4.4 PUT /api/staff/:id

PUT /api/staff/:id

Updates an existing staff record. Supports partial updates. Role changes require master_admin or administrator privileges and trigger an audit log entry.

19.4.5 DELETE /api/staff/:id

DELETE /api/staff/:id

Soft-deletes a staff record by setting status to terminated. The associated user account is deactivated but not removed. All historical records (shifts, timesheets, progress notes) are preserved for audit compliance.

19.5 Shift API

The Shift API manages the complete lifecycle of rostered shifts, from creation and assignment through to completion and timesheet approval. Shifts are the core operational unit linking staff members to client service delivery.

19.5.1 GET /api/shifts

GET /api/shifts

Retrieves shifts with filtering by date range, staff member, client, status, and location. Commonly used to populate calendar views and roster screens.

Query Parameters:

ParameterTypeDescription
startDateISO dateStart of date range (required)
endDateISO dateEnd of date range (required)
staffIdUUIDFilter by assigned staff member
clientIdUUIDFilter by client
statusstringscheduled, in_progress, completed, cancelled, no_show
locationstringFilter by service location

Success Response (200 OK):

{ "success": true, "data": [ { "id": "sh001-uuid", "clientId": "c001-uuid", "clientName": "Michael Thompson", "staffId": "s003-uuid", "staffName": "Tom Nguyen", "date": "2025-01-20", "startTime": "08:00", "endTime": "16:00", "duration": 8.0, "status": "scheduled", "serviceType": "Assistance with Daily Life", "ndisLineItem": "01_011_0107_1_1", "location": "Client Home", "notes": "Morning routine support and meal preparation" } ] }

19.5.2 POST /api/shifts

POST /api/shifts

Creates a new shift. The system validates staff availability, checks for scheduling conflicts, and verifies the client has sufficient NDIS budget remaining for the service type.

Request Body:

{ "clientId": "c001-uuid", "staffId": "s003-uuid", "date": "2025-01-22", "startTime": "08:00", "endTime": "16:00", "serviceType": "Assistance with Daily Life", "ndisLineItem": "01_011_0107_1_1", "location": "Client Home", "recurrence": { "type": "weekly", "endDate": "2025-06-30", "daysOfWeek": [1, 3, 5] } }

19.5.3 PUT /api/shifts/:id

PUT /api/shifts/:id

Updates a shift. Only shifts in scheduled status can be fully edited. Shifts in in_progress status can only have their end time and notes modified.

19.5.4 DELETE /api/shifts/:id

DELETE /api/shifts/:id

Cancels a shift by setting status to cancelled. A cancellation reason is required. If the shift is part of a recurring series, the user can choose to cancel just this occurrence or all future occurrences.

19.5.5 PATCH /api/shifts/:id/status

PATCH /api/shifts/:id/status

Updates the status of a shift. Valid transitions are enforced by the system:

Current StatusAllowed TransitionsRequired By
scheduledin_progress, cancelledStaff, Roster Officer
in_progresscompleted, cancelledStaff, Roster Officer
completedapprovedCoordinator, Admin
approvedinvoicedFinance

19.5.6 POST /api/shifts/:id/clock-in

POST /api/shifts/:id/clock-in

Records the start time when a support worker begins a shift. Captures GPS coordinates (if enabled) and device information for verification purposes.

{ "timestamp": "2025-01-22T08:02:15.000Z", "latitude": -33.8148, "longitude": 151.0012, "deviceId": "mobile-ios-a1b2c3" }

19.5.7 POST /api/shifts/:id/clock-out

POST /api/shifts/:id/clock-out

Records the end time when a support worker completes a shift. Requires a progress note to be submitted with the clock-out. The shift status transitions to completed.

{ "timestamp": "2025-01-22T16:05:30.000Z", "latitude": -33.8148, "longitude": 151.0012, "progressNote": "Assisted Michael with morning routine, meal prep, and community access outing to local shops. Michael was in good spirits and engaged well in all activities.", "goalsAddressed": ["goal-001", "goal-003"] }

19.6 Invoice API

The Invoice API handles the creation, management, submission, and approval of NDIS invoices. Invoices are generated from approved shifts and linked to specific NDIS line items and client plans.

19.6.1 GET /api/invoices

GET /api/invoices

Retrieves a paginated list of invoices with filtering by status, client, date range, and payment status.

Query Parameters:

ParameterTypeDescription
statusstringdraft, pending, submitted, paid, rejected, void
clientIdUUIDFilter by client
startDateISO dateInvoice date range start
endDateISO dateInvoice date range end
minAmountnumberMinimum invoice amount
maxAmountnumberMaximum invoice amount

Success Response (200 OK):

{ "success": true, "data": [ { "id": "inv001-uuid", "invoiceNumber": "INV-2025-00142", "clientId": "c001-uuid", "clientName": "Michael Thompson", "ndisNumber": "431234567", "invoiceDate": "2025-01-25", "dueDate": "2025-02-24", "totalAmount": 2480.00, "gst": 0.00, "status": "submitted", "lineItems": [ { "description": "Assistance with Daily Life - Weekday Daytime", "ndisLineItem": "01_011_0107_1_1", "quantity": 40, "unit": "hours", "rate": 62.00, "amount": 2480.00 } ], "createdAt": "2025-01-25T10:00:00.000Z" } ] }

19.6.2 POST /api/invoices

POST /api/invoices

Creates a new invoice. Invoices can be created manually or auto-generated from approved shifts within a specified date range.

Manual Creation Request Body:

{ "clientId": "c001-uuid", "invoiceDate": "2025-01-25", "dueDate": "2025-02-24", "lineItems": [ { "description": "Assistance with Daily Life - Weekday Daytime", "ndisLineItem": "01_011_0107_1_1", "quantity": 40, "unit": "hours", "rate": 62.00 } ] }

Auto-Generation from Shifts:

// POST /api/invoices/generate { "clientId": "c001-uuid", "startDate": "2025-01-01", "endDate": "2025-01-31", "autoSubmit": false }

19.6.3 PATCH /api/invoices/:id/submit

PATCH /api/invoices/:id/submit

Submits a draft invoice for approval. Validates all line items against the NDIS price guide and checks the client's remaining budget before submission. Transitions the invoice status from draft to pending.

19.6.4 PATCH /api/invoices/:id/approve

PATCH /api/invoices/:id/approve

Approves a pending invoice. Only users with the finance, administrator, or master_admin role can approve invoices. Transitions the status from pending to submitted (ready for NDIS claim).

{ "approverNotes": "Verified against approved shifts. All line items match NDIS price guide rates." }

19.6.5 PATCH /api/invoices/:id/void

PATCH /api/invoices/:id/void

Voids an invoice. A void reason is required. Voided invoices cannot be reactivated. The associated NDIS budget allocation is released back to the client's plan.

19.7 Incident API

The Incident API manages the reporting, investigation, and resolution of incidents in accordance with NDIS Quality and Safeguards Commission requirements. All incident-related actions are logged in an immutable audit trail.

19.7.1 GET /api/incidents

GET /api/incidents

Retrieves incidents with filtering by severity, status, client, staff member, category, and date range.

Query Parameters:

ParameterTypeDescription
severitystringlow, medium, high, critical
statusstringreported, under_investigation, action_required, resolved, closed
categorystringinjury, medication_error, behaviour, property_damage, abuse_neglect, restrictive_practice, death, other
clientIdUUIDFilter by involved client
reportedByUUIDFilter by reporting staff member

19.7.2 POST /api/incidents

POST /api/incidents

Reports a new incident. Certain categories (abuse/neglect, restrictive practices, death) automatically trigger notifications to the Compliance Officer and may require reporting to the NDIS Quality and Safeguards Commission within 24 hours.

Request Body:

{ "clientId": "c001-uuid", "category": "injury", "severity": "medium", "dateTime": "2025-01-20T14:30:00.000Z", "location": "Client Home - Kitchen", "description": "Client sustained a minor burn to left hand while assisting with meal preparation. First aid administered immediately. No medical attention required.", "immediateActions": "Cold water applied for 20 minutes. Area dressed with sterile bandage. Client monitored for 1 hour.", "witnessIds": ["s003-uuid"], "reportedBy": "s003-uuid" }

19.7.3 PATCH /api/incidents/:id/status

PATCH /api/incidents/:id/status

Updates the status of an incident. Status transitions follow a defined workflow:

Current StatusAllowed TransitionsRequired Role
reportedunder_investigationCompliance Officer, Admin
under_investigationaction_required, resolvedCompliance Officer, Admin
action_requiredresolvedCompliance Officer, Admin
resolvedclosedMaster Admin, Admin

19.8 Supabase / Oracle Real-Time Subscriptions

NDSS CRM leverages Supabase / Oracle Real-Time to deliver instant updates to connected clients without polling. This is used extensively for the dashboard activity feed, shift status updates, messaging, and notification delivery. The platform uses both PostgreSQL Change Data Capture (CDC) channels and Supabase / Oracle Broadcast channels.

19.8.1 PostgreSQL CDC Subscriptions

CDC subscriptions listen for INSERT, UPDATE, and DELETE events on specific database tables. These are used for data synchronisation across connected browser sessions.

TypeScript Client Example:

import { createClient } from '@supabase/supabase-js'; const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! ); // Subscribe to shift status changes const shiftSubscription = supabase .channel('shift-updates') .on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'shifts', filter: 'status=eq.in_progress' }, (payload) => { console.log('Shift updated:', payload.new); // Update the roster calendar in real-time updateRosterView(payload.new); } ) .subscribe(); // Subscribe to new incident reports const incidentSubscription = supabase .channel('incident-alerts') .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'incidents', filter: 'severity=in.(high,critical)' }, (payload) => { showUrgentNotification(payload.new); } ) .subscribe(); // Subscribe to client record changes for a specific client const clientSubscription = supabase .channel('client-c001') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'clients', filter: 'id=eq.c001-uuid' }, (payload) => { refreshClientProfile(payload.new); } ) .subscribe();

19.8.2 Broadcast Channels

Broadcast channels are used for ephemeral, user-to-user communication that does not need to be persisted in the database. This includes typing indicators, presence status, and live collaboration signals.

// Broadcast: typing indicator for messaging const messagingChannel = supabase .channel('messaging-room-001') .on('broadcast', { event: 'typing' }, (payload) => { showTypingIndicator(payload.payload.userId); }) .subscribe(); // Send typing event messagingChannel.send({ type: 'broadcast', event: 'typing', payload: { userId: currentUser.id, displayName: currentUser.name } }); // Presence: track online users on the dashboard const presenceChannel = supabase .channel('online-users') .on('presence', { event: 'sync' }, () => { const state = presenceChannel.presenceState(); updateOnlineUserList(state); }) .subscribe(async (status) => { if (status === 'SUBSCRIBED') { await presenceChannel.track({ userId: currentUser.id, role: currentUser.role, onlineAt: new Date().toISOString() }); } });

19.8.3 Available CDC Channels

TableEventsCommon Use Case
shiftsINSERT, UPDATE, DELETERoster calendar real-time sync
incidentsINSERT, UPDATEUrgent incident notifications
messagesINSERTNew message delivery
notificationsINSERTPush notification delivery
clientsUPDATEClient profile change alerts
invoicesINSERT, UPDATEInvoice status change notifications
timesheetsINSERT, UPDATETimesheet submission alerts
progress_notesINSERTNew progress note notifications

19.9 Python Service Endpoints

NDSS CRM uses a Python microservice layer for computationally intensive operations including data processing, report generation, analytics computations, and scheduled batch jobs. The Python services are built with Flask and communicate with the main Next.js application via internal HTTP calls. These endpoints are not directly exposed to external consumers but are invoked by the Next.js API layer.

19.9.1 Report Generation

POST /python/reports/generate

Generates complex reports in PDF, CSV, or XLSX format. Supports all report types defined in the platform (financial summaries, client outcome reports, compliance audits, staff utilisation reports, etc.).

Request Body:

{ "reportType": "financial_summary", "parameters": { "startDate": "2024-07-01", "endDate": "2024-12-31", "region": "NSW", "groupBy": "month", "includeGst": true }, "outputFormat": "pdf", "requestedBy": "s001-uuid" }

Python Service Implementation (excerpt):

from flask import Flask, request, jsonify, send_file from reportlab.lib.pagesizes import A4 from reportlab.platypus import SimpleDocTemplate, Table, TableStyle import psycopg2 import pandas as pd app = Flask(__name__) @app.route('/python/reports/generate', methods=['POST']) def generate_report(): data = request.get_json() report_type = data['reportType'] params = data['parameters'] output_format = data.get('outputFormat', 'pdf') # Connect to PostgreSQL via Supabase / Oracle connection string conn = psycopg2.connect(os.environ['DATABASE_URL']) if report_type == 'financial_summary': df = pd.read_sql( """ SELECT DATE_TRUNC(%s, i.invoice_date) AS period, COUNT(i.id) AS invoice_count, SUM(i.total_amount) AS total_revenue, SUM(CASE WHEN i.status = 'paid' THEN i.total_amount ELSE 0 END) AS collected, SUM(CASE WHEN i.status = 'submitted' THEN i.total_amount ELSE 0 END) AS outstanding FROM invoices i JOIN clients c ON i.client_id = c.id WHERE i.invoice_date BETWEEN %s AND %s AND (%s IS NULL OR c.region = %s) GROUP BY period ORDER BY period """, conn, params=[ params['groupBy'], params['startDate'], params['endDate'], params.get('region'), params.get('region') ] ) if output_format == 'pdf': filepath = generate_pdf_report(df, report_type, params) elif output_format == 'csv': filepath = generate_csv_report(df, report_type) elif output_format == 'xlsx': filepath = generate_xlsx_report(df, report_type) return send_file(filepath, as_attachment=True) return jsonify({'error': 'Unknown report type'}), 400

19.9.2 Analytics Computations

POST /python/analytics/compute

Performs complex analytics calculations including staff utilisation rates, client outcome trends, budget burn-rate projections, and compliance score aggregations.

Request Body:

{ "metric": "staff_utilisation", "parameters": { "startDate": "2025-01-01", "endDate": "2025-01-31", "department": "Community Support", "granularity": "daily" } }

Response:

{ "success": true, "data": { "metric": "staff_utilisation", "averageUtilisation": 78.5, "peakUtilisation": 95.2, "lowUtilisation": 42.1, "dataPoints": [ { "date": "2025-01-01", "utilisation": 72.3, "scheduledHours": 480, "workedHours": 347 }, { "date": "2025-01-02", "utilisation": 81.7, "scheduledHours": 520, "workedHours": 425 } ] } }

19.9.3 Data Processing Pipeline

POST /python/data/process

Handles batch data processing tasks including NDIS price guide imports, bulk client data transformations, scheduled data cleanup, and data validation routines.

Available Processing Tasks:

Task TypeDescriptionSchedule
price_guide_importImports and parses the latest NDIS price guide CSV into the platformOn demand / quarterly
budget_recalculationRecalculates budget usage for all active clients based on approved invoicesNightly at 02:00 AEST
expiry_alertsScans staff certifications and generates alerts for upcoming expiriesDaily at 06:00 AEST
plan_review_alertsIdentifies NDIS plans approaching end date (30, 60, 90 day warnings)Weekly on Monday
data_deduplicationIdentifies and flags potential duplicate client or staff recordsOn demand
compliance_scoringCalculates organisation-wide compliance scores across all NDIS Practice StandardsMonthly on 1st

19.9.4 Scheduled Jobs Manager

GET /python/jobs/status

Returns the status of all scheduled Python jobs including last run time, next scheduled run, and success/failure counts.

{ "success": true, "data": { "jobs": [ { "name": "budget_recalculation", "status": "completed", "lastRun": "2025-01-20T02:00:00.000Z", "nextRun": "2025-01-21T02:00:00.000Z", "duration": "4m 23s", "recordsProcessed": 247, "consecutiveSuccesses": 45 }, { "name": "expiry_alerts", "status": "completed", "lastRun": "2025-01-20T06:00:00.000Z", "nextRun": "2025-01-21T06:00:00.000Z", "duration": "1m 12s", "alertsGenerated": 7, "consecutiveSuccesses": 30 } ] } }

19.10 PHP Integration Endpoints

NDSS CRM includes a PHP integration layer that provides connectivity with legacy systems, bulk data import/export functionality, and specialised data synchronisation connectors. The PHP services are built with Laravel and run as a separate microservice that communicates with the main platform via internal API calls and shared PostgreSQL database access.

19.10.1 Legacy System Connectors

The PHP integration layer provides connectors for common legacy systems used by NDIS providers that are transitioning to NDSS CRM.

POST /php/connectors/sync

Initiates a data synchronisation job between a legacy system and NDSS CRM.

Request Body:

{ "connector": "myob", "direction": "pull", "entities": ["invoices", "payments"], "dateRange": { "from": "2025-01-01", "to": "2025-01-31" }, "credentials": { "apiKey": "stored-credential-ref-001" } }

Supported Legacy Connectors:

ConnectorTypeEntities SupportedDirection
myobAccountingInvoices, Payments, ContactsPull / Push
xeroAccountingInvoices, Payments, ContactsPull / Push
prodaNDIS ClaimsClaims, ResponsesPush / Pull
carelinkCare ManagementClients, Plans, NotesPull only
deputyRosteringShifts, Timesheets, StaffPull / Push
employment_heroHR/PayrollStaff, Leave, PayrollPush only

19.10.2 Bulk Data Import

POST /php/import/bulk

Handles bulk data imports from CSV, XLSX, and JSON files. Supports client records, staff records, historical shifts, and invoice data. The import process includes validation, duplicate detection, and error reporting.

PHP Service Implementation (excerpt):

// Laravel Controller - BulkImportController.php namespace App\Http\Controllers; use App\Services\ImportService; use App\Jobs\ProcessBulkImport; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; class BulkImportController extends Controller { public function import(Request $request) { $validated = $request->validate([ 'entity' => 'required|in:clients,staff,shifts,invoices', 'file' => 'required|file|mimes:csv,xlsx,json|max:10240', 'options.skipDuplicates' => 'boolean', 'options.updateExisting' => 'boolean', 'options.dryRun' => 'boolean', ]); $file = $request->file('file'); $entity = $validated['entity']; $options = $validated['options'] ?? []; // Queue the import job for background processing $importJob = ImportService::create([ 'entity' => $entity, 'filename' => $file->getClientOriginalName(), 'status' => 'queued', 'requestedBy' => $request->user()->id, ]); ProcessBulkImport::dispatch($importJob, $file->path(), $options); return response()->json([ 'success' => true, 'data' => [ 'importId' => $importJob->id, 'status' => 'queued', ], 'message' => 'Import job queued. Check status at /php/import/{id}/status', ], 202); } }

19.10.3 Bulk Data Export

POST /php/export/bulk

Generates bulk data exports in CSV, XLSX, JSON, or PDF format. Exports respect the requesting user's role-based data access permissions.

Request Body:

{ "entity": "clients", "format": "xlsx", "filters": { "status": "active", "region": "NSW" }, "columns": [ "ndisNumber", "firstName", "lastName", "dateOfBirth", "primaryDisability", "status", "planStartDate", "planEndDate", "totalBudget" ], "includeHeaders": true }

19.10.4 Import Status Tracking

GET /php/import/:id/status

Returns the current status and progress of a bulk import job.

{ "success": true, "data": { "importId": "imp-001-uuid", "entity": "clients", "status": "processing", "progress": { "totalRows": 500, "processed": 342, "successful": 335, "failed": 7, "skipped": 0, "percentComplete": 68.4 }, "errors": [ { "row": 45, "field": "ndisNumber", "message": "NDIS number already exists in system" }, { "row": 112, "field": "dateOfBirth", "message": "Invalid date format. Expected YYYY-MM-DD" } ], "startedAt": "2025-01-20T10:00:00.000Z", "estimatedCompletion": "2025-01-20T10:08:00.000Z" } }

19.11 Webhook Configuration

NDSS CRM supports outbound webhooks that notify external systems when specific events occur within the platform. Webhooks are configured through the Admin Settings panel or via the API. Each webhook endpoint receives a POST request with a JSON payload describing the event.

19.11.1 Webhook Registration

POST /api/webhooks

{ "url": "https://external-system.example.com/webhook", "events": [ "client.created", "client.updated", "shift.completed", "invoice.submitted", "incident.reported" ], "secret": "whsec_a1b2c3d4e5f6...", "active": true, "description": "Sync events to external accounting system" }

19.11.2 Available Event Types

EventTriggerPayload Includes
client.createdNew client record createdFull client object
client.updatedClient record modifiedUpdated fields, previous values
client.archivedClient soft-deletedClient ID, archive reason
staff.createdNew staff member registeredStaff profile (excluding sensitive data)
staff.updatedStaff record modifiedUpdated fields
shift.createdNew shift scheduledFull shift object
shift.completedShift marked as completedShift with timesheet data
shift.cancelledShift cancelledShift ID, cancellation reason
invoice.createdNew invoice generatedInvoice with line items
invoice.submittedInvoice submitted for claimInvoice summary
invoice.paidPayment receivedInvoice ID, payment details
incident.reportedNew incident filedIncident details (redacted PII)
incident.resolvedIncident resolution recordedIncident ID, resolution summary
compliance.alertCompliance threshold breachAlert type, affected entity

19.11.3 Webhook Payload Format

All webhook deliveries follow this standard payload structure:

{ "id": "evt_001-uuid", "type": "shift.completed", "timestamp": "2025-01-20T16:05:30.000Z", "version": "v1", "data": { // Event-specific payload }, "metadata": { "source": "ndss-crm", "environment": "production", "deliveryAttempt": 1 } }

19.11.4 Signature Verification

Each webhook delivery includes a X-NDSS-Signature header containing an HMAC-SHA256 signature computed from the request body and the webhook secret. Receiving systems should verify this signature to ensure the webhook was sent by NDSS CRM and has not been tampered with.

// Verification example (Node.js) const crypto = require('crypto'); function verifyWebhookSignature(body, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(body) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from('sha256=' + expected) ); }

19.11.5 Retry Policy

If a webhook delivery fails (non-2xx response or timeout after 30 seconds), NDSS CRM retries the delivery using exponential backoff:

AttemptDelayCumulative Wait
1 (initial)Immediate0 seconds
230 seconds30 seconds
32 minutes2.5 minutes
410 minutes12.5 minutes
530 minutes42.5 minutes
62 hours2 hours 42.5 minutes
7 (final)6 hours8 hours 42.5 minutes

After 7 failed attempts, the webhook is marked as failed and the administrator is notified. The webhook endpoint is automatically disabled after 50 consecutive failures.

19.12 Error Handling

The NDSS CRM API uses standard HTTP status codes combined with structured error response bodies to communicate failure conditions. Every error response includes a machine-readable error code, a human-readable message, and the HTTP status code.

19.12.1 Error Response Format

{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "One or more fields failed validation", "statusCode": 422, "details": [ { "field": "email", "message": "Must be a valid email address", "code": "invalid_format" }, { "field": "ndisNumber", "message": "NDIS number must be exactly 9 digits", "code": "invalid_length" } ] } }

19.12.2 Error Code Reference

HTTP StatusError CodeDescription
400BAD_REQUESTMalformed request syntax or invalid request body
401AUTH_INVALID_CREDENTIALSEmail or password is incorrect
401AUTH_TOKEN_EXPIREDAccess token has expired. Use refresh endpoint.
401AUTH_TOKEN_INVALIDToken is malformed or has been revoked
403AUTH_INSUFFICIENT_PERMISSIONSUser role does not have permission for this action
403AUTH_ACCOUNT_DISABLEDUser account has been deactivated
404RESOURCE_NOT_FOUNDRequested resource does not exist or has been archived
409CONFLICT_DUPLICATEA record with the same unique identifier already exists
409CONFLICT_SCHEDULEShift conflicts with existing scheduled shift for this staff member
422VALIDATION_ERRORRequest body failed schema validation
422BUDGET_EXCEEDEDRequested service exceeds available NDIS plan budget
422INVALID_STATUS_TRANSITIONRequested status change is not permitted from current status
429RATE_LIMIT_EXCEEDEDToo many requests. Retry after the specified time.
500INTERNAL_ERRORUnexpected server error. Contact support if persistent.
502SERVICE_UNAVAILABLEDownstream service (Python/PHP) is temporarily unavailable
503MAINTENANCE_MODEPlatform is undergoing scheduled maintenance

19.13 Rate Limiting

Rate limiting protects the NDSS CRM platform from abuse and ensures fair resource allocation across all consumers. Rate limits are applied per authenticated user (identified by access token) and vary by endpoint category.

19.13.1 Rate Limit Tiers

Endpoint CategoryLimitWindowNotes
Standard CRUD (GET, POST, PUT, DELETE)100 requests1 minuteMost API endpoints
Authentication (login, register, refresh)10 requests1 minuteProtects against brute-force attacks
Search / List with complex filters30 requests1 minuteDatabase-intensive queries
Report Generation (Python)5 requests5 minutesComputationally expensive operations
Bulk Import/Export (PHP)3 requests10 minutesLong-running batch operations
Webhook Management20 requests1 minuteConfiguration endpoints only
File Upload10 requests1 minuteMaximum 10 MB per file

19.13.2 Rate Limit Response Headers

Every API response includes the following rate limit headers:

X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1706185260 Retry-After: 45 // Only included when rate limit is exceeded (429 response)

19.13.3 Rate Limit Exceeded Response

{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Rate limit exceeded. Please retry after 45 seconds.", "statusCode": 429, "retryAfter": 45 } }
Rate Limit Increase

Organisations that require higher rate limits for approved integrations can request a limit increase through the Admin Settings panel or by contacting Newdawn Support Services. Custom rate limit tiers are available for enterprise integration partners.