# REST APIs

## Overview

The system provides a Representational State Transfer (REST) API to work with key records.&#x20;

REST provides a consistent URI for access and manipulation of a specific data record. Under REST, a single URI represents a data record, and the HTTP verb controls the manipulation according to the following table:

<table><thead><tr><th width="162.81640625">Method</th><th width="238.1015625">Description</th><th>Example</th></tr></thead><tbody><tr><td>GET</td><td>Returns a collection of items based on a filter</td><td>GET /api/json/item?...</td></tr><tr><td>POST</td><td>Creates a new item</td><td>POST /api/json/item</td></tr><tr><td>GET</td><td>Returns a single item</td><td>GET /api/json/item/id/1</td></tr><tr><td>PUT</td><td>Updates a single item</td><td>PUT /api/json/item/id/1</td></tr></tbody></table>

### Collections

The Crisisworks REST API returns either returns a single object or a collection of objects, based on its invocation.

Collections contain the following JSON structure:

```json
{
    "models": {
        "1": { ... }
        "2": { ... }
        "3": { ... }
        "4": { ... }
        "5": { ... }
    },
    "count": 5,
    "total": "22608"
}
```

In the collection structure:

* `models` contains an array of individual model structures,
* `count` contains the number of returned objects, and
* `total` contains the total set (this will be different if you call the API with a `limit` and/or `offset` parameter to paginate the set).

### Records

Use the GET method and supply an `id` parameter to fetch a single record.

```http
GET https://{{host}}/api/json/item/id/1
Authorization: Bearer {{token}}
X-Site: {{site}}
```

Example:

```http
GET https://{{host}}/api/json/item/id/1
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}
```

```json
{
    "id": "1",
    "eventId": "234",
    "due": null,
    "isSensitive": false,
    "itemSchemaName": "default",
    "userId": "myuser",
    "status": "10",
    "templateName": null,
    "costEstimate": "10000.00",
    "type": "recoveryInfrastructure",
    "title": "Small Rd (ACCESS RURAL) ",
    "address": "Small Rd (ACCESS RURAL) ",
    "assetId": "72784",
    "assignee": 0,
    "_canEdit": true,
    "dateCreated": "2016-09-29T15:07:27+10:00",
    "dateUpdated": "2016-09-29T15:07:27+10:00",
    "isTemplate": false,
    "tags": "",
    "descriptionPhotos": [],
    "scopePhotos": [],
    "contractors": [],
    "description": null,
    "scope": null,
    "costActual": "0",
    "priority": "2",
    "riskLevel": null
}
```

{% hint style="info" %}
The contents of the record structure depends on the type of content being retrieved.
{% endhint %}

If the record does not exist or is not accessible, the following is returned.

```json
{
  "status": 404,
  "message": "Not found"
}
```

## Working with REST collections

### Fetching a collection of records

Fetching a collection of RESTful objects is achieved by calling its base URL without an identifier. e.g.

```http
GET https://{{host}}/api/json/item?{{filter}}
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}
```

The `{{filter}}` is a standard GET parameter list with the following parameters.

#### Specifying the register

For `item` collections you must specify the type of register:

```
registerId=contact
```

#### Filtering

Filters can be provided using CQL.

Like all GET requests, the values must be URL encoded.

For example, to filter the CQL query

```
is:active status:[requested,assigned]
```

Your filter will look like:

```
cql=is%3Aactive%20status%3A%5Brequested%2Cassigned%5D
```

{% hint style="info" %}
Your language will have its own way to URL Encode variables.
{% endhint %}

#### Ordering

Collections can be ordered by a limited number of columns, with the most common being `id`, `dateCreated` and `dateModified`.

```
orderBy=dateCreated&orderDirection=ASC
```

#### Pagination

Optional pagination is controlled via `limit` and `offset`.

```
limit=5&offset=50
```

Each result will return the count in the result, and the total records:

```json
{
  "models": [...],
  "count": 100,
  "total": "212",
}
```

Example: get results 50-55 of recoveryInfrastructure

```http
https://{{host}}/api/json/item?limit=5&offset=50&type=recoveryInfrastructure
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}
```

```json
{
    "models": {
        "10744": {
            ...
        },
        "10755": {
            ...
        },
        "10756": {
            ...
        },
        "10757": {
            ...
        },
        "10759": {
            ...
        }
    },
    "count": 5,
    "total": "312",
}
```

### Searching and filtering records

You can use CQL to search and filter your records.

* See our user guide for details
* A data dictionary exists for each register, and you will find the link in the UI under the search box.

A full example in CQL for Crisisworks might be this — the following returns active records in event 22 updated in the last 30 days:

```
is:active event:22 dateUpdated:>now-30d
```

{% hint style="info" %}
Like all GET parameters, you must encode these values using your language's URL Encode function.
{% endhint %}

To run CQL in the REST API, you must url encode it and use a parameter called `cql`.

```http
https://{{host}}/api/json/item?type=recoveryCase&cql=is%3Aactive+event%3A22+dateUpdated%3A%3Enow-30d'
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}
```

## Working with REST Records

### Submitting new records

New records can be submitted using POST.

* JSON Input follows the same structure as that returned from the GET API.
* The JSON response reflects the final values of the record after being saved.
* Possible error codes include 40x and 50x status codes. All have a human-readable message, and use http codes so you can follow that spec to know whether it's a temporary or permanent error.

```http
POST https://{{host}}/api/json/item
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}

{
    "title": "Test submission via API",
    "requestor": "Scott Davey",
    "registerId": "recoveryInfrastructure",
    "field...": "value..."
}
```

The API will respond with the saved data.

```json
{
    "id": 12345,
    "registerId": "recoveryInfrastructure",
    "title": "Test submission via API",
    "requestor": "Scott Davey",
    "field...": "value..."
}
```

The fields and values are defined in the module guide.

### Updating existing records

To update an existing record, use PUT or PATCH.

PUT and PATCH work similarly, where:

* PUT expecting a full record, while&#x20;
* PATCH expects a change-set.&#x20;

Tip: When using PUT, missing data will be treated as if the value is set to null, and this will overwrite existing values at the server.

Possible error codes include 40x and 50x codes, as usual.

```http
PUT https://{{host}}/api/json/item/id/123
Accept: application/json
Content-Type: application/json;charset=UTF-8
Authorization: Bearer {{token}}
X-Site: {{site}}

{
    "id": 123,
    "registerId": "recoveryInfrastructure",
    "title": "Test submission via API",
    "requestor": "Scott Davey",
    "field...": "value..."
}
```

The API will respond with the saved data.

```json
{
    "id": 123,
    "registerId": "recoveryInfrastructure",
    "title": "Test submission via API",
    "requestor": "Scott Davey",
    "field...": "value..."
}
```

### Deleting records

Records in Crisisworks cannot be deleted. Instead, set the status to an inactive status.

Consult the relevant module reference guide for more information.

## REST Commands

### Asset

The asset REST command searches and returns assets in Crisisworks.

To search:

```
GET /api/json/asset?{{parameters}}

```

To return a specific record by its ID:

```
GET /api/json/asset/id/{{id}}
```

#### GET Parameters

<table><thead><tr><th width="143.5234375">Key(s)</th><th>Type</th><th>Details</th></tr></thead><tbody><tr><td><code>limit</code></td><td>Number</td><td>When paginating, how many records to return</td></tr><tr><td><code>offset</code></td><td>Number</td><td>When paginating, which record to start from</td></tr><tr><td><code>id</code></td><td>Integer</td><td>Returns a record of a specific ID</td></tr><tr><td><code>fulltext</code></td><td>String</td><td>Returns records containing the supplied text, as analysed by the full-text search parser.</td></tr><tr><td><code>soundex</code></td><td>String</td><td>Returns records where the title sounds like the supplied string<br><br><br>Aliases: name</td></tr><tr><td><code>active</code></td><td>Boolean</td><td>Returns only active (or inactive) records based on supplied value</td></tr><tr><td><code>type</code></td><td>String</td><td>Returns records matching the given asset type. For a list of asset types, see the <strong>asset-type</strong> API command.</td></tr><tr><td><code>code</code></td><td>String</td><td>Returns records matching the given asset code</td></tr><tr><td><code>isImpacted</code></td><td>Boolean</td><td>Returns records that have an active register item record in Crisisworks</td></tr><tr><td><p><code>latitude</code></p><p>longitude<br>range</p></td><td>Number</td><td>Returns assets near the provided geospatial location.</td></tr></tbody></table>

#### **Example**

Return 1 matching asset.

```http
GET https://{{host}}/api/json/asset?limit=1
Authorization: Bearer {{token}}
X-Site: {{site}}
```

Result:

```json
{
    "models": {
        "1": {
            "id": "1",
            "name": "TP827623",
            "code": "100044818",
            "type": "Asset_Property",
            "friendlyType": "Property",
            "geo": {
                "points": [],
                "polygons": [
                    {
                        "points": [
                            {
                                "longitude": "144.01960063",
                                "latitude": "-37.67845485"
                            },
                            {
                                "longitude": "144.01926323",
                                "latitude": "-37.67851867"
                            },
                            {
                                "longitude": "144.01912979",
                                "latitude": "-37.67853825"
                            },
                            {
                                "longitude": "144.01899564",
                                "latitude": "-37.67855447"
                            }
                        ]
                    }
                ],
                "linestrings": []
            },
            "_distance": null,
            "style": "green",
            "_within": false,
            "_order": 1
        }
    },
    "count": 1,
    "total": "22608",
    "updated": "2016-08-03T00:33:44+00:00"
}
```

### Event

This command fetches available events, and allows updating.

#### Fetch Individual Event

**Example**

```http
GET /api/json/event/id/123
Authorization: Bearer {{token}}
X-Site: {{site}}
```

#### Search Events

**Example**

```http
GET /api/json/event
Authorization: Bearer {{token}}
X-Site: {{site}}
```

**Parameters**

| Keys              | Type             | Details                                                                      |
| ----------------- | ---------------- | ---------------------------------------------------------------------------- |
| `limit`           | Number           | When paginating, how many records to return                                  |
| `offset`          | Number           | When paginating, which record to start from                                  |
| `id`              | Number           | Search by ID                                                                 |
| `fulltext`        | String           | Set `fulltext_operator` to the desired operator if changing from the default |
| `status`          | String           | Search item                                                                  |
| `active`          | Boolean          | All active statuses                                                          |
| `startDateAfter`  | Date Time String |                                                                              |
| `startDateBefore` | Date Time String |                                                                              |
| `tag`             | String           | Search for events containing this tag                                        |
| `isTemplate`      | Boolean          |                                                                              |
| `isGlobal`        | Boolean          |                                                                              |

**Example: Fetch the most recent event**

Request:

```http
GET https://{{host}}/api/json/event?limit=1&order=id&orderDirection=DESC
Authorization: Bearer {{token}}
X-Site: {{site}}
```

Result:

```json
{
    "models": {
        "1021": {
            "id": "1021",
            "title": "Fire at Broadbeach",
            "description": "",
            "startDate": "2016-08-11T03:58:00+00:00",
            "endDate": null,
            "status": {
                "label": "Open",
                "value": 1,
                "style": "yellow"
            },
            "severity": "2",
            "participants": [
                {
                    "id": "2758",
                    "type": "position",
                    "name": "Archive Officer",
                    "positionId": "81"
                },
                {
                    "id": "2759",
                    "type": "user",
                    "name": "Pete Bool",
                    "userId": "pbool"
                }
            ],
            "userParticipants": [],
            "_isSelectable": true,
            "parentId": "1",
            "_order": 1
        }
    },
    "count": 1,
    "total": "50",
    "updated": null
}
```

#### Update Event

{% hint style="danger" %}
This method is deprecated and will not be supported in 2026
{% endhint %}

```
PUT https://{{host}}/api/json/event/id/{{id}}
Authorization: Bearer {{token}}
X-Site: {{site}}

{
    "PAYLOAD"
}
```

Example: Close an event and update its description

```http
PUT https://{{host}}/api/json/event/id/25
Authorization: Bearer {{token}}
X-Site: {{site}}

{
  "id": "25",
  "title": "My Event",
  "description": "This event was closed today",
  "startDate": "2017-01-08T03:00:00+00:00",
  "endDate": "2017-01-08T04:00:00+00:00",
  "status": {
    "label": "Closed",
    "value": -1,
    "style": "grey"
  },
  "severity": "3",
  "participants": [],
  "userParticipants": [],
  "_isSelectable": true,
  "parentId": "1"
}
```

### Register Item

A RESTful command to access and manage register items, which are the primary business object within the system.

```
GET /api/json/item
POST /api/json/item
GET /api/json/item/id/123
PUT /api/json/item/id/123
```

#### GET Parameters

{% hint style="info" %}
The majority of filtering will use [CQL search terms](https://docs.cw.crisisworks.com/concepts-and-fundamentals/on-a-computer/searching-filtering-and-querying-registers).

Please consult the register guide or contact Datalink's Service Desk for more details.
{% endhint %}

<table><thead><tr><th width="197.8046875">Keys</th><th width="157.484375">Type</th><th>Details</th></tr></thead><tbody><tr><td><code>limit</code></td><td>Number</td><td>When paginating, how many records to return</td></tr><tr><td><code>offset</code></td><td>Number</td><td>When paginating, which record to start from</td></tr><tr><td><code>registerId</code></td><td>String</td><td><p>Aliases: <code>type</code> ; Set to the register ID for filtering.</p><p> </p></td></tr><tr><td><code>cql</code></td><td>String</td><td>Aliases <code>query</code>; Use this for all field-level and full-text querying using the CQL query language.</td></tr><tr><td><code>eventId</code></td><td>String</td><td></td></tr><tr><td><code>since</code></td><td>String</td><td>Set since_operator to the desired operator if changing from the default</td></tr><tr><td><code>until</code></td><td>String</td><td>Set until_operator to the desired operator if changing from the default</td></tr><tr><td><code>isTemplate</code></td><td>String</td><td>Filter to include or exclude template items</td></tr></tbody></table>

#### **Example: fetch all active FPN records**

Example output of all active FPN items.  Note, the first item has an attached asset and shows how the extra fields are returned.

```http
GET https://{{host}}/api/json/item?type=fpn&active=1
Authorization: Bearer {{token}}
X-Site: {{site}}
```

Response

```json
{
    "models": {
        "14919": {
            "id": "14919",
            "eventId": "1014",
            "due": null,
            "isSensitive": false,
            "itemSchemaName": "moorabool",
            "userId": "pkakris.mb",
            "status": "20",
            "templateName": null,
            "costEstimate": "0.00",
            "type": "fpn",
            "title": null,
            "address": null,
            "assetId": "1345678",
      	    "asset_friendly": "7 TEST STREET 3000",
            "asset_code": "pr_1234567",
            "asset_type": "Asset_Property_Vicmap",
            "asset_extra": {
                "spi": "2\\PS12345",
                "code": "pr_1234567",
                "crefno": "11111",
                "propnum": "22222",
                "fur_desc": null,
                "prop_pfi": "4444444",
                "parcel_pfi": "444444"
            },
            "assignee": "2632",
            "assignee_info": "Pete Kakris",
            "_canEdit": true,
            "dateCreated": "2016-03-03T13:13:33+11:00",
            "dateUpdated": "2016-03-03T13:13:33+11:00",
            "isTemplate": false,
            "tags": "",
            "infringementNumber": null,
            "contractors": [],
            "media": [
                {
                    "id": "602",
                    "uri": "\/api\/binary\/media\/602",
                    "thumbUri": "\/api\/binary\/media\/602?type=thumb",
                    "type": "image\/jpeg",
                    "name": "blob.jpg",
                    "created": "2016-03-03T02:13:22+00:00",
                    "size": "71785"
                }
            ],
            "mergedFile": [],
            "activity": null,
            "cutGrassWeeds10cm": false,
            "removeDebris": false,
            "firebreak10m": false,
            "cutGrassWeeds5cm": false,
            "trimTrees": false,
            "removeFlammable": false,
            "notes": null,
            "dateNewFromWeb": null,
            "dateNewFromMobile": null,
            "date1stInspectionRequired": null,
            "dateHazardExists": "2016-03-03T02:13:33+00:00",
            "dateComplianceInspectionRequired": null,
            "dateRequestCompulsoryClearing": null,
            "datePostClearanceInspectionReview": null,
            "dateHazardCleared": null,
            "dateTemporaryExemptionGranted": null,
            "dateClosed": null,
            "dateNoticeWithdrawn": null,
            "dateFpnSent": null,
            "infringementSentDate": null,
            "_order": 1
        },
        "14968": {
            "id": "14968",
            "eventId": "1014",
            "due": null,
            "isSensitive": false,
            "itemSchemaName": "moorabool",
            "userId": "pkakris.mb",
            "status": "20",
            "templateName": null,
            "costEstimate": "0.00",
            "type": "fpn",
            "title": "PARCEL 45530943",
            "address": "PARCEL 45530943",
            "assetId": "24733",
            "assignee": "2632",
            "assignee_info": "Pete Kakris",
            "_canEdit": true,
            "dateCreated": "2016-06-20T14:06:27+10:00",
            "dateUpdated": "2016-06-20T14:06:27+10:00",
            "isTemplate": false,
            "tags": "",
            "infringementNumber": null,
            "contractors": [],
            "media": [],
            "mergedFile": [],
            "activity": null,
            "cutGrassWeeds10cm": true,
            "removeDebris": false,
            "firebreak10m": false,
            "cutGrassWeeds5cm": false,
            "trimTrees": false,
            "removeFlammable": false,
            "notes": null,
            "dateNewFromWeb": null,
            "dateNewFromMobile": null,
            "date1stInspectionRequired": null,
            "dateHazardExists": "2016-06-20T04:06:27+00:00",
            "dateComplianceInspectionRequired": null,
            "dateRequestCompulsoryClearing": null,
            "datePostClearanceInspectionReview": null,
            "dateHazardCleared": null,
            "dateTemporaryExemptionGranted": null,
            "dateClosed": null,
            "dateNoticeWithdrawn": null,
            "dateFpnSent": null,
            "infringementSentDate": null,
            "_order": 2
        }
    },
    "count": 2,
    "total": 2,
    "updated": null
}
```

#### POST|PUT

Creating (POST) and updating (PUT) items uses a similar structure to the GET response, but only sends one item.

To create an item

```http
POST https://{{host}}/api/json/item
Authorization: Bearer {{token}}
X-Site: {{site}}
```

To update an item:

```http
PUT https://{{host}}/api/json/item/id/{{id}}
Authorization: Bearer {{token}}
X-Site: {{site}}
```

For example:

```http
PUT https://{{host}}/api/json/item/id/14968
Authorization: Bearer {{token}}
X-Site: {{site}}

{
  "id": "14968",
  "eventId": "1014",
  "status": "20",
  "type": "fpn",
  "title": "PARCEL 45530943",
  "assetId": "24733",
  "cutGrassWeeds10cm": true,
  "removeDebris": false,
  "firebreak10m": false,
  "cutGrassWeeds5cm": false,
  "trimTrees": false,
  "removeFlammable": false,
  "notes": "This is a note"
}
```

#### Matching assets&#x20;

When linking an asset to an item, you have three approaches:

* set `assetId` to the Crisisworks internal ID for the asset,
* set `asset_friendly` to a name, and have Crisisworks look up the asset using a its search algorithm, or
* set `asset_lookup` to look up a foreign key for the asset, that will match one of the stored foreign keys in the asset's `extra` property. For example, you can look up by `propnum` or `crefno`, if those foreign keys are in your asset dataset. To determine which code to look up, you can specify `asset_codefield`.

Example: creating an item with an asset looked up based on a property containing `propnum`.

```http
POST https://{{host}}/api/json/item
Authorization: Bearer {{token}}
X-Site: {{site}}

{
  "eventId": "1014",
  "status": "20",
  "type": "fpn",
  "itemSchemaName": "vicCouncil",
  "asset_lookup": "123456",
  "asset_codefield": "propnum"
}
```

Example: creating an item with an asset looked up based on a property by a name search.

```http
POST https://{{host}}/api/json/item
Authorization: Bearer {{token}}
X-Site: {{site}}

{
  "eventId": "1014",
  "status": "20",
  "type": "fpn",
  "itemSchemaName": "vicCouncil",
  "asset_friendly": "12 smith street collingwood"
}
```

### Audit Log

This fetches a collection of audit logs, either for a given object (with itemId specified), a given event (with eventId specified) or across the system.

```http
GET https://{{host}}/api/json/log
Authorization: Bearer {{token}}
X-Site: {{site}}
```

#### GET Parameters

<table><thead><tr><th width="170.83984375">Keys</th><th width="139.65234375">Type</th><th>Details</th></tr></thead><tbody><tr><td><code>limit</code></td><td>Number</td><td>When paginating, how many records to return</td></tr><tr><td><code>offset</code></td><td>Number</td><td>When paginating, which record to start from</td></tr><tr><td><code>id</code></td><td>String</td><td>Load a specific audit log ID</td></tr><tr><td><code>eventId</code></td><td>String</td><td>Load all audit logs for an event. Warning, this is a large payload and will need pagination.</td></tr><tr><td><code>itemId</code></td><td>String</td><td>Load all audit logs for a given register item</td></tr></tbody></table>

**Example**

Fetch the audit log for item 14968

```http
GET https://{{host}}/api/json/log?limit=5&item=14968
Authorization: Bearer {{token}}
X-Site: {{site}}
```

Result

```json
{
    "models": {
        "1004527": {
            "time": "2016-06-20 4:06:27 +0000",
            "id": "1004527",
            "type": "Items",
            "summary": "created a fire prevention notice and set it to hazard exists",
            "message": "",
            "images": [],
            "labels": [
                {
                    "style": "yellow",
                    "label": "Hazard Exists"
                }
            ],
            "dataChangeCount": 10,
            "itemCount": 1,
            "userName": "Pete Kakris",
            "userPosition": "Crisisworks Administrator, FPN Coordinator",
            "userOrganisation": "Datalink",
            "userId": "pkakris.mb",
            "userPositionId": "7",
            "userAvatarUrl": "https:\/\/demo4.crisisworks.com\/var\/files\/thumbs\/80ea44413272ba499ddd0413fc2858cf_57c193f71dbbed2361bce727c9ce1642_w60_h60_fit.png",
            "objId": "14968",
            "objType": "Fire Prevention Notice",
            "objIcon": "ico_hazard_fire.png",
            "title": "PARCEL 45530943",
            "url": "https:\/\/demo4.crisisworks.com\/register\/item\/view\/id\/14968",
            "registerId": "fpn",
            "registerName": "Fire Prevention Notice",
            "eventId": "1014",
            "eventName": "FPN Inspections",
            "assignments": [
                {
                    "id": "pkakris.mb",
                    "name": "Pete Kakris",
                    "type": "Mecc_User",
                    "avatarUrl": "https:\/\/demo4.crisisworks.com\/var\/files\/thumbs\/80ea44413272ba499ddd0413fc2858cf_57c193f71dbbed2361bce727c9ce1642_w60_h60_fit.png"
                }
            ],
            "status": "Hazard Exists",
            "statusClass": "yellow",
            "statusValue": 20,
            "visibility": "",
            "targetUsers": [
                "pkakris.mb"
            ],
            "targetPositions": [],
            "comment": null,
            "targetOrganisations": [],
            "sound": "message_received",
            "logEntries": [
                {
                    "objId": "1031017",
                    "objClass": "Fpn_Inspection",
                    "objTitle": "PARCEL 45530943",
                    "subject": "created a Fire Prevention Notice",
                    "dataChanges": [
                        {
                            "name": "eventId",
                            "label": "Event",
                            "oldValue": "FPN Inspections",
                            "newValue": "FPN Inspections"
                        },
                        {
                            "name": "status",
                            "label": "Status",
                            "oldValue": "",
                            "newValue": "Hazard Exists"
                        },
                        {
                            "name": "assetId",
                            "label": "Asset",
                            "oldValue": "",
                            "newValue": "PARCEL 45530943"
                        },
                        {
                            "name": "cutGrassWeeds10cm",
                            "label": "Cut grass and weeds over the whole property to a height of no more than 10cm.",
                            "oldValue": "",
                            "newValue": "Yes"
                        },
                        {
                            "name": "removeDebris",
                            "label": "Leaves, twigs and other vegetation debris must be removed at regular intervals.",
                            "oldValue": "",
                            "newValue": "No"
                        },
                        {
                            "name": "firebreak10m",
                            "label": "A firebreak of 10 metres wide is to be cut inside the property boundary as close as practicable to the fence-line, to a height of not more than 10cm",
                            "oldValue": "",
                            "newValue": "No"
                        },
                        {
                            "name": "cutGrassWeeds5cm",
                            "label": "Cut all grass and weeds within 30m of any building to a height of no more than 5cm.",
                            "oldValue": "",
                            "newValue": "No"
                        },
                        {
                            "name": "trimTrees",
                            "label": "Trim trees and shrubs clear of roofline, walls and other elements of the buildings.",
                            "oldValue": "",
                            "newValue": "No"
                        },
                        {
                            "name": "removeFlammable",
                            "label": "Remove flammable objects such as firewood, mulches, rubbish and garden furniture from within 10m of the vulnerable parts of the building like windows, decks and eaves.",
                            "oldValue": "",
                            "newValue": "No"
                        },
                        {
                            "name": "assignee",
                            "label": "Assign To",
                            "oldValue": "",
                            "newValue": "Pete K"
                        }
                    ]
                },
                {
                    "objId": "1031018",
                    "objClass": "Fpn_Inspection",
                    "objTitle": "PARCEL 45530943",
                    "subject": "linked to User Pete K"
                }
            ],
            "userOrganisationId": "",
            "subject": "",
            "_order": 1
        }
    },
    "count": 1,
    "total": 1,
    "updated": null
}
```

### Media

Media (photos, videos) are uploaded to Crisisworks and then attached to items.

#### Creating media

To upload a file, use the `/api/binary/file` endpoint and `POST` a `multipart/form-data` payload with `name` (the friendly filename) and `file` (the raw binary payload).&#x20;

{% hint style="info" %}
This is equivalent to the way a web browser handles file uploads. This is tricky to do by hand, so you'd typically do this using a library.
{% endhint %}

The following is a raw HTTP example:

```http
POST https://api.cw.dev.crisisworks.com/api/binary/file
Accept: application/json
Authorization: Bearer {{token}}
X-Site: {{site}}
Content-Type: multipart/form-data; boundary=----CrisisworksBinaryDataFormBoundary
Content-Length: {{content-length}}

------CrisisworksBinaryDataFormBoundary
Content-Disposition: form-data; name="file"; filename="Raising ducks.pdf"
Content-Type: application/pdf

%PDF-1.7...{{raw binary bytes of the PDF, not base64}}...EOF
------CrisisworksBinaryDataFormBoundary
Content-Disposition: form-data; name="filename"

Raising ducks.pdf
------CrisisworksBinaryDataFormBoundary--
```

Fortunately common HTTP libraries handle this for us.&#x20;

Here's the above example in BASH:

```bash
#!/bin/bash
FILE="Raising ducks.pdf"
TOKEN="your-access-token"
SITE="yoursiteid"
URI="https://yourhost/api/json/file"

curl -X POST "${URI}" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Site: $SITE" \
  -F "file=@${FILE};type=application/pdf;filename=${FILE}" \
  -F "filename=${FILE}"
```

And here is the same example in Windows PowerShell:

```powershell
$FilePath   = "Raising ducks.pdf"
$Token      = "your-access-token"
$Site       = "yoursiteid"
$Uri        = "https://yourhost/api/json/file"

# Build the multipart form
$Form = @{
    file     = Get-Item $FilePath
    filename = [IO.Path]::GetFileName($FilePath)
    comment  = "null"
}

# Send request with headers
Invoke-RestMethod -Uri $Uri -Method Post `
  -Headers @{
      "Accept" = "application/json"
      "Authorization" = "Bearer $Token"
      "X-Site" = $Site
  } `
  -Form $Form
```

The result contains a unique file ID:

```json
{
    code: 200, 
    message: "OK", 
    id: "1110"
}
```

You can use this `id` in future item POST and PUT commands to attach the item:

```json
POST https://{{host}}/api/json/item
Authorization: Bearer {{token}}
X-Site: {{site}}

{
  "__operationTimestamp": "2025-09-17T04:45:45.925Z",
  "type": "wiki",
  "title": "How to raise ducks",
  "body": "<p>A how-to guide on how to raise ducks</p>",
  "itemSchemaName": "document",
  "status": "2",
  "eventId": "20",
  "attachments": [
    {
      "id": "1110",
      "name": "Raising ducks.pdf",
      "type": "application/pdf"
    }
  ]
}
```

#### Downloading media

To download a file, use its file ID.

```http
GET https://{{host}}/api/binary/media/id/{{id}}
Authorization: Bearer {{token}}
X-Site: {{site}}
```

The output will be streamed in binary.

Use your libraries to make this easier. For example, in curl `-o` allows the destination filename to be specified:

```bash
curl -L \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Site: $SITE" \
  -o "my-custom-name.pdf" \
  "https://$HOST/api/binary/media/id/$ID"
```
