# Dynamics 365

> Dynamics 365: what the collector reads, how to connect it, its permissions, its certification by Atlantic Agentic Labs and its security posture.

Built, not certified Built and tested against recorded and synthetic responses (version 1.0.0, 10 November 2026). Not yet run against the vendor's sandbox or a client environment.

Reads accounts, opportunities and cases from a Dynamics 365 (Dataverse) environment, so commercial and service agents can answer from the account and case history. It reads in place, in your deployment; only ids, hashes and counts reach LightHouse.

## At a glance

| Collector                   | Dynamics 365, version `1.0.0`                                                                                                                                    |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Reads                       | Microsoft: Dynamics 365 (Dataverse Web API) ([the vendor's documentation](https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/overview)) |
| Family                      | CRM                                                                                                                                                              |
| Kind                        | CRM                                                                                                                                                              |
| Ways to connect             | OAuth approval                                                                                                                                                   |
| Scopes                      | - Read: `<environment>/.default`                                                                                                                                 |
| Read only                   | Yes, except: \[object Object]                                                                                                                                    |
| Vendor's API can move money | No                                                                                                                                                               |
| Personal data               | Contact, Content                                                                                                                                                 |
| Hosts it may contact        | `{org}.crm{region}.dynamics.com`, `login.microsoftonline.com`                                                                                                    |
| Vendor API versions         | Dataverse Web API v9.2                                                                                                                                           |
| Lowest engine version       | `0.46.0`                                                                                                                                                         |

## What it reads

- **Accounts:** name, account number, industry, website, city, country, description, primary contact (as its formatted name).
- **Opportunities:** name, customer, state, sales stage, estimated value, estimated close date, close probability, description.
- **Cases** (the `incident` table): title, ticket number, customer, state, priority, case type, description.
- Only the tables you name in `objects` (`accounts`, `opportunities`, `cases`), and only the columns above (`$select`), with lookups as their formatted names.
- Changes only: each table is read by `modifiedon` (UTC), oldest first, 500 a page, following `@odata.nextLink`, which must stay on the environment’s host.

## How to connect

1. In Microsoft Entra, make an app registration with a certificate, as for SharePoint, and note the directory (tenant) id and application (client) id.
2. In your Dynamics 365 environment, add the app as an **application user** with a security role that is a read-only copy over the three tables.
3. In LightHouse, open **Setup and admin, Connectors**, choose **Dynamics 365**, and give `environment_url` (`https://<org>.crm.dynamics.com`, or `crm2`, `crm4` and so on for your region) and `objects`.
4. Paste the certificate’s private key. Your browser seals it to your deployment; LightHouse never sees it.

The credential is JSON in the variable the source names (`DYNAMICS_CREDENTIAL` by default): `tenant_id`, `client_id`, `certificate` and `environment_url`.

## Permissions

- **Scope requested:** `<environment_url>/.default`: a token for that environment alone, minted from a certificate assertion signed in your own account (client-credentials grant). No client secret exists.
- Dataverse states no permissions in the token, so **read-only is the security role you give the application user**: a copy of a read-only role over accounts, opportunities and cases. The connection check says so.
- **What the collector does:** `GET` requests to `/api/data/v9.2/<table>`, plus one `POST` to Microsoft’s token endpoint (`login.microsoftonline.com/<tenant>/oauth2/v2.0/token`) for the access token. Its read-only test proves that on every change.
- **Hosts:** your environment and Microsoft’s login host. A next-page link to any other host is refused.

## Limits

- Dataverse Web API v9.2.
- `environment_url` must look like `https://<org>.crm.dynamics.com` (with an optional region number after `crm`).
- Pages of 1 to 5,000 rows (`page_size`, default 500).
- Deletions are found by listing primary keys every six hours; a deleted record is removed from the corpus then, not at once.
- A table the role cannot list (403 or 404) skips the deletion check for it rather than failing the read.

## Data handling

- Accounts, contacts’ names and cases hold personal data. Documents carry the `label` you give the source.
- Content is read in place, in your deployment. LightHouse receives ids, hashes and counts, never the records, and never opens the credential.
- The raw bytes of each response are cached in your deployment, named by their SHA-256, so any passage can be traced to what was served.
- The private key is used only to sign the assertion; it is never put in a request, a log line or an error message.

## Troubleshooting

| What you see                                           | What it means                                                 | What to do                                             |
| ------------------------------------------------------ | ------------------------------------------------------------- | ------------------------------------------------------ |
| `credential variable 'DYNAMICS_CREDENTIAL' is not set` | The deployment holds no credential for this source            | Connect Dynamics 365 again in LightHouse               |
| `the dynamics credential has no environment_url`       | A field (named in the message) is missing                     | Re-enter all four fields                               |
| `environment_url is https://<org>.crm.dynamics.com`    | The URL is not a Dataverse environment                        | Use the environment’s own address                      |
| `tenant_id is the directory's id, a GUID`              | `tenant_id` is not a GUID                                     | Copy the directory id from Entra                       |
| `HTTP 401` or `HTTP 403`                               | The app is not an application user, or its role lacks a table | Add the application user and give it read on the table |
| `HostNotAllowed` (`... is not an allowed host`)        | A next-page link named another host                           | Report it; nothing was sent there                      |

## Certification

Each entry is a run by Atlantic Agentic Labs, newest first. Only a run against the vendor’s sandbox or a client environment certifies a collector; a certification lasts six months, or less if the vendor publishes an API version the collector does not list. See [How collectors are certified](/collectors/certification/).

| Date             | Collector | Engine   | Vendor API             | Method                              | Expires        |
| ---------------- | --------- | -------- | ---------------------- | ----------------------------------- | -------------- |
| 10 November 2026 | `1.0.0`   | `0.46.0` | Dataverse Web API v9.2 | Fixtures only: built, not certified | Not applicable |

## Security posture

From the collector’s last scan on the default branch. What each line means, and what blocks a release: [Security posture](/collectors/security/).

| Last scanned               | 10 November 2026                                                                                                                                                                                                      |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Critical findings          | 0                                                                                                                                                                                                                     |
| High findings              | 0                                                                                                                                                                                                                     |
| Medium findings            | 0                                                                                                                                                                                                                     |
| Low findings               | 0                                                                                                                                                                                                                     |
| Info findings              | 0                                                                                                                                                                                                                     |
| Release blocked            | No                                                                                                                                                                                                                    |
| Network allow-list check   | Pass                                                                                                                                                                                                                  |
| Read-only behavioural test | Pass                                                                                                                                                                                                                  |
| SBOM (CycloneDX)           | Produced                                                                                                                                                                                                              |
| Dependency licences        | Pass                                                                                                                                                                                                                  |
| Scanners                   | bandit 1.9.4, semgrep 1.181.1, pip-audit 2.10.1, osv-scanner 2.7.0, cyclonedx-py 7.5.0, pip-licenses 5.5.5, gitleaks repository job aal-secrets, hosts_check tools/hosts_check.py, read-only test pytest -m read_only |

Source: https://docs.atlanticagenticlabs.com/collectors/catalogue/dynamics/
