Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article explains how to import documents into a predefined search index using REST APIs, Azure SDKs, or the Azure portal.
Tip
For the fastest path to loading data, use the Import data wizard in the Azure portal, which creates an index and loads it in one workflow.
Prerequisites
An Azure AI Search service (any tier). Create a service or find an existing one.
An existing search index. This article assumes you already created an index. If you need to create and load in one step, use an Import wizard or indexer.
Permissions to load documents:
- Key-based authentication: An admin API key for your search service.
- Role-based authentication: Search Index Data Contributor role on the search service.
For SDK development, install the Azure Search client library:
- .NET: Azure.Search.Documents
- Python: azure-search-documents
- JavaScript: @azure/search-documents
- Java: azure-search-documents
Use the Azure portal
In the Azure portal, use an import wizard to create and load indexes in a seamless workflow. If you want to load an existing index, choose an alternative approach.
Sign in to the Azure portal with your Azure account and find your search service.
On the Overview page, select Import data or Import data (new) on the command bar to create and populate a search index.
You can follow these links to review the workflow: Quickstart: Create an Azure AI Search index and Quickstart: Integrated vectorization.
After the wizard is finished, use Search Explorer to check for results.
Tip
The import wizards create and run indexers. If indexers are already defined, you can reset and run an indexer from the Azure portal, which is useful if you're adding fields incrementally. Reset forces the indexer to start over, picking up all fields from all source documents.
Use the REST APIs
Documents - Index is the REST API for importing data into a search index.
The body of the request contains one or more documents to be indexed. Documents are uniquely identified through a case-sensitive key. Each document is associated with an action: "upload", "delete", "merge", or "mergeOrUpload". Upload requests must include the document data as a set of key/value pairs.
REST APIs are useful for initial proof-of-concept testing, where you can test indexing workflows without having to write much code. The @search.action parameter determines whether documents are added in full, or partially in terms of new or replacement values for specific fields.
Quickstart: Full-text search using REST explains the steps. The following example is a modified version of the example. The value is trimmed for brevity and the first HotelId value is altered to avoid overwriting an existing document.
Formulate a POST call specifying the index name, the "docs/index" endpoint, and a request body that includes the
@search.actionparameter.POST https://[service name].search.windows.net/indexes/hotels-sample-index/docs/index?api-version=2025-09-01 Content-Type: application/json api-key: [admin key] { "value": [ { "@search.action": "upload", "HotelId": "1111", "HotelName": "Stay-Kay City Hotel", "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", "Category": "Boutique", "Tags": [ "pool", "air conditioning", "concierge" ] }, { "@search.action": "mergeOrUpload", "HotelId": "2", "HotelName": "Old Century Hotel", "Description": "This is description is replacing the original one for this hotel. New and changed values overwrite the previous ones. In a comma-delimited list like Tags, be sure to provide the full list because there is no merging of values within the field itself.", "Category": "Boutique", "Tags": [ "pool", "free wifi", "concierge", "my first new tag", "my second new tag" ] } ] }Set the
@search.actionparameter touploadto create or overwrite a document. Set it tomergeoruploadOrMergeif you're targeting updates to specific fields within the document. The previous example shows both actions.Action Effect upload Similar to an "upsert" where the document is inserted if it's new, and updated or replaced if it exists. If the document is missing values that the index requires, the document field's value is set to null. merge Updates a document that already exists, and fails a document that can't be found. Merge replaces existing values. For this reason, be sure to check for collection fields that contain multiple values, such as fields of type Collection(Edm.String). For example, if atagsfield starts with a value of["budget"]and you execute a merge with["economy", "pool"], the final value of thetagsfield is["economy", "pool"]. It isn't["budget", "economy", "pool"].mergeOrUpload Behaves like merge if the document exists, and upload if the document is new. This is the most common action for incremental updates. delete Delete removes the specified document from the index. Any field you specify in a delete operation, other than the key field, is ignored. If you want to remove an individual field from a document, use merge instead and set the field explicitly to null. For more information, see Delete documents in a search index. There are no ordering guarantees for which action in the request body is executed first. It's not recommended to have multiple "merge" actions associated with the same document in a single request body. If there are multiple "merge" actions required for the same document, perform the merging client-side before updating the document in the search index.
In primitive collections, if the document contains a Tags field of type
Collection(Edm.String)with a value of ["budget"], and you execute a merge with a value of ["economy", "pool"] for Tag, the final value of the Tags field will be ["economy", "pool"]. It isn't ["budget", "economy", "pool"].In complex collections, if the document contains a complex collection field named Rooms with a value of [{ "Type": "Budget Room", "BaseRate": 75.0 }], and you execute a merge with a value of [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }], the final value of the Rooms field will be [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]. It won't be either of the following:
[{ "Type": "Budget Room", "BaseRate": 75.0 }, { "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }] (append elements)
[{ "Type": "Standard Room", "BaseRate": 75.0 }, { "Type": "Budget Room", "BaseRate": 60.5 }] (merge elements in order, then append any extras)
Note
When you upload DateTimeOffset values with time zone information to your index, Azure AI Search normalizes these values to UTC. For example, 2025-01-13T14:03:00-08:00 will be stored as 2025-01-13T22:03:00Z. If you need to store time zone information, add an extra column to your index.
Send the request.
The following table explains the various per-document status codes that can be returned in the response. Some status codes indicate problems with the request itself, while others indicate temporary error conditions. The latter you should retry after a delay.
Status code Meaning Retryable Notes 200 Document was successfully modified or deleted. n/a Delete operations are idempotent. That is, even if a document key doesn't exist in the index, attempting a delete operation with that key results in a 200 status code. 201 Document was successfully created. n/a 400 There was an error in the document that prevented it from being indexed. No The error message in the response indicates what is wrong with the document. 404 The document couldn't be merged because the given key doesn't exist in the index. No This error doesn't occur for uploads since they create new documents, and it doesn't occur for deletes because they're idempotent. 409 A version conflict was detected when attempting to index a document. Yes This can happen when you're trying to index the same document more than once concurrently. 422 The index is temporarily unavailable because it was updated with the 'allowIndexDowntime' flag set to 'true'. Yes 429 Indicates that you have exceeded your quota on the number of documents per index. No You must either create a new index or upgrade for higher capacity limits. 503 Your search service is temporarily unavailable, possibly due to heavy load. Yes Your code should wait before retrying in this case or you risk prolonging the service unavailability. Note
If your client code frequently encounters a 207 response, one possible reason is that the system is under load. You can confirm this by checking the
statusCodeproperty for 503. If this is the case, we recommend throttling indexing requests. Otherwise, if indexing traffic doesn't subside, the system could start rejecting all requests with 503 errors.Look up the documents you just added as a validation step:
GET https://[service name].search.windows.net/indexes/hotel-sample-index/docs/1111?api-version=2025-09-01
Reference: Documents - Index, Documents - Get
A successful index request returns HTTP 200 (OK) for a batch where all documents succeeded, or HTTP 207 (Multi-Status) if some documents failed. The response body contains status for each document:
{
"value": [
{ "key": "1111", "status": true, "statusCode": 201 },
{ "key": "2", "status": true, "statusCode": 200 }
]
}
When the document key or ID is new, null becomes the value for any field that's unspecified in the document. For actions on an existing document, updated values replace the previous values. Any fields that weren't specified in a "merge" or "mergeUpload" are left intact in the search index.
Use the Azure SDKs
Programmability is provided in the following Azure SDKs.
The Azure SDK for Python provides the following APIs for simple and bulk document uploads into an index:
Reference: SearchClient, IndexDocumentsBatch
Code samples include:
Be sure to check the azure-search-vector-samples repo for code examples showing how to index vector fields.
Verify your data load
After loading documents, verify the data is indexed correctly.
- In the Azure portal, open the search service Overview page.
- Select Search explorer from the command bar.
- Select your index from the dropdown.
- Select Search to run an empty query that returns all documents.
- Verify the document count and spot-check field values.
How data import works
A search service accepts JSON documents that conform to the index schema. A search service can import and index plain text content and vector content in JSON documents.
Plain text content is retrieved from fields in the external data source, from metadata properties, or from enriched content that's generated by a skillset. Skills can extract or infer textual descriptions from images and unstructured content.
Vector content is retrieved from a data source that provides it, or it's created by a skillset that implements integrated vectorization in an Azure AI Search indexer workload.
You can prepare these documents yourself, but if content resides in a supported data source, running an indexer or using an Import wizard can automate document retrieval, JSON serialization, and indexing.
Once data is indexed, the physical data structures of the index are locked in. For guidance on what can and can't be changed, see Update and rebuild an index.
Indexing isn't a background process. A search service balances indexing and query workloads, but if query latency is too high, you can either add capacity or identify periods of low query activity for loading an index.
For more information, see Data import strategies.
Troubleshoot common errors
| Error | Cause | Solution |
|---|---|---|
| HTTP 400 Bad Request | Document contains invalid data or missing required fields | Check the error message for the specific field. Ensure all required fields are present and data types match the index schema. |
| HTTP 404 Not Found (merge) | Attempting to merge a document that doesn't exist | Use mergeOrUpload instead of merge if the document might not exist. |
| HTTP 409 Conflict | Concurrent updates to the same document | Implement retry logic with exponential backoff. |
| HTTP 413 Payload Too Large | Batch size exceeds limits | Reduce the number of documents per batch. Maximum batch size is 1,000 documents or 16 MB. |
| HTTP 429 Too Many Requests | Quota exceeded | Check your service tier limits. Consider upgrading or creating a new index. |
| HTTP 503 Service Unavailable | Service is under heavy load | Implement retry logic with exponential backoff. Reduce indexing request frequency. |