> ## Documentation Index
> Fetch the complete documentation index at: https://developers.novala.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Inspections API — Create and Retrieve Field Inspections

> List inspections with filters, create new inspection records linked to equipment and checklists, and retrieve full detail including findings and team members.

Inspections are field records created when a technician inspects a piece of equipment at a site using a checklist template. Each inspection tracks its status through a review workflow and accumulates findings — discrete observations with severity ratings.

<Note>
  The inspections API requires the `calso` module to be enabled for your tenant. Requests made without the module active will return `403 Forbidden`.
</Note>

## Inspection statuses

An inspection moves through the following lifecycle:

| Status      | Meaning                                       |
| ----------- | --------------------------------------------- |
| `draft`     | Created, not yet submitted by the technician. |
| `submitted` | Submitted by the technician for review.       |
| `in_review` | Under review by a coordinator or manager.     |
| `approved`  | Inspection approved.                          |
| `delivered` | Report delivered to the customer.             |
| `rejected`  | Returned to the technician for corrections.   |

## Finding severities

| Severity   | Meaning                                                              |
| ---------- | -------------------------------------------------------------------- |
| `imminent` | Requires immediate action; equipment should be taken out of service. |
| `serious`  | Significant deficiency requiring prompt repair.                      |
| `minor`    | Low-risk observation; should be addressed in routine maintenance.    |

***

## List inspections

`GET /api/inspections`

Returns a paginated list of inspections for the authenticated tenant.

### Query parameters

<ParamField query="status" type="string">
  Filter by inspection status. One of: `draft`, `submitted`, `in_review`, `approved`, `delivered`, `rejected`.
</ParamField>

<ParamField query="technicianId" type="string">
  Filter by technician UUID. Returns inspections where the user is the lead technician or a team member.
</ParamField>

<ParamField query="companyId" type="string">
  Filter by company (customer) UUID.
</ParamField>

<ParamField query="search" type="string">
  Full-text search across company name, equipment type name, technician name, and serial number.
</ParamField>

<ParamField query="page" type="integer" default="1">
  1-based page index.
</ParamField>

<ParamField query="limit" type="integer" default="25">
  Results per page. Maximum `100`.
</ParamField>

### Response

```json theme={null}
{
  "data": [
    {
      "inspection": {
        "id": "e1b234cd-0001-4aaa-bbbb-ccccddddeeee",
        "status": "submitted",
        "inspectionDate": "2024-07-15",
        "overallResult": "conditional",
        "notes": "Customer was on-site during inspection.",
        "createdAt": "2024-07-15T08:00:00Z"
      },
      "equipment": {
        "id": "eq-uuid-001",
        "manufacturer": "Genie",
        "model": "S-65",
        "serialNumber": "GS65-001234"
      },
      "equipmentType": {
        "id": "type-uuid-001",
        "name": "Boom Lift",
        "category": "aerial"
      },
      "site": {
        "id": "site-uuid-001",
        "name": "Main Warehouse",
        "address": "123 Industrial Blvd",
        "city": "Austin",
        "state": "TX"
      },
      "customer": {
        "id": "cust-uuid-001",
        "name": "Acme Corp"
      },
      "technician": {
        "id": "user-uuid-001",
        "name": "Jordan Smith"
      },
      "findingCount": 3
    }
  ],
  "total": 47,
  "page": 1,
  "pageSize": 25
}
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://app.novala.ai/api/inspections?status=submitted" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://app.novala.ai/api/inspections?status=submitted',
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );
  const { data, total } = await response.json();
  ```
</CodeGroup>

***

## Get an inspection

`GET /api/inspections/{id}`

Retrieves a full inspection record including equipment details, checklist template, findings with photos, and the technician team.

### Path parameters

<ParamField path="id" type="string" required>
  UUID of the inspection.
</ParamField>

### Response fields

<ResponseField name="inspection" type="object">
  <Expandable title="Inspection object">
    <ResponseField name="id" type="string">UUID.</ResponseField>
    <ResponseField name="status" type="string">Current inspection status.</ResponseField>
    <ResponseField name="inspectionDate" type="string">Date of inspection (`YYYY-MM-DD`).</ResponseField>
    <ResponseField name="overallResult" type="string | null">One of `pass`, `fail`, `conditional`. Set during review.</ResponseField>
    <ResponseField name="responses" type="array">Checklist item responses recorded by the technician.</ResponseField>
    <ResponseField name="notes" type="string | null">Inspector notes.</ResponseField>
    <ResponseField name="customerSignatureUrl" type="string | null">URL of the customer's signature image.</ResponseField>
    <ResponseField name="rejectionReason" type="string | null">Reason for rejection, if status is `rejected`.</ResponseField>
    <ResponseField name="createdAt" type="string">ISO 8601 creation timestamp.</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO 8601 last-updated timestamp.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="equipment" type="object">
  Equipment with `id`, `manufacturer`, `model`, `serialNumber`, `ratedCapacity`, `status`, `nameplatePhotoUrl`, `locationLabel`.
</ResponseField>

<ResponseField name="equipmentType" type="object">
  Equipment type with `id`, `name`, `category`, `oshaStandard`.
</ResponseField>

<ResponseField name="site" type="object">
  Site with `id`, `name`, `address`, `city`, `state`.
</ResponseField>

<ResponseField name="customer" type="object">
  Company with `id` and `name`.
</ResponseField>

<ResponseField name="technician" type="object">
  Lead technician with `id`, `name`, `email`.
</ResponseField>

<ResponseField name="template" type="object">
  Checklist template with `id`, `name`, and `sections`.
</ResponseField>

<ResponseField name="findings" type="array">
  <Expandable title="Finding object">
    <ResponseField name="id" type="string">UUID of the finding.</ResponseField>
    <ResponseField name="severity" type="string">One of `imminent`, `serious`, `minor`.</ResponseField>
    <ResponseField name="description" type="string">Description of the deficiency.</ResponseField>
    <ResponseField name="recommendation" type="string | null">Recommended corrective action.</ResponseField>
    <ResponseField name="oshaReference" type="string | null">Applicable OSHA standard reference.</ResponseField>
    <ResponseField name="quoteStatus" type="string">Repair quote status: `unquoted`, `quoted`, `accepted`, `declined`, `completed`.</ResponseField>
    <ResponseField name="photos" type="array">Array of photo objects with `id`, `photoUrl`, `caption`, `photoType`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="teamMembers" type="array">
  Array of team members with `id`, `technicianId`, `role` (`lead` or `member`), and `name`.
</ResponseField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://app.novala.ai/api/inspections/e1b234cd-0001-4aaa-bbbb-ccccddddeeee \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://app.novala.ai/api/inspections/e1b234cd-0001-4aaa-bbbb-ccccddddeeee',
    { headers: { 'Authorization': `Bearer ${apiKey}` } }
  );
  const { inspection, findings, teamMembers } = await response.json();
  ```
</CodeGroup>

***

## Create an inspection

`POST /api/inspections`

Creates a new inspection in `draft` status. The inspection is assigned to the authenticated user unless a `technicianId` (or `technicianIds`) is specified, which requires the **Admin** or **Coordinator** role.

### Request body

<ParamField body="equipmentId" type="string" required>
  UUID of the equipment to inspect.
</ParamField>

<ParamField body="siteId" type="string" required>
  UUID of the site where the inspection takes place.
</ParamField>

<ParamField body="checklistTemplateId" type="string" required>
  UUID of the checklist template to use. Must belong to your tenant.
</ParamField>

<ParamField body="inspectionDate" type="string" required>
  Date of inspection in `YYYY-MM-DD` format.
</ParamField>

<ParamField body="notes" type="string">
  Pre-inspection notes.
</ParamField>

<ParamField body="technicianId" type="string">
  UUID of the lead technician. Only honored when the caller has the `system_admin` or `field_coordinator` role.
</ParamField>

<ParamField body="technicianIds" type="array">
  Array of technician UUIDs. The first element is the lead; subsequent elements are team members. Takes precedence over `technicianId`.
</ParamField>

### Response

Returns `201 Created` with the new inspection object (without nested relations). Initial status is always `draft`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://app.novala.ai/api/inspections \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "equipmentId": "eq-uuid-001",
      "siteId": "site-uuid-001",
      "checklistTemplateId": "tmpl-uuid-001",
      "inspectionDate": "2024-08-20",
      "technicianIds": ["user-uuid-001", "user-uuid-002"]
    }'
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://app.novala.ai/api/inspections', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      equipmentId: 'eq-uuid-001',
      siteId: 'site-uuid-001',
      checklistTemplateId: 'tmpl-uuid-001',
      inspectionDate: '2024-08-20',
      technicianIds: ['user-uuid-001', 'user-uuid-002'],
    }),
  });
  const inspection = await response.json(); // 201 Created
  ```
</CodeGroup>
