Audits

Create, run, and complete supplier site audits — sections, checklist responses, photos and scoring — via secure, RESTful API endpoints.

Overview

The Audits API mirrors the Food-Trace mobile supplier audit workflow: create an audit against a supplier, fetch its eight checklist sections and their live traffic-light progress, save Pass / Fail / Flag / N/A answers item by item, attach photos, and finalise the audit to calculate a score. Every route below is a thin wrapper over the same stored procedures the mobile app already uses in production — no new business logic, just an HTTP surface for it.

LIVE https://developer.traceallglobal.com/api/v1
Key Features
  • Live traffic-light section progress
  • Auto-save per checklist item
  • Photo upload & delete per item
  • Automatic scoring on completion

API Endpoints

GET
/audits
List audits
POST
/audits
Create a new audit
GET
/audits/{auditid}/sections
Section tiles & progress
PUT
/audits/{auditid}/items/{itemid}/response
Save a checklist answer
POST
/audits/{auditid}/items/{itemid}/photos
Upload a checklist photo
DELETE
/audits/{auditid}/photos/{docid}
Delete an audit photo
POST
/audits/{auditid}/complete
Finalise & score the audit

Returns the audit dashboard list — supplier, date, status, score percentage and traffic-light colour for each audit. Pass userid to restrict results to audits carried out by a specific auditor; omit it (or pass 0) to return every audit. Requires API permission level 1 (Basic) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication. Handles JWT validation automatically.

userid (query, integer, Optional) - Filter to audits carried out by this user. Omit for all audits.

Test this endpoint

Response Examples

{
  "success": true,
  "data": [
    {
      "auditid": 42,
      "companyid": 12,
      "companyname": "Acme Foods Ltd",
      "auditdate": "2026-07-20",
      "statusid": 2,
      "score_pct": null,
      "traffic_light": "amber"
    }
  ]
}
{
  "success": false,
  "error": "Missing API key"
}

Code Examples

curl -X GET "https://developer.traceallglobal.com/api/v1/audits?userid=14" \
  -H "X-API-Key: YOUR_API_KEY"
fetch('https://developer.traceallglobal.com/api/v1/audits?userid=14', {
  headers: { 'X-API-Key': 'YOUR_API_KEY' }
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits"
headers = {"X-API-Key": "YOUR_API_KEY"}
params = {"userid": 14}

response = requests.get(url, headers=headers, params=params)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits?userid=14';
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: YOUR_API_KEY'],
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Creates a new audit record for a supplier. Note there is no siteid parameter on this endpoint — the underlying createSupplierAudit procedure does not accept one, so a caller that needs to record which site was audited must patch it afterwards through the desktop editSiteAudit flow. Requires API permission level 2 (Editor) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

Content-Type (header, string, Required) - Must be application/json.

Body (JSON) (object, Required):

  • companyid (integer, Required) — supplier company being audited
  • userid (integer, Required) — user carrying out the audit
  • audit_date (string, Required) — YYYY-MM-DD
  • audit_reason (string, Optional)
Sample JSON:
{
  "companyid": 12,
  "userid": 14,
  "audit_date": "2026-07-28",
  "audit_reason": "Annual scheduled audit"
}
Test this endpoint

Response Examples

{
  "success": true,
  "data": {
    "message": "Audit created successfully",
    "auditid": 42
  }
}
{
  "success": false,
  "error": "Missing required field: companyid"
}

Code Examples

curl -X POST "https://developer.traceallglobal.com/api/v1/audits" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companyid": 12,
    "userid": 14,
    "audit_date": "2026-07-28",
    "audit_reason": "Annual scheduled audit"
  }'
fetch('https://developer.traceallglobal.com/api/v1/audits', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    companyid: 12,
    userid: 14,
    audit_date: '2026-07-28',
    audit_reason: 'Annual scheduled audit'
  })
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits"
headers = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
data = {
    "companyid": 12,
    "userid": 14,
    "audit_date": "2026-07-28",
    "audit_reason": "Annual scheduled audit"
}

response = requests.post(url, headers=headers, json=data)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits';
$headers = ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'];
$data = [
    'companyid'    => 12,
    'userid'       => 14,
    'audit_date'   => '2026-07-28',
    'audit_reason' => 'Annual scheduled audit',
];

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_POSTFIELDS     => json_encode($data),
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Returns the eight checklist sections for an audit, each with total/answered item counts and a traffic-light colour (grey, amber, red, green) reflecting progress and any critical fails or flags. Requires API permission level 1 (Basic) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

auditid (path, integer, Required) - The audit to fetch sections for.

Test this endpoint

Response Examples

{
  "success": true,
  "data": [
    {
      "sectionid": 1,
      "section_name": "Documentation and Records",
      "icon_class": "fi fi-rr-document",
      "sort_order": 1,
      "total_items": 6,
      "answered_items": 6,
      "traffic_light": "green"
    },
    {
      "sectionid": 3,
      "section_name": "Hygiene and Cleaning",
      "icon_class": "fi fi-rr-soap",
      "sort_order": 3,
      "total_items": 6,
      "answered_items": 2,
      "traffic_light": "amber"
    }
  ]
}
{
  "success": false,
  "error": "Missing or invalid audit id (auditid) parameter"
}

Code Examples

curl -X GET "https://developer.traceallglobal.com/api/v1/audits/42/sections" \
  -H "X-API-Key: YOUR_API_KEY"
fetch('https://developer.traceallglobal.com/api/v1/audits/42/sections', {
  headers: { 'X-API-Key': 'YOUR_API_KEY' }
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits/42/sections"
headers = {"X-API-Key": "YOUR_API_KEY"}

response = requests.get(url, headers=headers)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits/42/sections';
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: YOUR_API_KEY'],
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Saves (or updates) the answer for one checklist item. Called once per tap in the mobile app — there is no separate submit step. Returns the updated stats for the item's section so a UI can refresh its traffic-light colour immediately. Requires API permission level 2 (Editor) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

Content-Type (header, string, Required) - Must be application/json.

auditid (path, integer, Required) - The audit being answered.

itemid (path, integer, Required) - The checklist item being answered.

Body (JSON) (object, Required):

  • result (string, Required) — one of pass, fail, flag, na
  • notes (string, Optional)
  • userid (integer, Optional) — defaults to the authenticated API user
Sample JSON:
{
  "result": "fail",
  "notes": "Chiller running at 9°C, above legal limit",
  "userid": 14
}
Test this endpoint

Response Examples

{
  "success": true,
  "data": {
    "sectionid": 4,
    "total_items": 5,
    "answered_items": 3,
    "traffic_light": "red"
  }
}
{
  "success": false,
  "error": "Invalid result value — must be one of: pass, fail, flag, na"
}

Code Examples

curl -X PUT "https://developer.traceallglobal.com/api/v1/audits/42/items/41/response" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "result": "fail",
    "notes": "Chiller running at 9C, above legal limit",
    "userid": 14
  }'

# If your HTTP client cannot send PUT, use the override header instead:
curl -X POST "https://developer.traceallglobal.com/api/v1/audits/42/items/41/response" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-HTTP-Method-Override: PUT" \
  -d '{"result": "fail", "notes": "...", "userid": 14}'
fetch('https://developer.traceallglobal.com/api/v1/audits/42/items/41/response', {
  method: 'PUT',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ result: 'fail', notes: 'Chiller running at 9C', userid: 14 })
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits/42/items/41/response"
headers = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
data = {"result": "fail", "notes": "Chiller running at 9C", "userid": 14}

response = requests.put(url, headers=headers, json=data)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits/42/items/41/response';
$headers = ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'];
$data = ['result' => 'fail', 'notes' => 'Chiller running at 9C', 'userid' => 14];

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'PUT',
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_POSTFIELDS     => json_encode($data),
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Uploads a photo (JPEG, PNG, GIF or WebP, max 10 MB) attached to one checklist item. The API owns file storage for audit photos — the returned url is a fully-qualified, publicly addressable link, safe to use directly as an <img src> regardless of which app renders it. Requires API permission level 2 (Editor) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

Content-Type (header, string, Required) - Must be multipart/form-data.

auditid (path, integer, Required)

itemid (path, integer, Required)

Body (multipart/form-data) (Required):

  • file (file, Required) — the image file
  • userid (integer, Optional) — defaults to the authenticated API user
Test this endpoint

Response Examples

{
  "success": true,
  "data": {
    "docid": 187,
    "url": "https://developer.traceallglobal.com/uploads/audit-photos/42/42_41_2026-07-28_14-05-10_66abf1.jpg",
    "filename": "chiller.jpg"
  }
}
{
  "success": false,
  "error": "Only image files are allowed (JPEG, PNG, GIF, WebP)"
}

Code Examples

curl -X POST "https://developer.traceallglobal.com/api/v1/audits/42/items/41/photos" \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@/path/to/chiller.jpg" \
  -F "userid=14"
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('userid', 14);

fetch('https://developer.traceallglobal.com/api/v1/audits/42/items/41/photos', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY' },
  body: formData
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits/42/items/41/photos"
headers = {"X-API-Key": "YOUR_API_KEY"}
files = {"file": open("chiller.jpg", "rb")}
data = {"userid": 14}

response = requests.post(url, headers=headers, files=files, data=data)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits/42/items/41/photos';
$data = [
    'file'   => new CURLFile('/path/to/chiller.jpg', 'image/jpeg', 'chiller.jpg'),
    'userid' => 14,
];

$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: YOUR_API_KEY'],
    CURLOPT_POSTFIELDS     => $data,
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Deletes one photo, scoped to the given auditid so callers can't delete a photo belonging to a different audit by guessing a docid. Requires API permission level 3 (Manager) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

auditid (path, integer, Required)

docid (path, integer, Required) - The photo's document ID, as returned by the upload endpoint.

Test this endpoint

Response Examples

{
  "success": true,
  "data": { "success": true }
}
{
  "success": false,
  "error": "Photo not found for this audit"
}

Code Examples

curl -X DELETE "https://developer.traceallglobal.com/api/v1/audits/42/photos/187" \
  -H "X-API-Key: YOUR_API_KEY"
fetch('https://developer.traceallglobal.com/api/v1/audits/42/photos/187', {
  method: 'DELETE',
  headers: { 'X-API-Key': 'YOUR_API_KEY' }
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits/42/photos/187"
headers = {"X-API-Key": "YOUR_API_KEY"}

response = requests.delete(url, headers=headers)
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits/42/photos/187';
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['X-API-Key: YOUR_API_KEY'],
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>

Finalises an audit — validates that answers exist, calculates the final score percentage, and sets the audit to complete. Fails with 422 if the audit isn't ready to be completed (e.g. required items still unanswered). Requires API permission level 2 (Editor) or higher.

Parameters

X-API-Key (header, string, Required) - Your API key for authentication.

auditid (path, integer, Required)

Body (JSON) (object, Optional) - userid (integer, Optional) — defaults to the authenticated API user.

Test this endpoint

Response Examples

{
  "success": true,
  "data": {
    "success": true,
    "score_pct": 92.5,
    "message": "Audit completed successfully."
  }
}
{
  "success": false,
  "error": "Could not complete audit"
}

Code Examples

curl -X POST "https://developer.traceallglobal.com/api/v1/audits/42/complete" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"userid": 14}'
fetch('https://developer.traceallglobal.com/api/v1/audits/42/complete', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({ userid: 14 })
})
.then(response => response.json())
.then(data => console.log(data));
import requests

url = "https://developer.traceallglobal.com/api/v1/audits/42/complete"
headers = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

response = requests.post(url, headers=headers, json={"userid": 14})
print(response.json())
<?php
$url = 'https://developer.traceallglobal.com/api/v1/audits/42/complete';
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: YOUR_API_KEY', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['userid' => 14]),
]);
$response = curl_exec($curl);
curl_close($curl);
print_r(json_decode($response, true));
?>