# Crew messages

Every job has a chat between the office and the crews working it: the **Messages** inbox in TruTec and the Messages tab in the crew app. Photos and files shared there stay on the job.

!!! warning
    Posting reaches your crew. Crew members with work on the job get an in-app alert, and an email and a text when it is the first message they haven't read in that thread. A broadcast alerts every crew with work in the next 14 days.

Posts are made as the person who created the API key, shown as the office. They need operations turned on for the workspace (`403` `Operations not enabled` otherwise).

## The message object

| Field | Type | Description |
|---|---|---|
| `id` | integer | Message id. |
| `job_id` | integer | The job. |
| `work_order_id` | integer or null | The visit the message is about, if any. |
| `sender` | object | `{id, name}`. |
| `sender_role` | string | `office` or `field` (a crew member). |
| `body` | string | The text. Broadcasts start with `[Broadcast]`. |
| `photo_url` | string or null | A photo or video shared in the chat. `is_video` says which. |
| `document` | object or null | A file shared in the chat, `{id, filename}`. Download it with the files endpoints. |
| `created_at` | string | UTC timestamp. |

## List a job's messages

`GET /v1/jobs/{id}/crew-messages`

**Permission:** Read jobs

Oldest first. Takes `created_after` (ISO 8601) to fetch only new messages, `work_order_id`, `limit` and `offset`.

```json
{
  "data": [
    {
      "id": 90211,
      "job_id": 70412,
      "work_order_id": 4120,
      "sender": { "id": 344, "name": "Crew Lead" },
      "sender_role": "field",
      "body": "Gate is locked, waiting on the property manager.",
      "photo_url": null,
      "is_video": false,
      "document": null,
      "created_at": "2026-11-03T13:05:12Z"
    }
  ],
  "pagination": { "total": 1, "limit": 50, "offset": 0 }
}
```

## Post a message

`POST /v1/jobs/{id}/crew-messages`

**Permission:** Write jobs

| Field | Type | Required | Description |
|---|---|---|---|
| `body` | string | Yes | Up to 5,000 characters. |
| `work_order_id` | integer | No | A visit on this job the message is about. |
| `document_id` | integer | No | A file already on this job to attach. |

```bash
curl -X POST "https://trutec.ai/api/v1/jobs/70412/crew-messages" \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "body": "Property manager is on the way with the gate key, 10 minutes.", "work_order_id": 4120 }'
```

Returns `201` with the message.

## Message every crew

`POST /v1/crews/broadcast` with `{"body": "Rain call: no paving tomorrow, crews report to the yard at 7."}`

**Permission:** Write jobs

Sends one message to every crew with scheduled or in-progress work in the next 14 days, like **Broadcast** in the Messages inbox: an in-app alert to each crew member with TruTec access, and a `[Broadcast]` line in the chat of each of those jobs so it's on the record. Holds are left out.

```json
{ "data": { "crew_members_notified": 14, "jobs_messaged": 6 } }
```
