Microsoft Dynamics 365 Finance & Operations Connector Guide

The Microsoft Dynamics 365 Finance & Operations connector allows Tealfabric workflows to exchange ERP data through Dynamics data entities and OData endpoints. It is designed for reliable operational automations such as customer synchronization, order orchestration, and finance process handoffs.

Document information
FieldValue
Canonical URL/docs/04_connecting-systems/connectors/m/microsoft-dynamics-fo
Version (published date)2026-05-08
Tagsconnectors, reference, microsoft-dynamics-fo
Connector IDmicrosoft-dynamics-fo-1.0.0

Microsoft Dynamics 365 Finance and Operations connector flow showing Azure AD authentication, data entity writes, OData reads, and workflow decisions based on ERP state.

When to use this connector

Use this connector when workflows must write business records to Dynamics F&O or read entity data to drive downstream actions. Typical use cases include syncing customers, checking open transactions, and moving approved data into accounting or supply-chain processes. The connector is most effective when integrations clearly separate read and write responsibilities and include retry-safe execution logic.

Prerequisites

Before creating workflows, register an Azure AD application with permissions to your Dynamics F&O environment and confirm that required data entities are available. Collect connection settings and validate API access in a non-production environment before promotion. Define operational ownership for credentials and access reviews to reduce integration risk.

Configuration

Set these values in the integration profile:

  • base_url (required): Dynamics F&O environment URL.
  • tenant_id (required): Microsoft Entra tenant identifier.
  • client_id (required): Application client ID.
  • client_secret (required): Application client secret.
  • timeout_seconds (optional): Request timeout in seconds.

Write customer data with send

Use send for create or update flows that push business data into Dynamics F&O entities. Keep payload fields aligned with the target entity definition and validate required attributes before runtime.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type DynamicsWriteResult = {
  entity_key?: string;
  status?: string;
};

async function createCustomer(integrationId: string): Promise<DynamicsWriteResult> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "send",
        endpoint: "data/CustomersV3",
        method: "POST",
        data: {
          dataAreaId: "USMF",
          CustomerAccount: "CUST-10508",
          OrganizationName: "Acme Components",
          CurrencyCode: "USD",
          CustomerGroupId: "10",
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as { result?: DynamicsWriteResult };
  if (!payload.result) throw new Error("Missing Dynamics write payload");
  return payload.result;
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "send",
    "endpoint": "data/CustomersV3",
    "method": "POST",
    "data": {
      "dataAreaId": "USMF",
      "CustomerAccount": "CUST-10508",
      "OrganizationName": "Acme Components",
      "CurrencyCode": "USD",
      "CustomerGroupId": "10"
    }
  }'
{
  "success": true,
  "result": {
    "entity_key": "CUST-10508",
    "status": "created"
  }
}

Read open sales orders with receive

Use receive to query Dynamics F&O entities through OData-style filters and pagination values. This pattern is useful for scheduled jobs that gather operational records for fulfillment, reconciliation, or reporting.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type SalesOrder = {
  SalesOrderNumber?: string;
  CustomerAccount?: string;
  OrderStatus?: string;
};

async function listOpenSalesOrders(integrationId: string): Promise<SalesOrder[]> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "receive",
        endpoint: "data/SalesOrderHeadersV2",
        query: {
          "filter": "OrderStatus eq Microsoft.Dynamics.DataEntities.SalesStatus"Backorder"",
          "top": 20,
          "skip": 0,
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as { data?: SalesOrder[] };
  if (!payload.data) throw new Error("Missing Dynamics receive payload");
  return payload.data;
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "receive",
    "endpoint": "data/SalesOrderHeadersV2",
    "query": {
      "$filter": "OrderStatus eq Microsoft.Dynamics.DataEntities.SalesStatus'\''Backorder'\''",
      "$top": 20,
      "$skip": 0
    }
  }'
{
  "success": true,
  "data": [
    {
      "SalesOrderNumber": "SO-001245",
      "CustomerAccount": "CUST-10508",
      "OrderStatus": "Backorder"
    }
  ],
  "record_count": 1
}

Reliability guidance

Use a lower top value and incremental checkpoints for high-volume entity pulls so retries remain bounded and observable. Handle 429 and transient network failures with backoff and idempotent workflow logic to avoid duplicate posting. Keep credentials in secure storage, rotate secrets on a schedule, and review app permissions regularly as business processes evolve.

Related references