Skip to main content

Dynamics 365 Web API: How to Perform Multiple POST or Upsert Operations

Dynamics 365 Web API: How to Perform Multiple POST or Upsert Operations

Dynamics 365 Web API: How to Perform Multiple POST or Upsert Operations

The Dynamics 365 Web API provides a powerful way to interact with data in a structured and scalable manner. Among its most efficient — yet often underutilized — capabilities is the ability to perform multiple record operations (batch requests) or upserts (insert or update) in a single call.

This article walks you through how to correctly build URIs, structure JSON payloads, handle lookup bindings using @odata.bind, and understand how Dynamics 365 interprets and processes these requests internally.


🧩 1. What Is an Upsert Operation?

An Upsert is a hybrid between two common database operations:

  • Insert (POST): Creates a new record.
  • Update (PATCH): Updates an existing record.

Dynamics 365 automatically determines whether to insert or update based on whether a record with the specified Alternate Key already exists.

Alternate Keys are unique identifiers you define in the Dataverse schema (e.g., new_ordercode, new_customercode). They allow external systems to perform data synchronization without relying on internal GUIDs, making integration much more reliable and maintainable.


🌐 2. Understanding the Web API URI Structure

Every Dynamics 365 Web API request follows the same general pattern:

https://<organization_name>.crmX.dynamics.com/api/data/v9.2/

Where:

  • <organization_name> is your environment name.
  • crmX depends on your region (e.g., crm4, crm11).
  • v9.2 is the API version.

Entity sets use the plural logical name of the entity. For example:

https://<organization_name>.crmX.dynamics.com/api/data/v9.2/new_orders

To perform a multiple-record Upsert operation, the endpoint looks like this:

https://<organization_name>.crmX.dynamics.com/api/data/v9.2/new_orders/Microsoft.Dynamics.CRM.UpsertMultiple

This special action allows you to create or update multiple records in a single request, improving performance and reducing API traffic.


🧱 3. JSON Structure for Multiple Upserts

The body of an UpsertMultiple request includes an array of items under the Items property. Each item represents a record to be created or updated.

{
  "Items": [
    {
      "@odata.type": "Microsoft.Dynamics.CRM.new_order",
      "new_name": "Order 001",
      "@odata.id": "new_orders(new_ordercode='ORD-001')",
      "new_CustomerId@odata.bind": "/new_customers(new_customercode='CUST-1001')",
      "new_totalamount": 2500.75
    },
    {
      "@odata.type": "Microsoft.Dynamics.CRM.new_customer",
      "new_name": "Global Distribution Ltd.",
      "@odata.id": "new_customers(new_customercode='CUST-1001')",
      "new_email": "info@globaldistribution.com"
    }
  ]
}

🔍 4. JSON Field Breakdown

PropertyDescription
@odata.typeDefines the entity logical name in Dynamics (e.g., Microsoft.Dynamics.CRM.new_order).
@odata.idSpecifies the Alternate Key used to determine whether the record already exists.
@odata.bindUsed to link one record to another (e.g., linking an order to a customer).
Custom FieldsSuch as new_name, new_totalamount, etc., represent actual attributes on your entity.

🔗 5. How @odata.bind Works — and Why Schema Case Matters

The @odata.bind suffix is used to establish relationships between entities without using GUIDs.

"new_CustomerId@odata.bind": "/new_customers(new_customercode='CUST-1001')"

Here:

  • new_CustomerId refers to the Schema Name of the lookup field in Dynamics 365. The uppercase “C” and “I” are intentional and must exactly match the Schema Name defined in your Dataverse model. If you change the casing or use the display name, the API will return an error.
  • /new_customers(...) points to the related entity set.
  • new_customercode is the alternate key identifying the specific customer.

When Dynamics receives this reference:

  1. It checks if a record with new_customercode = 'CUST-1001' exists.
  2. If found → it links the order to that customer.
  3. If not → it creates the customer (if included in the same payload) and then establishes the relationship.

This mechanism enables seamless data integrity and eliminates the need to manually retrieve GUIDs before linking entities.


⚙️ 6. How Dynamics Internally Processes the UpsertMultiple Operation

When you send a multiple upsert request, the Web API executes a structured sequence of operations:

  1. Validate the request body – Ensures all entity names and fields exist.
  2. Iterate over each item in the Items array.
  3. For each record:
    • Check if a record exists using the Alternate Key or the specified @odata.id.
    • If it exists → perform an update operation.
    • If not → perform a create operation.
  4. Resolve lookups – process any @odata.bind relationships, creating referenced records if necessary.
  5. Apply the transaction – depending on your organization’s configuration, all operations can be processed in a single transaction or individually.
  6. Return a structured response – indicating the result (success or failure) of each item in the batch.

This approach dramatically improves performance for integration scenarios — for example, synchronizing thousands of records from ERP systems, external CRMs, or e-commerce platforms.


🧠 7. Key Considerations When Using Alternate Keys

Before you can use alternate keys for upsert operations, ensure that:

  • The Alternate Key field is configured and indexed in your Dataverse environment.
  • The field you use as a key is unique and non-nullable.
  • You can have multiple Alternate Keys per entity, but each one must uniquely identify a record.
  • Once created, the Alternate Key cannot be deleted if it’s referenced by other processes (e.g., Power Automate or integrations).

Tip: When integrating with external systems, use human-readable keys (like ORDER-001, CUST-0005) rather than system-generated codes. This simplifies debugging and makes logs easier to interpret.


🧩 8. Common Pitfalls and How to Avoid Them

IssueCauseHow to Fix
400 Bad Request: Property not found Using the display name or incorrect casing instead of the Schema Name. Verify the exact Schema Name in the entity designer (e.g., new_CustomerId).
404 Not Found The referenced record in @odata.bind doesn’t exist and isn’t included in the same batch. Ensure the target entity is either created in the same request or exists in Dataverse.
Duplicate records created The alternate key is missing or incorrectly defined. Check the entity’s key configuration under Advanced Settings → Customizations → Keys.
Timeout errors Sending very large payloads in one request. Break data into smaller batches (e.g., 500–1000 items per request).

✅ 9. Best Practices for Reliable Integrations

  • Always use Schema Names for all attributes, especially lookups.
  • Keep payloads lightweight — include only required fields.
  • Define Alternate Keys on both primary and related entities.
  • Validate payloads before sending (missing commas or invalid property names are common sources of errors).
  • Log both the request and the response for traceability.
  • If working with Power Automate or custom connectors, test your JSON payload in Postman first to confirm it’s valid.

🚀 10. Final Thoughts

Mastering UpsertMultiple in Dynamics 365 Web API is a game-changer for any developer or integration specialist. It allows you to:

  • Reduce the number of API calls.
  • Avoid duplicate records.
  • Maintain relationships seamlessly across entities.
  • Synchronize large datasets efficiently.

Understanding how Dynamics interprets the JSON structure — particularly how it handles Alternate Keys and Schema-based lookup bindings — is essential for building robust, scalable, and professional-grade integrations.

Comments

Popular posts from this blog

Dynamics 365 CRM – Managing Translations in JavaScript with RESX Files

Dynamics 365 CRM – Managing Translations in JavaScript with RESX Files Dynamics 365 CRM – Managing Translations in JavaScript with RESX Files In multi-language environments within Dynamics 365 CRM , it is common to display localized messages in alerts, pop-ups, or validation logic. A robust solution is to use .resx resource files together with Xrm.Utility.getResourceString in JavaScript. Retrieving a Translation The standard pattern to retrieve a translated message is: Xrm.Utility.getResourceString( namespace.localization.webResourceName, namespace.localization.messageKey ); webResourceName : the name of the .resx resource file, without specifying a language ID. Dynamics automatically loads the correct language based on the user’s settings. messageKey : the key defined in the .resx file that contains the translated message. Best Practices for Structuring Keys Organizing translations in a c...

SSIS (.dtsx in Visual Studio) vs XrmToolBox — Data Transporter

SSIS (.dtsx in Visual Studio) vs XrmToolBox — Data Transporter SSIS (.dtsx in Visual Studio) vs XrmToolBox — Data Transporter Technical Comparison and Practical Guide for Moving Data Between Dynamics 365 / Dataverse Environments Moving data between environments (dev → test → prod) is something every team working with Dynamics 365 / Dataverse does frequently. There are two common operational approaches: Classic SSIS (Visual Studio .dtsx packages with Data Flow, Lookups, Scripts, SQL staging, etc.) — an industrial ETL/ELT approach. XrmToolBox – Data Transporter (a lightweight plugin for copying records between organizations) — a manual, fast, developer-oriented approach. Below we break down the real differences, risks, and practical recommendations for each method. 1) Architecture and Philosophy SSIS (.dtsx in Visual Studio) ETL/ELT architecture: connect to sources (SQL, CSV, APIs), transform (Derived Column, Lookup, Script Component) and load into Dat...