Custom batch - Batch

You may want to perform multiple operations with one API call to reduce latency.

If you have one index per user, you may want to perform a batch operations across several indices. We expose a method to perform this type of batch:

List<JObject> objs = new List<JObject>();
objs.Add(JObject.Parse(@"{""action"":""addObject"", ""indexName"": ""index1"", ""body"": {""firstname"":""Roger"", ""lastname"":""Barninger""}}"));
objs.Add(JObject.Parse(@"{""action"":""addObject"", ""indexName"": ""index2"", ""body"": {""firstname"":""Roger"", ""lastname"":""Speach""}}"));

The attribute action can have these values:

  • addObject
  • updateObject
  • partialUpdateObject
  • partialUpdateObjectNoCreate
  • deleteObject

Backup / Export an index - Browse

The search method cannot return more than 1,000 results. If you need to retrieve all the content of your index (for backup, SEO purposes or for running a script on it), you should use the browse method instead. This method lets you retrieve objects beyond the 1,000 limit.

This method is optimized for speed. To make it fast, distinct, typo-tolerance, word proximity, geo distance and number of matched words are disabled. Results are still returned ranked by attributes and custom ranking.

Response Format

  "hits": [
      "firstname": "Jimmie",
      "lastname": "Barninger",
      "objectID": "433"
  "processingTimeMS": 7,
  "query": "",
  "params": "filters=level%3D20",
  • cursor (string, optional): A cursor to retrieve the next chunk of data. If absent, it means that the end of the index has been reached.
  • query (string): Query text used to filter the results.
  • params (string, URL-encoded): Search parameters used to filter the results.
  • processingTimeMS (integer): Time that the server took to process the request, in milliseconds. Note: This does not include network time.

The following fields are provided for convenience purposes, and only when the browse is not filtered:

  • nbHits (integer): Number of objects in the index.
  • page (integer): Index of the current page (zero-based).
  • hitsPerPage (integer): Maximum number of hits returned per page.
  • nbPages (integer): Number of pages corresponding to the number of hits. Basically, ceil(nbHits / hitsPerPage).


// Iterate with a filter over the index
IndexIterator it = index.BrowseAll(new Query("text"));

// Retrieve the next cursor from the browse method
System.Diagnostics.Debug.WriteLine(index.BrowseFrom(new Query("text"), null)["cursor"]);

List user keys - ListApiKeys

To list existing keys, you can use:

// Lists API Keys
var keys = client.ListApiKeys();
// Asynchronous
// var keys = await client.ListApiKeysAsync();
// Lists API Keys that can access only to this index
keys = index.ListApiKeys();
// Asynchronous
// keys = await index.ListApiKeysAsync();

Each key is defined by a set of permissions that specify the authorized actions. The different permissions are:

  • search: Allowed to search.
  • browse: Allowed to retrieve all index contents via the browse API.
  • addObject: Allowed to add/update an object in the index.
  • deleteObject: Allowed to delete an existing object.
  • deleteIndex: Allowed to delete index content.
  • settings: allows to get index settings.
  • editSettings: Allowed to change index settings.
  • analytics: Allowed to retrieve analytics through the analytics API.
  • listIndexes: Allowed to list all accessible indexes.

Add API key - AddApiKey

To create API keys:

// Creates a new API key that can only perform search actions
var res = client.AddApiKey(new String[] { "search" });
// Asynchronous
// var res = await client.AddApiKeyAsync(new String[] { "search" });
System.Diagnostics.Debug.WriteLine("Key: " + res["key"]);
// Creates a new API key that can only perform search action on this index
res = index.AddApiKey(new String[] { "search" });
// Asynchronous
// res = await index.AddApiKeyAsync(new String[] { "search" });
System.Diagnostics.Debug.WriteLine("Key: " + res["key"]);

You can also create an API Key with advanced settings:


Add a validity period. The key will be valid for a specific period of time (in seconds).


Specify the maximum number of API calls allowed from an IP address per hour. Each time an API call is performed with this key, a check is performed. If the IP at the source of the call did more than this number of calls in the last hour, a 403 code is returned. Defaults to 0 (no rate limit). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.


Specify the maximum number of hits this API key can retrieve in one call. Defaults to 0 (unlimited). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.


Specify the list of targeted indices. You can target all indices starting with a prefix or ending with a suffix using the ‘*’ character. For example, “dev_*” matches all indices starting with “dev_” and “*_dev” matches all indices ending with “_dev”. Defaults to all indices if empty or blank.


Specify the list of referers. You can target all referers starting with a prefix, ending with a suffix using the ‘*’ character. For example, “https://algolia.com/*” matches all referers starting with “https://algolia.com/” and “*.algolia.com” matches all referers ending with “.algolia.com”. If you want to allow the domain algolia.com you can use “*algolia.com/*”. Defaults to all referers if empty or blank.


Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X&param2=Y…).


Specify a description to describe where the key is used.

// Creates a new index specific API key valid for 300 seconds, with a rate limit of 100 calls per hour per IP and a maximum of 20 hits

Dictionary<string, object> param = new Dictionary<string, object>();
param["acl"] = new String[] { "search" };
param["validity"] = 300;
param["maxQueriesPerIPPerHour"] = 100;
param["maxHitsPerQuery"] = 20;
param["indexes"] = new string[]{"dev_*"};
param["referers"] = new string[]{"algolia.com/*"};
param["queryParameters"] = "typoTolerance=strict&ignorePlurals=false";
param["description"] = "Limited search only API key for algolia.com";

res = index.AddApiKey(param);
// Asynchronous
// res = await index.AddApiKeyAsync(param);
System.Diagnostics.Debug.WriteLine("Key: " + res["key"]);

Update api key - UpdateApiKey

To update the permissions of an existing key:

// Update an existing API key that is valid for 300 seconds
var res = client.UpdateApiKey("myAPIKey", new String[] { "search" }, 300, 0, 0, new string[]{"dev_*"});
// Asynchronous
// var res = await client.UpdateApiKeyAsync("myAPIKey", new String[] { "search" }, 300, 0, 0, new string[]{"dev_*"});
System.Diagnostics.Debug.WriteLine("Key: " + res["key"]);
// Update an existing index specific API key valid for 300 seconds, with a rate limit of 100 calls per hour per IP and a maximum of 20 hits
res = index.UpdateApiKey("myAPIKey", new String[] { "search" }, 300, 100, 20, new string[]{"dev_*"});
// Asynchronous
// res = await index.UpdateApiKeyAsync("myAPIKey", new String[] { "search" }, 300, 100, 20, new string[]{"dev_*"});
System.Diagnostics.Debug.WriteLine("Key: " + res["key"]);

To get the permissions of a given key:

// Gets the rights of a key
var res = client.GetApiKey("f420238212c54dcfad07ea0aa6d5c45f");
// Asynchronous
// var res = await client.GetApiKeyAsync("f420238212c54dcfad07ea0aa6d5c45f");

// Gets the rights of an index specific key
res = index.GetApiKey("71671c38001bf3ac857bc82052485107");
// Asynchronous
// res = await index.GetApiKeyAsync("71671c38001bf3ac857bc82052485107");

Delete api key - DeleteApiKey

To delete an existing key:

// Deletes a key
// Asynchronous
// await client.DeleteApiKeyAsync("f420238212c54dcfad07ea0aa6d5c45f");
// Deletes an index specific key
// Asynchronous
// await index.DeleteApiKeyAsync("71671c38001bf3ac857bc82052485107");

Get key permissions - GetApiKeyACL

To get the permissions of a given key:

// Gets the rights of a key
var res = client.GetApiKeyACL("f420238212c54dcfad07ea0aa6d5c45f");
// Asynchronous
// var res = await client.GetApiKeyACLAsync("f420238212c54dcfad07ea0aa6d5c45f");

// Gets the rights of an index specific key
res = index.GetApiKeyACL("71671c38001bf3ac857bc82052485107");
// Asynchronous
// res = await index.GetApiKeyACLAsync("71671c38001bf3ac857bc82052485107");

Get latest logs - GetLogs

You can retrieve the latest logs via this API. Each log entry contains:

  • Timestamp in ISO-8601 format
  • Client IP
  • Request Headers (API Key is obfuscated)
  • Request URL
  • Request method
  • Request body
  • Answer HTTP code
  • Answer body
  • SHA1 ID of entry

You can retrieve the logs of your last 1,000 API calls and browse them using the offset/length parameters:


Specify the first entry to retrieve (0-based, 0 is the most recent log entry). Defaults to 0.


Specify the maximum number of entries to retrieve starting at the offset. Defaults to 10. Maximum allowed value: 1,000.


Retrieve only logs with an HTTP code different than 200 or 201. (deprecated)


Specify the type of logs to retrieve:

  • query: Retrieve only the queries.
  • build: Retrieve only the build operations.
  • error: Retrieve only the errors (same as onlyErrors parameters).
// Get last 10 log entries
// Asynchronous
// await client.GetLogsAsync();
// Get last 100 log entries
client.GetLogs(0, 100);
// Asynchronous
// await client.GetLogsAsync(0, 100);

Retry logic

Algolia’s architecture is heavily redundant, to provide optimal reliability. Every application is hosted on at least three different servers. As a developer, however, you don’t need to worry about those details. The API Client handles them for you:

  • It leverages our dynamic DNS to perform automatic load balancing between servers.
  • Its retry logic switches the targeted server whenever it detects that one of them is down or unreachable. Therefore, a given request will not fail unless all servers are down or unreachable at the same time.

Application-level errors (e.g. invalid query) are still reported without retry.

Error handling

Requests can fail for two main reasons:

  1. Network issues: the server could not be reached, or did not answer within the timeout.
  2. Application error: the server rejected the request.

In the latter case, the error reported by the API client contains:

  • an HTTP status code indicating the type of error;
  • an error message indicating the cause of the error.

The error message is purely informational and intended for the developer. You should never rely on its content programmatically, as it may change without notice.

Configuring timeouts

Network & DNS resolution can be slow. That is why we have pre-configured timeouts. We do not advise to change them, but it could make sense to change them in some special cases:

  AlgoliaClient client = new AlgoliaClient(...);
    4000, /* readTimeout */
    4000, /* writeTimeout */
  client._dsnInternalTimeout = 4000 // delay before retrying a host we know was down

Did you find this page helpful?

We're always looking for advice to help improve our documentation! Please let us know what's working (or what's not!) - we're constantly iterating thanks to the feedback we receive.

Send us your suggestions!