Total Access Docs
API Reference

Public Data API

Action-based API for reading and writing Total Access data from external applications.

Public Data API

The Public Data API provides a simplified, action-based endpoint for external applications to read and write Total Access data using an API key. It uses the X-API-Key header instead of Authorization: Bearer.

Endpoints

MethodPathDescription
GET/api/v1/public/dataDiscovery and documentation
POST/api/v1/public/dataExecute an action
GET/api/v1/public/data/tools?format=mcpTool catalog for AI agents (MCP schema)
GET/api/v1/public/data/tools?format=openaiTool catalog (OpenAI function schema)
POST/api/v1/public/mcpMCP JSON-RPC adapter

See AI Agent & MCP Bridge for agent-specific usage.

Authentication

X-API-Key: ta_sk_a1b2c3d4e5f6...

The API key must have the appropriate scopes for the action being performed. See Authentication for the scope catalog.

Request format

All requests are POST with a JSON body containing an action field:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-active-users",
    "status": "active"
  }'

Available actions

Users & Employees

ActionRequired ScopeDescription
get-active-usersusers:readGet all active users with client membership
get-employeesemployees:readGet employees with pagination and filters
get-user-membershipsusers:readGet user-client membership details
get-subordinatesemployees:read or users:readGet employees reporting to a manager (direct reports and/or all descendants)

Example — Get employees:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-employees",
    "is_active": true,
    "include_terminated": false,
    "limit": 100,
    "offset": 0
  }'

Example — Get subordinates (reporting hierarchy):

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-subordinates",
    "user_id": 88,
    "include_descendants": true,
    "include_self": true
  }'

get-subordinates parameters

ParameterTypeRequiredDescription
employee_idnumberNo*Employee ID of the manager to get reports for
user_idnumberNo*User ID of the manager (resolved to employee_id if not provided)
include_descendantsbooleanNoInclude all descendants in the reporting tree, not just direct reports (default: false)
include_selfbooleanNoInclude the manager themselves in the results (default: false)

* Either employee_id or user_id is required.

The response includes each employee's depth (0 = self, 1 = direct report, 2 = report of report, etc.) and a scope object with employee_ids and user_ids arrays for easy use in downstream queries.

Work Items

ActionRequired ScopeDescription
get-work-itemwork_items:readGet a specific work item by ID
list-work-itemswork_items:readList work items with filters
get-work-item-relationshipswork_items:readGet relationships for a work item
get-work-item-attachmentswork_items:readGet attachments for a work item
get-work-item-commentswork_items:readGet comments for a work item
get-work-item-time-entrieswork_items:readGet time entries for a work item
create-work-itemwork_items:writeCreate a new work item (job, task, ticket, etc.)
update-work-itemwork_items:writeUpdate an existing work item
close-work-itemwork_items:writeMark a work item as completed/closed/resolved/cancelled
delete-work-itemwork_items:write or work_items:deleteSoft-delete a work item
create-appointmentappointments:write or work_items:writeCreate a new appointment with scheduled start/end times
create-commentcomments:write or work_items:writeAdd a comment to a work item
get-employee-due-taskswork_items:read or employees:readGet tasks due today (and optionally overdue) for a user
get-employee-overdue-taskswork_items:read or employees:readGet overdue tasks for a user
create-managed-taskwork_items:writeCreate a standalone managed task assigned to one or more users
add-work-item-to-managed-taskwork_items:writeAdd any existing work item to a user's managed task list

Example — Create a work item:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create-work-item",
    "item_type": "job",
    "title": "Install new equipment",
    "description": "Install and configure new server rack",
    "module_context": "service-operations",
    "status": "open",
    "priority": "high",
    "contact_id": 123,
    "contact_name": "Acme Corporation",
    "contact_email": "[email protected]",
    "contact_phone": "+27123456789",
    "location_id": 456,
    "location_name": "Main Office",
    "location_address": "123 Main Street, Johannesburg, 2000",
    "contact_person_id": 789,
    "contact_person": "Jane Doe",
    "assigned_to": 150,
    "assigned_users": [150, 151],
    "scheduled_start": "2026-08-01T08:00:00Z",
    "scheduled_end": "2026-08-01T12:00:00Z",
    "due_date": "2026-08-01",
    "estimated_hours": 4,
    "tags": ["urgent", "installation"],
    "custom_fields": {
      "safety_requirements": "Hard hat required",
      "equipment_required": "Drill, safety gear"
    },
    "notes": "Ensure power is isolated before starting"
  }'

create-work-item parameters

ParameterTypeRequiredDescription
item_typestringYesjob, task, ticket, project, milestone
titlestringYesWork item title
descriptionstringNoWork item description
module_contextstringNoWorkflow template key (defaults to service-operations for jobs)
statusstringNoInitial status (defaults vary by item_type)
prioritystringNolow, medium, high, urgent
contact_idnumberNoCustomer/contact ID
contact_namestringNoContact display name
contact_emailstringNoContact email
contact_phonestringNoContact phone
location_idnumberNoContact location ID
location_namestringNoLocation name
location_addressstringNoLocation address
location_coordinatesobjectNo{ lat: number, lng: number }
contact_person_idnumberNoSite contact person ID
contact_personstringNoSite contact person name
assigned_tonumberNoPrimary assignee user ID
assigned_teamstringNoTeam UUID
assigned_usersnumber[]NoMultiple assignee user IDs
assigned_contractorsnumber[]NoContractor contact IDs
scheduled_startstringNoISO 8601 datetime
scheduled_endstringNoISO 8601 datetime
start_datestringNoISO 8601 datetime
due_datestringNoISO 8601 datetime
estimated_hoursnumberNoEstimated effort in hours
parent_idstringNoParent work item UUID
project_idstringNoProject work item UUID (creates child_of relationship)
tagsstring[]NoArray of tag strings
custom_fieldsobjectNoArbitrary JSON object for custom data
notesstringNoAdditional notes

Example — Update a work item:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "update-work-item",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "title": "Updated title — urgent repair needed",
    "status": "in_progress",
    "priority": "urgent",
    "assigned_to": 150,
    "assigned_users": [150, 151],
    "due_date": "2026-08-05",
    "tags": ["urgent", "repair"],
    "custom_fields": {
      "safety_requirements": "Hard hat and safety vest required"
    }
  }'

update-work-item parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the work item to update
titlestringNoUpdated title
descriptionstringNoUpdated description
item_subtypestringNoUpdated subtype
module_contextstringNoUpdated module context
statusstringNoUpdated status (e.g. open, in_progress, completed, cancelled)
prioritystringNolow, medium, high, urgent, critical
assigned_tonumberNoPrimary assignee user ID
assigned_teamstringNoTeam UUID
assigned_usersnumber[]NoReplaces existing user assignees
assigned_contractorsnumber[]NoReplaces existing contractor assignees
contact_idnumberNoContact ID
contact_namestringNoContact name
contact_emailstringNoContact email
contact_phonestringNoContact phone
location_idnumberNoContact location ID
location_namestringNoLocation name
location_addressstringNoLocation address
location_coordinatesobjectNo{ lat: number, lng: number }
contact_person_idnumberNoContact person ID
contact_personstringNoContact person name
reporter_idnumberNoReporter user ID
reporter_namestringNoReporter name
reporter_emailstringNoReporter email
reporter_phonestringNoReporter phone
start_datestringNoISO 8601 datetime
due_datestringNoISO 8601 datetime
scheduled_startstringNoISO 8601 datetime
scheduled_endstringNoISO 8601 datetime
estimated_hoursnumberNoEstimated effort in hours
tagsstring[]NoUpdated tags array
custom_fieldsobjectNoUpdated custom fields object
notesstringNoUpdated notes

Example — Delete a work item (soft delete):

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "delete-work-item",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000"
  }'

Soft delete behaviour

Deleting a work item sets deleted_at and deleted_by on the record — the item is not hard-deleted from the database. Child items (appointments, tasks linked via child_of relationships) are cascade-soft-deleted as well. The operation is idempotent: deleting an already-deleted item returns success.

delete-work-item parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the work item to soft-delete

Example — Close a work item:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "close-work-item",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "closure_status": "completed",
    "completion_note": "Work verified by client"
  }'

close-work-item parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the work item to close
closure_statusstringNocompleted (default), closed, done, resolved, cancelled, canceled
completion_notestringNoOptional note stored in the activity log

Managed Tasks

Managed tasks are work items with item_type: "task" that appear in a user's "Managed Tasks" list. They can be standalone tasks or linked to other work items (jobs, invoices, appointments) via work_item_relationships. The following actions let AI agents and external integrations create, query, and assign managed tasks without requiring WhatsApp or manual UI interaction.

Example — Create a standalone managed task:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create-managed-task",
    "title": "Follow up with supplier",
    "description": "Confirm delivery date for order #1234",
    "priority": "high",
    "due_date": "2026-08-25T17:00:00Z",
    "assigned_to": 243
  }'

create-managed-task parameters

ParameterTypeRequiredDescription
titlestringYesTask title
descriptionstringNoTask description
prioritystringNolow, medium, high, urgent (default: medium)
due_datestringNoDue date (ISO 8601)
assigned_tonumberNoPrimary assignee user ID (also added to work_item_assignees)
assigned_usersnumber[]NoMultiple assignee user IDs (first user becomes assigned_to)
parent_idstringNoUUID of a parent work item to link this task to (creates a child_of relationship)
module_contextstringNoModule context (default: total-operations)
tagsstring[]NoArray of tags
custom_fieldsobjectNoCustom field key-value pairs
notesstringNoAdditional notes

Example — Add an existing work item to a user's managed task list:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "add-work-item-to-managed-task",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "target_user_id": 243,
    "title": "Follow up on job",
    "priority": "high",
    "due_date": "2026-08-26T17:00:00Z"
  }'

This creates a task linked to the source work item via a child_of relationship in work_item_relationships, with reference metadata stored in custom_fields. If a managed task already exists for this work item + user, the existing task is returned with already_existed: true (idempotent).

add-work-item-to-managed-task parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the source work item to add to managed tasks
target_user_idnumberNoUser ID to assign the managed task to (defaults to the API key owner)
titlestringNoOverride task title (defaults to source work item title)
descriptionstringNoOverride task description (defaults to source work item description)
prioritystringNolow, medium, high, urgent (default: medium)
due_datestringNoDue date for the managed task (ISO 8601)
reference_urlstringNoOptional deep link URL to the source item
context_dataobjectNoAdditional metadata to store in custom_fields

Example — Get an employee's due tasks:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-employee-due-tasks",
    "user_id": 243,
    "include_overdue": true,
    "limit": 50
  }'

Returns tasks/subtasks assigned to the user (via assigned_to or work_item_assignees) that are due today or overdue, excluding terminal statuses. Results are sorted by due date (ascending) then priority (urgent first).

get-employee-due-tasks parameters

ParameterTypeRequiredDescription
user_idnumberYesUser ID to get due tasks for
include_overduebooleanNoInclude overdue tasks in results (default: true)
limitnumberNoResults per page (max 500, default 200)
offsetnumberNoPagination offset (default 0)

Example — Get an employee's overdue tasks:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-employee-overdue-tasks",
    "user_id": 243,
    "limit": 50
  }'

Returns only overdue tasks (due_date < today) for the user, excluding terminal statuses. Same sorting as get-employee-due-tasks.

get-employee-overdue-tasks parameters

ParameterTypeRequiredDescription
user_idnumberYesUser ID to get overdue tasks for
limitnumberNoResults per page (max 500, default 200)
offsetnumberNoPagination offset (default 0)

Typical AI agent workflow for managed tasks

A common pattern for an AI operations agent:

  1. Discover subordinatesget-subordinates with include_descendants: true to get all user_ids in the manager's reporting scope
  2. Check due/overdue tasksget-employee-due-tasks and get-employee-overdue-tasks for each user
  3. Create new taskscreate-managed-task to assign work to a specific employee
  4. Link existing work itemsadd-work-item-to-managed-task to add a job/invoice/appointment to someone's task list
  5. Close completed tasksclose-work-item to mark tasks as completed

Example — Create an appointment:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create-appointment",
    "title": "Site inspection",
    "scheduled_start": "2026-08-01T09:00:00Z",
    "scheduled_end": "2026-08-01T11:00:00Z",
    "contact_name": "John Smith",
    "location_name": "Client Office"
  }'

Example — Add a comment:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create-comment",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "comment_text": "Work completed and verified by client"
  }'

Example — Get a work item:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-work-item",
    "work_item_id": "YOUR_WORK_ITEM_UUID",
    "include": ["relationships", "attachments", "comments", "time_entries"]
  }'

Time & Attendance

ActionRequired ScopeDescription
get-attendance-logsattendance:readGet attendance clock in/out records
get-shiftsshifts:readGet shift templates and assignments
get-rosterroster:readGet shift roster entries
get-locationslocations:readGet locations and geofence identifiers
get-timesheetstimesheets:readGet timesheet records
get-overtimeovertime:readGet overtime records

Example — Get attendance logs:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "get-attendance-logs",
    "start_date": "2026-07-01",
    "end_date": "2026-07-31",
    "employee_id": 100,
    "limit": 500,
    "offset": 0
  }'

Finance

ActionRequired ScopeDescription
get-invoicesinvoices:readList invoices with filters
get-invoiceinvoices:readGet a specific invoice by ID
get-billsbills:readList bills with filters
get-paymentspayments:readList payment records
generate-finance-document-pdfinvoices:read or bills:read or quotes:readGenerate a PDF for any finance document (invoice, quote, credit note, purchase order, etc.)
convert-finance-documentinvoices:write or bills:write or quotes:writeConvert one finance document type to another (e.g. quote → invoice)

generate-finance-document-pdf parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the finance document work item
doc_typestringNoDocument type key (e.g. invoice, quote, credit_note). Inferred from the work item if omitted
formatstringNoResponse format: raw (binary PDF, default) or base64 (JSON with base64-encoded PDF)

Example — Generate a finance document PDF:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "generate-finance-document-pdf",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "doc_type": "invoice",
    "format": "raw"
  }'

The response is a raw binary PDF when format=raw (default), or a JSON object with a base64 field when format=base64.

convert-finance-document parameters

ParameterTypeRequiredDescription
work_item_idstringYesUUID of the source finance document
source_doc_typestringNoSource document type key (inferred from work item if omitted)
target_doc_typestringYesTarget document type key (e.g. invoice, purchase_order)

Example — Convert a quote to an invoice:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "convert-finance-document",
    "work_item_id": "550e8400-e29b-41d4-a716-446655440000",
    "source_doc_type": "quote",
    "target_doc_type": "invoice"
  }'

Finance Tier Restrictions

Finance document types are gated by subscription tier

The finance document types available to a client are determined by their Total Finance subscription tier. Both the API and the UI enforce these restrictions:

  • Server-side: The generate-finance-document-pdf and convert-finance-document actions return 403 Forbidden if the requested document type is not allowed by the client's tier.
  • Client-side: The Public Data API Manager UI, Outbound Webhook Modal, and API Key Modal all filter finance document actions, events, and scopes based on the client's tier.

The following finance document types are subject to tier restrictions:

Document Type KeyTypical Scope
invoiceinvoices:read / invoices:write
quotequotes:read / quotes:write
credit_noteinvoices:read / invoices:write
purchase_orderbills:read / bills:write
delivery_noteinvoices:read
proformainvoices:read
sales_orderquotes:read
supplier_invoicebills:read
supplier_quotebills:read
expensebills:read

Contact your account manager to upgrade your Total Finance tier for access to additional document types.

Contacts

ActionRequired ScopeDescription
list-contactscontacts:readList customer and supplier contacts
get-contactcontacts:readGet a specific contact by ID
search-contactscontacts:readSearch contacts by name, email, phone
list-contact-peoplecontacts:readList contact people with filters
search-contact-peoplecontacts:readQuick search contact people by phone, email, or name
list-contact-locationscontacts:readList delivery/service locations for a contact
list-contact-documentscontacts:readList documents linked to a contact

Threads & Messaging

ActionRequired ScopeDescription
list-threadsthreads:readList client threads with filters
get-job-threadthreads:readGet a job thread by job ID
get-team-threadthreads:readGet a shared team thread by team ID or solution key
get-thread-messagesthreads:readGet messages from a thread
send-thread-messagethreads:send_message or threads:writeSend a message to a job or team thread

Fleet

ActionRequired ScopeDescription
get-vehiclesvehicles:readList vehicles with details
get-vehicle-locationtracking:readGet latest GPS location for a vehicle

Reports & PDFs

ActionRequired ScopeDescription
generate-job-card-pdfwork_items:readGenerate a job card PDF for a work item
generate-attendance-card-pdfwork_items:readGenerate an attendance card PDF for an appointment
generate-finance-document-pdfinvoices:read or bills:read or quotes:readGenerate a PDF for a finance document (see Finance section for details)
get-work-item-analyticswork_items:readGet aggregated work item analytics
get-work-item-slawork_items:readGet SLA status for work items

Recurring Jobs

ActionRequired ScopeDescription
create-recurring-jobrecurring:write or work_items:writeCreate a recurring job schedule that auto-generates work items
update-recurring-jobrecurring:write or work_items:writeUpdate an existing recurring job schedule
list-recurring-jobsrecurring:write or work_items:readList recurring job schedules with optional filters
get-recurring-jobrecurring:write or work_items:readGet a single recurring job schedule with generation history
pause-recurring-jobrecurring:write or work_items:writePause a recurring job schedule
resume-recurring-jobrecurring:write or work_items:writeResume a paused recurring job schedule
generate-recurring-jobrecurring:write or work_items:writeManually generate a job from a recurring schedule

Example — Create a recurring job:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "create-recurring-job",
    "name": "Weekly Site Inspection",
    "description": "Auto-generated weekly site inspection job",
    "contact_id": 42,
    "priority": "high",
    "assigned_to": 15,
    "assigned_users": [15, 22],
    "frequency": "weekly",
    "day_of_week": 1,
    "generate_time": "08:00:00",
    "auto_assign": true,
    "auto_approve": true,
    "create_appointments": true,
    "due_days_after_creation": 3,
    "safety_requirements": "Hard hat and safety vest required",
    "equipment_required": "Inspection camera, multimeter"
  }'

Example — Generate a job from a recurring schedule:

curl -X POST https://totalaccess.co.za/api/v1/public/data \
  -H "X-API-Key: ta_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "action": "generate-recurring-job",
    "id": "550e8400-e29b-41d4-a716-446655440000"
  }'

Response format

{
  "success": true,
  "data": [ ... ],
  "meta": {
    "action": "get-employees",
    "count": 45,
    "limit": 100,
    "offset": 0,
    "total": 45
  }
}

Error responses

{
  "success": false,
  "error": {
    "code": "FORBIDDEN",
    "message": "API key does not have required scope: employees:read"
  }
}
Error CodeHTTP StatusDescription
UNAUTHORIZED401Missing, invalid, or expired API key
FORBIDDEN403API key lacks required scope or IP not allowed
TIER_RESTRICTED403Finance document type not allowed by client's subscription tier
NOT_FOUND404Requested resource not found
BAD_REQUEST400Invalid action or missing required parameters
RATE_LIMITED429Rate limit exceeded

Rate limiting

The Public Data API shares the same rate limits as the REST API. See Introduction for tier details.

Rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1700000000

On this page