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

# Microsoft Dynamics 365 Sales Integration for AI Agents & Workflows

> CRM platform for managing accounts, contacts, appointments, and custom entities via the Dynamics 365 Web API

{/* Self-hosted logo — build-time vendored from modulex.json / Iconify (see scripts/lib/logo.js). */}

<img src="https://mintcdn.com/modulexaillc/df8MOr-hXotYLTh5/logos/microsoft-dynamics-365-sales.svg?fit=max&auto=format&n=df8MOr-hXotYLTh5&q=85&s=e28b336329ba15ff2008fd738d28f560" alt="Microsoft Dynamics 365 Sales logo" width="72" height="72" data-path="logos/microsoft-dynamics-365-sales.svg" />

## Overview

Add **Microsoft Dynamics 365 Sales** to any ModuleX agent or workflow. CRM platform integration for managing accounts, contacts, appointments, and custom entities via the Dynamics 365 Web API (`https://{org}.crm.dynamics.com/api/data/v9.2`).

<Info>
  **Categories**: CRM · Sales · Productivity & Collaboration · **Auth**: OAuth2 · **Actions**: 11
</Info>

## Authentication

### OAuth2 Authentication

Connect using Microsoft OAuth2 (recommended)

#### Required Credentials

| Field                     | Description                                                         | Required | Format                                 |
| ------------------------- | ------------------------------------------------------------------- | -------- | -------------------------------------- |
| Client ID                 | Microsoft Entra (Azure AD) OAuth App Client ID                      | Yes      | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Client Secret             | Microsoft Entra (Azure AD) OAuth App Client Secret                  | Yes      | `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` |
| Dynamics 365 Instance URL | Your Dynamics 365 org URL hostname (e.g. org12345.crm.dynamics.com) | Yes      | `org12345.crm.dynamics.com`            |

#### OAuth Configuration

* **Authorization URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/authorize`
* **Token URL**: `https://login.microsoftonline.com/common/oauth2/v2.0/token`
* **Scopes**: `https://dynamics.microsoft.com/user_impersonation`, `offline_access`

## Available Actions

<AccordionGroup>
  <Accordion title="create_appointment — Create a new appointment linked to an account with a required attendee (system user)">
    ### Parameters

    <ResponseField name="subject" type="string" required>
      Title of the appointment
    </ResponseField>

    <ResponseField name="scheduledstart" type="string" required>
      Start date/time in ISO 8601 format (e.g. 2026-02-20T12:00:00Z)
    </ResponseField>

    <ResponseField name="scheduledend" type="string" required>
      End date/time in ISO 8601 format
    </ResponseField>

    <ResponseField name="regarding_account_id" type="string" required>
      Account ID the appointment is regarding
    </ResponseField>

    <ResponseField name="required_attendee_email" type="string" required>
      Email address of the Dynamics system user to add as attendee
    </ResponseField>

    <ResponseField name="category" type="integer">
      Optional category value (numeric). Use list\_appointment\_categories to discover valid values
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "appointment_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Appointment Id"
        },
        "deep_link": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Deep Link"
        },
        "appointment": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Appointment"
        }
      },
      "required": [
        "success"
      ],
      "title": "CreateAppointmentOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="create_custom_entity — Create a custom entity definition in Dynamics 365">
    ### Parameters

    <ResponseField name="solution_id" type="string" required>
      Identifier of the solution to associate the entity with
    </ResponseField>

    <ResponseField name="display_name" type="string" required>
      Display name for the new entity (e.g. 'Bank Account')
    </ResponseField>

    <ResponseField name="primary_attribute" type="string" required>
      Primary name attribute of the new entity (e.g. 'Account Name')
    </ResponseField>

    <ResponseField name="language_code" type="integer">
      Language code (e.g. 1033 for English US) (Default: `1033`)
    </ResponseField>

    <ResponseField name="additional_attributes" type="object">
      Array of attribute definition objects to add to the entity
    </ResponseField>

    <ResponseField name="description" type="string">
      Description of the new entity
    </ResponseField>

    <ResponseField name="has_activities" type="boolean">
      Whether the entity supports activities (Default: `false`)
    </ResponseField>

    <ResponseField name="has_notes" type="boolean">
      Whether the entity supports notes (Default: `false`)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "entity": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Entity"
        }
      },
      "required": [
        "success"
      ],
      "title": "CreateCustomEntityOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="find_contact — Search for a contact by ID, name, or custom OData filter">
    ### Parameters

    <ResponseField name="contact_id" type="string">
      Contact GUID to look up directly
    </ResponseField>

    <ResponseField name="name" type="string">
      Find contacts whose full name contains this value
    </ResponseField>

    <ResponseField name="filter" type="string">
      Custom OData \$filter expression (e.g. "lastname eq 'Smith'")
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "contacts": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Contacts",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "FindContactOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="get_account — Retrieve a single account by its GUID">
    ### Parameters

    <ResponseField name="account_id" type="string" required>
      Account GUID to retrieve
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "account": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Account"
        }
      },
      "required": [
        "success"
      ],
      "title": "GetAccountOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_accounts — List accounts with optional OData filter and pagination">
    ### Parameters

    <ResponseField name="filter" type="string">
      Optional OData \$filter (e.g. 'statecode eq 0' for active accounts)
    </ResponseField>

    <ResponseField name="records_per_page" type="integer">
      Number of records per page (max 5000) (Default: `50`)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "accounts": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Accounts",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListAccountsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_appointment_categories — List available appointment category values from metadata or existing rows">
    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "category_type": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Category Type"
        },
        "categories": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Categories",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListAppointmentCategoriesOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_appointment_category_options — Retrieve available options for the appointment Category picklist field">
    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "options": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Options",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListAppointmentCategoryOptionsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_appointments — List appointments ordered by scheduled start descending">
    ### Parameters

    <ResponseField name="filter" type="string">
      Optional OData \$filter (e.g. 'statecode eq 0')
    </ResponseField>

    <ResponseField name="records_per_page" type="integer">
      Number of appointments to return (max 100) (Default: `25`)
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "appointments": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Appointments",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListAppointmentsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="list_solution_id_options — Retrieve available solutions with their IDs and names">
    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "solutions": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Solutions",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "ListSolutionIdOptionsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="search_accounts — Search accounts by company name substring">
    ### Parameters

    <ResponseField name="search_term" type="string" required>
      Substring to match against account name
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "accounts": {
          "items": {
            "additionalProperties": true,
            "type": "object"
          },
          "title": "Accounts",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "SearchAccountsOutput",
      "type": "object"
    }
    ```
  </Accordion>

  <Accordion title="update_appointment — Update an existing appointment (only supplied fields are modified)">
    ### Parameters

    <ResponseField name="appointment_id" type="string" required>
      Appointment activity GUID to update
    </ResponseField>

    <ResponseField name="subject" type="string">
      Updated subject/title
    </ResponseField>

    <ResponseField name="scheduledstart" type="string">
      Updated start in ISO 8601
    </ResponseField>

    <ResponseField name="scheduledend" type="string">
      Updated end in ISO 8601
    </ResponseField>

    <ResponseField name="category" type="integer">
      Updated category value (numeric). Use list\_appointment\_categories to discover valid values
    </ResponseField>

    ### Response

    ```json theme={null}
    {
      "additionalProperties": false,
      "properties": {
        "success": {
          "title": "Success",
          "type": "boolean"
        },
        "error": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Error"
        },
        "appointment_id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Appointment Id"
        },
        "updated_fields": {
          "items": {
            "type": "string"
          },
          "title": "Updated Fields",
          "type": "array"
        }
      },
      "required": [
        "success"
      ],
      "title": "UpdateAppointmentOutput",
      "type": "object"
    }
    ```
  </Accordion>
</AccordionGroup>

## Limits & Quotas

* **API limits**: Dynamics 365 enforces per-org service protection limits (typically 6,000 requests per 5-minute sliding window per user).
* **Throttling**: Returns HTTP 429 when limits are exceeded; retry after the `Retry-After` header value.
* **Error model**: Non-2xx responses are caught and returned as `success=False` + `error` rather than raising.

## Related integrations

<CardGroup cols={3}>
  <Card title="Insightly" href="/integrations/tools/insightly" />

  <Card title="Clay" href="/integrations/tools/clay" />

  <Card title="Dropcontact" href="/integrations/tools/dropcontact" />
</CardGroup>

## Links

* [Microsoft Dynamics 365 Sales](https://dynamics.microsoft.com)
