Updating lookup fields in SharePoint via the REST API is a common task, yet it often trips up developers because the syntax differs from standard text or number fields. When you query a list item using $select and $expand, you see the display value of the lookup, but when it comes time to perform an update, the API expects something different.

In this guide, you will learn the exact syntax required to update both single and multi-value lookup fields using the SharePoint REST API, along with specific nuances for Power Automate and legacy environments.

The Secret: The "Id" Suffix Convention

When you create a lookup field in a SharePoint list, SharePoint implicitly creates a secondary internal field specifically for the ID of the related item. To update a lookup value via the REST API, you do not target the display name of the field; instead, you target this internal ID field.

As a general rule, the name of this implicit field is your Internal Field Name + Id. For example, if your lookup column is named State, the REST API expects you to send data to a property named StateId.

How to Update a Single Lookup Field

To update a single-select lookup field, you simply pass the integer ID of the item from the source list. This is the most efficient way to link items because it bypasses the need for the API to resolve text strings.

Here is a practical example using jQuery to update a lookup field named "State" in a list called "Sales Opportunities":

var call = jQuery.ajax({
    url: _spPageContextInfo.webAbsoluteUrl +
        "/_api/Web/Lists/getByTitle('Sales Opportunities')/Items(5)",
    type: "POST",
    data: JSON.stringify({
        "__metadata": { type: "SP.Data.Sales_x0020_OpportunitiesListItem" },
        StateId: 2 // 'State' is the lookup field, '2' is the ID of the target item
    }),
    headers: {
        Accept: "application/json;odata=verbose",
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
        "IF-MATCH": "*",
        "X-Http-Method": "PATCH"
    }
});

Understanding the Headers

  • X-Http-Method: We use PATCH (or MERGE) to perform a partial update. This ensures we only change the lookup field without overwriting the entire item.
  • IF-MATCH: Using "*" tells SharePoint to overwrite the item regardless of version mismatches. In a production environment, you might prefer to use a specific ETag for concurrency control.
  • __metadata: The type string is crucial. It usually follows the pattern SP.Data.[ListName]ListItem. Note that spaces in list names are often encoded as _x0020_.

Handling Multi-Value Lookup Fields

If your lookup column allows multiple selections, passing a single integer will result in an error. Multi-value lookups require a specific object structure containing an array of IDs.

To update a multi-value lookup field (e.g., a field named "Projects"), use the following format:

var itemProperties = {
    "__metadata": { "type": 'SP.Data.TasksListItem' }, 
    "ProjectsId": { "results": [1, 3, 5] } // Array of IDs for the target items
};

$.ajax({
    url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Tasks')/items(4)",
    type: "POST",
    contentType: "application/json;odata=verbose",
    data: JSON.stringify(itemProperties),
    headers: {
        "Accept": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(),
        "X-HTTP-Method": "MERGE",
        "If-Match": '*'
    }
});

In this scenario, the results key is mandatory. It tells SharePoint to clear any existing values and replace them with the IDs provided in the array.

Special Case: Power Automate "Send an HTTP Request"

When using the Send an HTTP request to SharePoint action in Power Automate (formerly Microsoft Flow), you may find that the FieldNameId convention occasionally fails or behaves inconsistently depending on the API version being used.

In these cases, use the following nested object syntax instead:

{
    "lookup_field_name": {
        "Id": 10
    }
}

This explicitly defines the object relationship and is often more robust within the Power Platform ecosystem.

Legacy Support: SPServices and SOAP

While the REST API is the modern standard, some developers maintaining legacy SharePoint On-Premises environments (like 2010 or 2013) may still use SPServices. If you are using the UpdateListItems method via SOAP, the format changes significantly to a string-based identifier:

$().SPServices({
   operation: "UpdateListItems",
   async: false,
   listName: "Sales Opportunities",
   ID: 5,
   valuepairs: [["State", "2;#Rhode Island"]], // ID followed by the display value
   completefunc: function (xData, Status) {
      console.log("Update successful");
   }
});

In this older format, you provide the ID, a separator sequence (;#), and the text value of the lookup.

Frequently Asked Questions

How do I find the correct internal name for my lookup field?

Navigate to your List Settings and click on the column name. Look at the URL in your browser; the internal name is located at the very end of the URL string after Field=. This is the name you should append Id to for your REST calls.

Can I update a lookup field using the text value instead of the ID?

No. The SharePoint REST API requires the integer ID of the item in the source list. If you only have the text value, you must first perform a separate GET request to the source list to retrieve the corresponding ID before performing your update.

What happens if I provide an ID that doesn't exist?

SharePoint will return a 400 Bad Request error. Always ensure the ID you are passing exists in the target list to avoid runtime exceptions.

Wrapping Up

Updating lookup fields via the SharePoint REST API boils down to two main rules: 1. Append "Id" to the internal field name for single-value lookups. 2. Use the "results" array for multi-value lookups.

By following these patterns and ensuring your __metadata type is correctly defined, you can seamlessly integrate complex data relationships into your SharePoint applications. Whether you are building a custom SPFx web part or a Power Automate workflow, these techniques ensure your data remains consistent and your integrations remain robust.