> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.fortresstech.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.fortresstech.io/_mcp/server.

# Work Orders Overview

> Overview of the Work Orders API endpoints and functionality

The Work Orders API provides endpoints for managing and interacting with maintenance work orders.

## Key Concepts

### Work Order Status

Work Orders can be in various states:

* `OPEN`
* `COMPLETED`
* `CANCELED`
* `ON_HOLD`
* `IN_PROGRESS`

### Work Order Priority

Work Orders can be categorized by different priorities:

* `LOW`
* `MEDIUM`
* `HIGH`
* `URGENT`
* `WARRANTY`

### Work Order Entry Preference

Work Orders can have entry preference:

* `24_HOUR_NOTICE`
* `BY_APPOINTMENT`
* `CALL_FIRST`
* `NO_PREFERENCE`
* `ANYTIME`

## Available Endpoints

| Endpoint                                                                                                                                 | Summary                      | Method |
| ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | :----: |
| [`/workorders`](/api-reference/work-orders/list-work-orders)                                                                             | List Work Orders             |   GET  |
| [`/workorders`](/api-reference/work-orders/create-work-order)                                                                            | Create Work Order            |  POST  |
| [`/workorders/{workOrderId}`](/api-reference/work-orders/read-work-order)                                                                | Read Work Order              |   GET  |
| [`/workorders/{workOrderId}`](/api-reference/work-orders/update-work-order)                                                              | Update Work Order            |   PUT  |
| [`/workorders/{workOrderId}`](/api-reference/work-orders/delete-work-order)                                                              | Delete Work Order            | DELETE |
| [`/workorders/{workOrderId}/attachments`](/api-reference/work-orders/list-attachments)                                                   | List Attachments             |   GET  |
| [`/workorders/{workOrderId}/attachments`](/api-reference/work-orders/create-attachment)                                                  | Create Attachment            |  POST  |
| [`/workorders/{workOrderId}/attachments/{attachmentId}/downloadUrl`](/api-reference/work-orders/read-work-order-attachment-download-url) | Read Attachment Download URL |   GET  |
| [`/workorders/{workOrderId}/assign`](/api-reference/work-orders/assign-work-order)                                                       | Assign Work Order            |  PATCH |
| [`/workorders/{workOrderId}/unassign`](/api-reference/work-orders/unassign-work-order)                                                   | Unassign Work Order          |  PATCH |
| [`/workorders/{workOrderId}/start`](/api-reference/work-orders/start-work-order)                                                         | Start Work Order             |  PATCH |
| [`/workorders/{workOrderId}/hold`](/api-reference/work-orders/hold-work-order)                                                           | Hold Work Order              |  PATCH |
| [`/workorders/{workOrderId}/complete`](/api-reference/work-orders/complete-work-order)                                                   | Complete Work Order          |  PATCH |
| [`/workorders/{workOrderId}/cancel`](/api-reference/work-orders/cancel-work-order)                                                       | Cancel Work Order            |  PATCH |

## Work order photos

The `url` on an attachment from the list endpoint is a storage reference. You cannot fetch it. To show or download a photo, request a short-lived download link for that attachment.

Your API key needs an explicit `workOrders` read grant for this route. A key that works on the other work-order routes but has no permissions map gets 403 here. To request the grant, contact our team.

### Example

1. List the attachments of a work order. Copy the `id` of the attachment you need.

```bash
curl --location 'https://api.fortresstech.io/v1/workOrders/3f2b8c1e-5a4d-4e7b-9c10-2d6e8f0a1b34/attachments' \
--header 'x-api-key: <your-api-key>'
```

2. Request a download link. `expiresInSeconds` is optional. It defaults to 300 and the server clamps it to 60–900.

```bash
curl --location 'https://api.fortresstech.io/v1/workOrders/3f2b8c1e-5a4d-4e7b-9c10-2d6e8f0a1b34/attachments/9a7c4d02-6b1e-4f83-8e25-0c3d5b7a9e61/downloadUrl?expiresInSeconds=300' \
--header 'x-api-key: <your-api-key>'
```

```json
{
  "url": "https://<bucket>.s3.amazonaws.com/<key>?X-Amz-...",
  "expiresAt": "2026-10-08T18:05:00.000Z",
  "attachmentId": "9a7c4d02-6b1e-4f83-8e25-0c3d5b7a9e61",
  "workOrderId": "3f2b8c1e-5a4d-4e7b-9c10-2d6e8f0a1b34",
  "fileName": "kitchen-leak.jpg",
  "contentType": "image/jpeg"
}
```

3. Fetch the `url` with a plain GET before `expiresAt`. Do not send the `x-api-key` header. Accept `Content-Encoding: gzip`.

```bash
curl --location --compressed 'https://<bucket>.s3.amazonaws.com/<key>?X-Amz-...' --output kitchen-leak.jpg
```

4. After `expiresAt`, the link stops working. Call the route from step 2 again to get a fresh link.

> **Warning**
>
> Never store a download link as a permanent reference to a photo. The link expires. Store the attachment `id` and the work order `id`, and request a new link each time you need the file.

### Response codes

| Status | Meaning                                                                                                                                                                             |
| :----: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   200  | The response holds a signed link and its expiry time.                                                                                                                               |
|   400  | The request is not valid. `expiresInSeconds` is not an integer, `workOrderId` or `attachmentId` is not a UUID, or the key is an all-organizations key, which cannot use this route. |
|   401  | The request has no `x-api-key` header. API Gateway returns this status with a `{"message": "Unauthorized"}` body before the authorizer runs.                                        |
|   403  | The API key has no permissions map, or its map has no `workOrders` read. The floo gateway returns this status with a `{"Message": ...}` body.                                       |
|   404  | The attachment or the work order was not found. The response is the same for a missing, deleted, or out-of-scope item.                                                              |
|   415  | The file is not a PDF, JPEG, PNG, or GIF.                                                                                                                                           |
|   500  | The server could not issue the link, for example when the access log write failed. Retry later.                                                                                     |