[DEPRECATED] Send Outlook REST requests in batches (version 2.0)

Applies to: Exchange Online | Office 365 | Hotmail.com | Live.com | MSN.com | Outlook.com | Passport.com

Note

Version 2.0 of the Outlook REST API is deprecated.

As announced on November 17, 2020, version 2.0 of the Outlook REST API has been deprecated. The v2.0 REST endpoint will be fully decommissioned in November 2022, and the v2.0 documentation will be removed shortly afterwards. Migrate existing apps to use Microsoft Graph. See a comparison to start your migration.

Batching allows you to put multiple Outlook REST requests in a single HTTP batch request, reducing the number of HTTP connections and overhead. The requests in a batch access the data of the signed-in user, secured by Azure Active Directory in Office 365, or in a Microsoft account (Hotmail.com, Live.com, MSN.com, Outlook.com, or Passport.com).

Note

For simplicity of reference, the rest of this article uses Outlook.com to include these Microsoft account domains.

Not interested in v2.0 of the API? In the table of contents on the left, go to the Office 365 REST API reference section and select the version you want.

Overview

A REST request requires an HTTP connection between the client and server, which incurs a certain amount of overhead. Batching enables you to reduce connection overhead by combining multiple REST API calls for the same context into a single HTTP POST request to the $batch endpoint.

For example, you can combine API calls for the me context like this:

POST https://outlook.office.com/api/v2.0/me/$batch

A batch request can include up to 20 individual REST API calls, which can be data query (e.g. GET) or change (e.g. POST) operations. You can specify a Prefer header to have the batch continue even when one or more REST calls fail.

Batching is especially useful in synchronizing large amounts of data. API calls in the same batch can access different resources, such as messages and events, that belong to the same mailbox.

If you need to make more than 20 calls, or if the order of completing calls matters, use multiple batch requests.

Example

A simple example best illustrates batching. The following batch request puts 2 Outlook REST API calls in a single batch for the me context:

  1. GET all the events of the signed-in user.
  2. POST and send a message.

Batch request

POST https://outlook.office.com/api/v2.0/me/$batch HTTP/1.1

Authorization: Bearer aGFwcHlnQGRr==
Host: outlook.office.com
Content-Type: multipart/mixed; boundary=batch_myBatchId


--batch_myBatchId
Content-Type: application/http
Content-Transfer-Encoding: binary

GET /api/v2.0/me/events?$select=subject,organizer HTTP/1.1

--batch_myBatchId
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /api/v2.0/me/sendmail HTTP/1.1
Content-Type: application/json

{
  "Message": {
    "Subject": "Meet for lunch?",
    "Body": {
      "ContentType": "Text",
      "Content": "The new cafeteria is open."
    },
    "ToRecipients": [
      {
        "EmailAddress": {
          "Address": "rufus@contoso.com"
        }
      }
    ]
  }
}

--batch_myBatchId--

Note

In the preceding example that has a POST operation at the end of the batch, currently a new line is required after the very last batch delimiter --batch_{batchId}--. See more formatting notes for batch request bodies.

Batch response

The batch response includes separate response codes and bodies, where applicable, for the batch request and individual calls.

HTTP/1.1 200 OK
Content-Type: multipart/mixed; boundary=batchresponse_caad32b6-3fa6-4346-94d0-ee98e067318a
Content-Length: 786

--batchresponse_caad32b6-3fa6-4346-94d0-ee98e067318a
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8

{
    "@odata.context":"https://outlook.office.com/api/v2.0/$metadata#Me/Events(Subject,Organizer)",
    "value":[
        {
            "@odata.id":"https://outlook.office.com/api/v2.0/Users('cd209b0b-3f83-4c35-82d2-d88a61820480@8b5d41d8-b1af-495e-b871-8bbd867ba67a')/Events('AAMkAGI1AAAt9AHkAAA=')",
            "@odata.etag":"W/\"ZlnW4RIAV06KYYwlrfNZvQAALfZeSA==\"",
            "Id":"AAMkAGI1AAAt9AHkAAA=",
            "Subject":"Let's go for lunch",
            "Organizer":{
                "EmailAddress":{
                    "Name":"Dana Swope",
                    "Address":"danas@contoso.onmicrosoft.com"
                }
            }
        },
        {
            "@odata.id":"https://outlook.office.com/api/v2.0/Users('cd209b0b-3f83-4c35-82d2-d88a61820480@8b5d41d8-b1af-495e-b871-8bbd867ba67a')/Events('AAMkAGI1AAAtCq6LAAA=')",
            "@odata.etag":"W/\"ZlnW4RIAV06KYYwlrfNZvQAALQzodA==\"",
            "Id":"AAMkAGI1AAAtCq6LAAA=",
            "Subject":"Prep for customer visit",
            "Organizer":{
                "EmailAddress":{
                    "Name":"Dana Swope",
                    "Address":"danas@contoso.onmicrosoft.com"
                }
            }
        }
    ]
}
--batchresponse_caad32b6-3fa6-4346-94d0-ee98e067318a
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 202 Accepted

--batchresponse_caad32b6-3fa6-4346-94d0-ee98e067318a--

Endpoint URL

You can do a POST on the $batch endpoint for one of 2 contexts:

  • For the signed-in user me:

    POST https://outlook.office.com/api/v2.0/me/$batch HTTP/1.1
    
  • For a specific user, where user_id can be a user ID or user email address:

    POST https://outlook.office.com/api/v2.0/users('{user_id}')/$batch
    

Once you have established the context in the POST request to the $batch endpoint, all the REST API calls included in the same batch request must apply to the same context.

Important

  • If your batch request is for a specific user, make sure you reference the user in a consistent way throughout the set of batched requests. That is, use only .../users('{user_id}') or .../users/'{user_id}' but not both.
  • When using the root URL https://outlook.office.com, for optimal performance, add an x-AnchorMailbox header and set it to the user's email address.
  • Handle the case where an Outlook.com user's mailbox has not yet been enabled for the Outlook REST API; check for the error codes MailboxNotEnabledForRESTAPI and MailboxNotSupportedForRESTAPI. See more information here.

Note

For developers in China

  • If you are developing apps for Office 365 in China, you should continue to use the API endpoints of Office 365 for China.
  • If you are creating apps for Outlook.com in China, you must use the v2 app model preview, and the following Outlook REST endpoint: https://outlook.office.com/api/{version}

Version of API

Batching has been promoted from preview to General Availability (GA) status. It is supported in the v2.0 and beta versions of the Outlook REST API.

You must specify the same host and version in the batch request as in the REST calls in the batch.

Target user

You can group Outlook REST API calls for the same mailbox in a batch. The mailbox can be on Office 365 or Outlook.com. Attempting to access more than one mailbox in a set of batched requests results in an exception.

Authentication

Similar to sending Outlook REST API calls as individual requests, you should include a valid access token in an Authorization request header. If you specify that header for the batch request, then the access token should provide the necessary permission for all the calls in that batch. Optionally you can specify an access token for a specific call in the batch if that call requires a different access token.

Getting an access token requires you to have registered and identified your app, and obtained the appropriate authorization. Find out more about some streamlined registration and authorization options for you. Keep this in mind as you learn more about batching requests.

Batch request headers

Include the following headers for each batch request:

Host: outlook.office.com
Content-Type: multipart/mixed; boundary=batch_<batchId>

where {batchId} identifies a batch and is used to delimit requests within the batch. It can be a GUID or any distinguishing string.

You can include other headers where appropriate. Except for content-related headers such as Content-Type, headers in the batch request generally apply to every operation in the batch. If you specify a header in both the batch request and a specific operation in the batch, the latter takes precedence and applies to that operation.

Batch request body

Start each operation within a batch with the following header lines:

--batch_{batchId}
Content-Type: application/http
Content-Transfer-Encoding: binary

End the last operation in the batch with this:

--batch_{batchId}--

Formatting a batch request body

Note the following formatting requirements, otherwise your batch request may fail or may not return the expected responses:

  • Make sure you have an additional new line before a batch boundary delimiter, as shown in the following request body that has 2 batched GET operations.
  • In particular, if you have a POST request at the end of a batch similar to the first example batch request, make sure there is a new line after the very last batch delimiter --batch_{batchId}--.

You can see more examples of batch request bodies in Batch Processing (OData Version 3.0).


--batch_{batchId}
Content-Type: application/http
Content-Transfer-Encoding: binary

GET  /api/v2.0/me/messages    HTTP/1.1

--batch_{batchId}
Content-Type: application/http
Content-Transfer-Encoding: binary

GET  /api/v2.0/me/events    HTTP/1.1

--batch_{batchId}--

Operations in a batch

You can specify up to 20 operations in a batch request.

An operation in a batch can be a data query, modification, action, or function invocation request. While you don't have to repeat full URLs and state all headers for each operation in the batch, make sure to include specific headers and request body if they are required for an operation.

Supported formats of requests in a batch

As mentioned above, the host, version, and context have to remain consistent throughout a set of batched requests. Requests included in the same batch can be a mix of any of the following 3 formats. For the examples below, assume the POST request to the $batch endpoint looks like this:

POST https://outlook.office.com/api/v2.0/me/$batch HTTP/1.1

Absolute URL

Include the host, version, and context in the URL. For example:

GET https://outlook.office.com/api/v2.0/me/messages?$select=subject,sender HTTP/1.1

URL relative to the host

Include a URL relative to the host specified in the batch request. While you don't repeat the host in each batched request, you do include the version and context. For example:

GET /api/v2.0/me/messages?$select=subject,sender HTTP/1.1

URL relative to the batch

In this format, you don't repeat the host, version, and context in the batched request. For example:

GET messages?$select=subject,sender HTTP/1.1

Processing a batch request

A batch request is processed on its own as one request and returns its own response code. A well-formed batch request with correct headers returns HTTP 200 OK. This however doesn't mean all the requests in the batch were successful.

Each request in the batch request body is in turn processed separately and returns its own response code, and any response body and error message.

The server may perform operations within a batch in any order. If you must have operations carried out in a specific order, you should not put them in the same batch request. Instead, send one operation by itself, wait for the response before sending the next one.

By default, processing stops on the first operation that returns an error. You can specify the following header to have processing ignore the error and continue with the next operation in the batch:

Prefer: odata.continue-on-error

Next steps

Whether you're ready to start building an app or just want to learn more, we've got you covered.

Or, learn more about using the Office 365 platform: