Do not use the OData v2.0 endpoint

Category: Supportability

Impact potential: High

Symptoms

There are no immediate symptoms, but code using this endpoint will stop working when the deprecated endpoint is removed.

We plan to remove this endpoint on April 30, 2023. OData v2.0 Service removal date announcement. The original removal date was November 11, 2022, but this was extended.

Guidance

You should change any code that depends on the Organization Data Service (OData v2.0) to use the Dataverse Web API (OData v4.0) endpoint instead.

For model-driven apps, you should use the Xrm.WebApi (Client API reference), which provides access to the Dataverse Web API for client-side extensions using JavaScript web resources.

Problematic patterns

The Organization Data Service uses this endpoint: /XRMServices/2011/OrganizationData.svc. You should look for any active code using this endpoint.

The Dynamics CRM SDK provided an example JavaScript library as a JavaScript Web Resource named sample_/Scripts/SDK.REST.js, which can be found here. The Xrm.WebApi (Client API reference) provides similar functions to create, update, delete, and retrieve records.

The Organization Data Service endpoint is also sometimes used by PowerShell scripts using Invoke-WebRequest.

Additional information

Organization Data Service is an OData v2.0 endpoint introduced with Dynamics CRM 2011. It was deprecated with Dynamics 365 Customer Engagement v8.0. Also known as the OData endpoint or REST endpoint when it was released, this endpoint only provides the ability to perform create, retrieve, update, and delete operations on tables.

Note

Both are OData endpoints, but there are differences in how they are implemented. Do not expect that existing code will work with only minor changes.

Some of the major differences are described below.

Resource names

Web API resource names for tables are based on the EntitySetName. Organization Data Service names had Set appended to the SchemaName. For example:

Web API Organization Data Service
accounts AccountSet
contacts ContactSet
tasks TaskSet

Column names

Column Names in Web API are all lower case using the LogicalName. With the Organization Data Service, column names use the SchemaName.

HTTP methods

Organization Data Service uses MERGE or PUT rather than PATCH to update a record.

Data format

Organization Data Service supports both JSON and ATOM. ATOM is an XML-based format usually used for RSS feeds. Web API only supports JSON.

Limits on number of records returned

Organization Data Service will only return 50 records at a time and doesn't provide a way to specify max page size.

Web API allows to set a max page size and will return up to 5000 records. More information: Limits on number of table rows (entities) returned.

Legacy documentation

Documentation describing the Organization Data Service is available here: Microsoft Dynamics 2015 SDK: Use the OData endpoint with web resources.

The following table connects related areas for the Organization Data Service and the Web API:

Organization Data Service Web API
Query Microsoft Dynamics CRM 2015 data using the OData endpoint
OData system query options using the OData endpoint
Query data
Web API Properties
Creating records Create a table row
Retrieving records Retrieve a table row
Updating records Basic update
Deleting records Basic delete
Using Deep insert Create related table rows in one operation
Updating individual properties Update a single property value
Associating and disassociating records Associate and disassociate table rows
OData endpoint Http status codes Identify status codes

Examples

This section highlights the differences between using the Organization Data Service and the Web API.

The Organization Data Service is only able to perform Create, Retrieve, Update, and Delete operations on tables. These examples show the differences between the services to help migrate to the Web API.

Query records

These examples show the differences between the Organization Data Service and the Web API when querying records.

The Organization Data Service has no way to manage paging other than using $top and $skip, but the maximum page size was limited to 50 records.

Request

GET  [Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet?$select=OwnershipCode,PrimaryContactId,OpenDeals_Date,Telephone1,NumberOfEmployees,Name,AccountNumber,DoNotPhone,IndustryCode&$filter=PrimaryContactId/Id ne null&$top=2 HTTP/1.1
Accept: application/json

Response

HTTP/1.1 200 OK
Cache-Control: no-cache
Allow: OPTIONS,GET,HEAD,POST
Content-Type: application/json;charset=utf-8

{
  "d": {
    "results": [
      {
        "__metadata": {
          "uri": " [Organization URI]/xrmservices/2011/OrganizationData.svc/AccountSet(guid'7a4814f9-b0b8-ea11-a812-000d3a122b89')",
          "type": "Microsoft.Crm.Sdk.Data.Services.Account"
        },
        "OwnershipCode": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
          },
          "Value": 2
        },
        "PrimaryContactId": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.EntityReference"
          },
          "Id": "dff27d1f-a61b-4bfe-a203-b2e5a36cda0e",
          "LogicalName": "contact",
          "Name": "Sam Smith",
          "RowVersion": null
        },
        "OpenDeals_Date": "/Date(1663715691000)/",
        "Telephone1": "555-1234",
        "NumberOfEmployees": 500,
        "Name": "Contoso, Ltd. (sample)",
        "AccountNumber": "1111",
        "DoNotPhone": false,
        "IndustryCode": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
          },
          "Value": 7
        }
      },
      {
        "__metadata": {
          "uri": " [Organization URI]/xrmservices/2011/OrganizationData.svc/AccountSet(guid'fed58509-4af3-ec11-bb3d-000d3a1a51c1')",
          "type": "Microsoft.Crm.Sdk.Data.Services.Account"
        },
        "OwnershipCode": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
          },
          "Value": null
        },
        "PrimaryContactId": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.EntityReference"
          },
          "Id": "ffd58509-4af3-ec11-bb3d-000d3a1a51c1",
          "LogicalName": "contact",
          "Name": "Susie Curtis",
          "RowVersion": null
        },
        "OpenDeals_Date": "/Date(1663715691000)/",
        "Telephone1": null,
        "NumberOfEmployees": null,
        "Name": "Fourth Coffee",
        "AccountNumber": null,
        "DoNotPhone": false,
        "IndustryCode": {
          "__metadata": {
            "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
          },
          "Value": null
        }
      }
    ]
  }
}

When more than 50 records were returned, there is a __next property to access the next page:

"__next": "https://[Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet?$select=OwnershipCode,PrimaryContactId,OpenDeals_Date,Telephone1,NumberOfEmployees,Name,AccountNumber,DoNotPhone,IndustryCode&$filter=PrimaryContactId/Id ne null&$skiptoken=1,'accountid','%7B22153355-851D-ED11-B83E-000D3A572421%7D','%7B7A4814F9-B0B8-EA11-A812-000D3A122B89%7D'"

Create records

These examples show the differences between the Organization Data Service and the Web API when creating records.

Request

POST [Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet HTTP/1.1
Accept: application/json
Content-Type: application/json

{
  "OwnershipCode": {
    "Value": 2
  },
  "PrimaryContactId": {
    "Id": "dff27d1f-a61b-4bfe-a203-b2e5a36cda0e",
    "LogicalName": "contact"
  },
  "OpenDeals_Date": "12/25/2022",
  "CustomerSizeCode": {
    "Value": 1
  },
  "Telephone1": "555-1234",
  "NumberOfEmployees": 500,
  "Name": "Contoso, Ltd. (sample)",
  "AccountNumber": "12225",
  "DoNotPhone": true,
  "IndustryCode": {
    "Value": 7
  }
}

Response

With the Organization Data Service all properties are returned when a record is created.

HTTP/1.1 201 Created
Content-Type: application/json;charset=utf-8
REQ_ID: a0c614be-50be-4c1e-9413-1c7ba459c5c9

{
  "d": {
    "__metadata": {
      "uri": "[Organization URI]/xrmservices/2011/OrganizationData.svc/AccountSet(guid'57d4d1af-7b38-ed11-9db0-002248296d7e')",
      "type": "Microsoft.Crm.Sdk.Data.Services.Account"
    },
    "AccountId": "57d4d1af-7b38-ed11-9db0-002248296d7e",

    <All properties are returned. Removed for brevity>

  }
}

Retrieve records

These examples show the differences between the Organization Data Service and the Web API when retrieving records.

Request

GET https://[Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet(guid'b68d56a6-4739-ed11-9db0-002248296d7e')?$select=OwnershipCode,PrimaryContactId,OpenDeals_Date,Telephone1,NumberOfEmployees,Name,AccountNumber,DoNotPhone,IndustryCode HTTP/1.1
Accept: application/json

Response

HTTP/1.1 200 OK

{
  "d": {
    "__metadata": {
      "uri": "https://[Organization URI]/xrmservices/2011/OrganizationData.svc/AccountSet(guid'b68d56a6-4739-ed11-9db0-002248296d7e')",
      "type": "Microsoft.Crm.Sdk.Data.Services.Account"
    },
    "OwnershipCode": {
      "__metadata": {
        "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
      },
      "Value": 2
    },
    "PrimaryContactId": {
      "__metadata": {
        "type": "Microsoft.Crm.Sdk.Data.Services.EntityReference"
      },
      "Id": "dff27d1f-a61b-4bfe-a203-b2e5a36cda0e",
      "LogicalName": "contact",
      "Name": "Sam Smith",
      "RowVersion": null
    },
    "OpenDeals_Date": "/Date(1663784098000)/",
    "Telephone1": "555-1234",
    "NumberOfEmployees": 500,
    "Name": "Contoso, Ltd. (sample)",
    "AccountNumber": "12227",
    "DoNotPhone": true,
    "IndustryCode": {
      "__metadata": {
        "type": "Microsoft.Crm.Sdk.Data.Services.OptionSetValue"
      },
      "Value": 7
    }
  }
}

Update records

These examples show the differences between the Organization Data Service and the Web API when updating records.

Organization Data Service requires the X-HTTP-Method: MERGE request header to be applied with a POST request.

Request

POST https://[Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet(guid'b68d56a6-4739-ed11-9db0-002248296d7e') HTTP/1.1
Accept: application/json
X-HTTP-Method: MERGE
Content-Type: application/json

{
  "OwnershipCode": {
    "Value": 3
  },
  "PrimaryContactId": {
    "Id": "6db0be2e-d01c-ed11-b83e-000d3a572421"
  },
  "OpenDeals_Date": "12/26/2022",
  "Telephone1": "555-1235",
  "NumberOfEmployees": 501,
  "Name": "Contoso, Ltd.",
  "AccountNumber": "12228",
  "DoNotPhone": false,
  "IndustryCode": {
    "Value": 6
  }
}

Response

HTTP/1.1 204 No Content

Delete records

These examples show the differences between the Organization Data Service and the Web API when deleting records.

Request

DELETE https://[Organization URI]/XRMServices/2011/OrganizationData.svc/AccountSet(guid'b68d56a6-4739-ed11-9db0-002248296d7e') HTTP/1.1
Accept: application/json

Response

HTTP/1.1 204 No Content

See Also

How to use Application Insights to identify usage of the OrganizationData.svc endpoint which is planned for retirement in November 2022 (Community Forum)
How to use Solution Checker to identify usage of the OrganizationData.svc endpoint which is planned for retirement in November 2022 (Community Forum)
Use the Microsoft Dataverse Web API