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

# Dynamics 365 Field Service and Connected Field Service

> Client-mode REST API connector for a curated Dynamics 365 Field Service / Connected Field Service Dataverse slice: IoT alerts from MQTT alarms, work orders, customer asset PATCH, work order filter query

Technical Preview

## Overview

A client-mode connector for a **curated Field Service / Connected Field Service** slice of the [Dataverse Web API](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/overview) on Dynamics 365 Field Service (`https://YOUR_ORG.api.crm.dynamics.com`):

| Catalog connector event | Entity / path | Notes |
| - | - | - |
| POST msdyn\_iotalerts (from MQTT alarm) | `POST /api/data/v9.2/msdyn_iotalerts` | Connected Field Service [IoT Alert](https://learn.microsoft.com/en-us/dynamics365/developer/reference/entities/msdyn_iotalert); `msdyn_description` required |
| POST msdyn\_workorders | `POST /api/data/v9.2/msdyn_workorders` | [Create work order](https://learn.microsoft.com/en-us/dynamics365/field-service/create-work-order-api-example); use `@odata.bind` for lookups |
| PATCH msdyn\_customerassets | `PATCH /api/data/v9.2/msdyn_customerassets({id})` | [Customer Asset](https://learn.microsoft.com/en-us/dynamics365/field-service/developer/reference/entities/msdyn_customerasset); `If-Match: *` |
| GET msdyn\_workorders?\$filter= | `GET /api/data/v9.2/msdyn_workorders?$filter=…` | OData filter / select / top |

`BASE_ADDRESS` is `https://{org}.api.crm{N}.dynamics.com` (no trailing slash; endpoints already include `/api/data/v9.2/...`). Topics use `cmms/dynamics-365-field-service-and-connected-field-service/<object>/<verb>`.

This package is **distinct** from the general Dataverse CRM template [Dynamics 365](/latest/lot-language/routes/rest-api-apps/dynamics365) (accounts / contacts / WhoAmI).

> [!NOTE]
>
> Prefer Hub secrets for Entra access tokens. This template has not been verified against a live Field Service org. Status remains blocked until an authenticated live smoke succeeds.

## Basic Syntax

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
# Coreflux REST_API template — Dynamics 365 Field Service / Connected Field Service
# Auth: Entra Bearer {value.json.api_token}
# BASE_ADDRESS: https://YOUR_ORG.api.crm.dynamics.com

DEFINE ROUTE Dynamics365FieldServiceRestApi WITH TYPE REST_API
    ADD REST_API_CONFIG
        WITH BASE_ADDRESS "https://YOUR_ORG.api.crm.dynamics.com"
        WITH ENABLE_CLIENT "true"
        WITH USE_SSL "true"
        WITH REQUEST_TIMEOUT '60'
        WITH DEFAULT_CONTENT_TYPE "application/json"
    ADD EVENT Createiotalert
        WITH SOURCE_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_iotalerts/create"
        WITH DESTINATION_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_iotalerts/create/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/data/v9.2/msdyn_iotalerts"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "OData-MaxVersion" "4.0"
            ADD "OData-Version" "4.0"
            ADD "Prefer" "return=representation,odata.include-annotations=\"*\""
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
    ADD EVENT Createworkorder
        WITH SOURCE_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/create"
        WITH DESTINATION_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/create/response"
        WITH METHOD "POST"
        WITH ENDPOINT "/api/data/v9.2/msdyn_workorders"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "OData-MaxVersion" "4.0"
            ADD "OData-Version" "4.0"
            ADD "Prefer" "return=representation,odata.include-annotations=\"*\""
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
    ADD EVENT Patchcustomerasset
        WITH SOURCE_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_customerassets/patch"
        WITH DESTINATION_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_customerassets/patch/response"
        WITH METHOD "PATCH"
        WITH ENDPOINT "/api/data/v9.2/msdyn_customerassets({value.json.msdyn_customerassetid})"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "Content-Type" "application/json"
            ADD "OData-MaxVersion" "4.0"
            ADD "OData-Version" "4.0"
            ADD "If-Match" "*"
            ADD "Prefer" "odata.include-annotations=\"*\""
            ADD "Authorization" "Bearer {value.json.api_token}"
        WITH BODY "{payload}"
    ADD EVENT Listworkorders
        WITH SOURCE_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/list"
        WITH DESTINATION_TOPIC "cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/list/response"
        WITH METHOD "GET"
        WITH ENDPOINT "/api/data/v9.2/msdyn_workorders?$filter={value.json.filter}&$select={value.json.select}&$top={value.json.top}"
        WITH HEADERS
            ADD "Accept" "application/json"
            ADD "OData-MaxVersion" "4.0"
            ADD "OData-Version" "4.0"
            ADD "Prefer" "odata.include-annotations=\"*\""
            ADD "Authorization" "Bearer {value.json.api_token}"
```

## Parameters

| Parameter | Required | Description |
| - | - | - |
| `BASE_ADDRESS` | Yes | `https://{org}.api.crm{N}.dynamics.com` — org API host, no trailing slash |
| `api_token` (MQTT JSON) | Yes | Entra ID access token (audience = org URL) for `Authorization: Bearer …` |
| `filter` | For list | OData `$filter`, e.g. `msdyn_systemstatus eq 690970000` |
| `select` | For list | OData `$select` column list |
| `top` | For list | OData `$top` page size |
| `msdyn_customerassetid` | For PATCH | Customer asset GUID (path) |
| `{payload}` | POST/PATCH | Dataverse JSON body (lookups as `@odata.bind` paths) |

## Authentication

* **Entra ID OAuth 2.0 Bearer** for the Dataverse org resource (client credentials or delegated).
* Prefer Hub secrets / `GET SECRET`. Never commit real tokens.
* See [Authenticate to Dataverse with the Web API](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/authenticate-oauth).

## MQTT topics

| Event | Source topic | Method |
| - | - | - |
| Create IoT alert | `cmms/dynamics-365-field-service-and-connected-field-service/msdyn_iotalerts/create` | POST |
| Create work order | `cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/create` | POST |
| Patch customer asset | `cmms/dynamics-365-field-service-and-connected-field-service/msdyn_customerassets/patch` | PATCH |
| List work orders | `cmms/dynamics-365-field-service-and-connected-field-service/msdyn_workorders/list` | GET |

Responses publish on the same topic with `/response` appended.

## Example payloads

**IoT alert from MQTT alarm**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_ENTRA_ACCESS_TOKEN",
  "msdyn_description": "IIoT alarm — high vibration Zone A",
  "msdyn_alerttime": "2026-10-04T11:00:00Z",
  "msdyn_alerttype": 192350000,
  "msdyn_deviceid": "edge-compressor-01",
  "msdyn_alertdata": "{\"metric\":\"vibration_rms\",\"value\":12.4}",
  "msdyn_customerasset@odata.bind": "/msdyn_customerassets(00000000-0000-0000-0000-000000000001)"
}
```

Alert types: `192350000` Anomaly, `192350001` Info, `192350002` Preventive Maintenance, `192350003` Test.

**Work order**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_ENTRA_ACCESS_TOKEN",
  "msdyn_serviceaccount@odata.bind": "/accounts(…)",
  "msdyn_workordertype@odata.bind": "/msdyn_workordertypes(…)",
  "msdyn_systemstatus": 690970000,
  "msdyn_instructions": "Investigate IoT alert from Coreflux"
}
```

**Filter work orders**

```json theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "api_token": "YOUR_ENTRA_ACCESS_TOKEN",
  "filter": "msdyn_systemstatus eq 690970000",
  "select": "msdyn_name,msdyn_systemstatus,msdyn_workorderid",
  "top": "20"
}
```

## Notes

* Successful creates often return **204** with an `OData-EntityId` header (or a body when `Prefer: return=representation` is honored).
* Never send bare GUIDs for lookup fields — always `/entityset(guid)` via `@odata.bind`.
* Connected Field Service IoT alerts can be converted to work orders in the Field Service UI / BPF; this connector also supports creating work orders directly and optionally binding `msdyn_iotalert@odata.bind`.
* Requires Field Service (and Connected Field Service entities for IoT alerts) installed in the Dataverse environment.

## Related

* [REST API Connectors](/latest/lot-language/routes/rest-api-routes)
* [Dynamics 365 (Dataverse CRM)](/latest/lot-language/routes/rest-api-apps/dynamics365)
* [IBM Maximo Manage](/latest/lot-language/routes/rest-api-apps/ibm-maximo-manage)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.