> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Initialize the API clients

> Initialize the search client and index.

<Note>
  This page documents an earlier version of the API client.
  For the latest version,
  see [Install the (latest) API clients](/doc/libraries/sdk/install)
  and [Customize the clients](/doc/libraries/sdk/customize).
</Note>

Before you can index your data or search your [Algolia indices](/doc/guides/sending-and-managing-data/prepare-your-data/in-depth/prepare-data-in-depth#algolia-index),
you must initialize a search client with your **application ID** and **API key**.
You can find both in your [Algolia account](https://dashboard.algolia.com/account/api-keys).

## Initialize the search client and index

The search client handles authentication and lets you manage your indices,
for example, add data to them, or search them.

<CodeGroup>
  ```cs C# theme={"system"}
  SearchClient client = new SearchClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY");
  SearchIndex index = client.InitIndex("INDEX_NAME");
  ```

  ```go Go theme={"system"}
  client := search.NewClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  index := client.InitIndex("INDEX_NAME")
  ```

  ```java Java theme={"system"}
  SearchClient client = DefaultSearchClient.create("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY");
  SearchIndex<Contact> index = client.initIndex("INDEX_NAME", Contact.class);
  ```

  ```js JavaScript theme={"system"}
  // Default version (all methods)
  import algoliasearch from "algoliasearch";

  // Search-only version
  // import algoliasearch from 'algoliasearch/lite';

  const client = algoliasearch("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY");
  const index = client.initIndex("INDEX_NAME");
  ```

  ```kotlin Kotlin theme={"system"}
  val client = ClientSearch(
    applicationID = ApplicationID("ALGOLIA_APPLICATION_ID"),
    apiKey = APIKey("ALGOLIA_API_KEY")
  )
  val indexName = IndexName("INDEX_NAME")

  client.initIndex(indexName)
  ```

  ```php PHP theme={"system"}
  <?php
  // composer autoload
  require __DIR__ . '/vendor/autoload.php';

  // if you aren't using composer
  // require_once 'path/to/algolia/folder/autoload.php';

  use Algolia\AlgoliaSearch\SearchClient;

  $client = SearchClient::create('ALGOLIA_APPLICATION_ID', 'ALGOLIA_API_KEY');

  $index = $client->initIndex('INDEX_NAME');
  ```

  ```python Python theme={"system"}
  from algoliasearch.search_client import SearchClient

  client = SearchClient.create("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  index = client.init_index("INDEX_NAME")
  ```

  ```ruby Ruby theme={"system"}
  require "algolia"

  client = Algolia::Search::Client.create("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  index = client.init_index("INDEX_NAME")
  ```

  ```scala Scala theme={"system"}
  // The index doesn't need to be initialized
  val client = new AlgoliaClient("ALGOLIA_APPLICATION_ID", "ALGOLIA_API_KEY")
  ```

  ```swift Swift theme={"system"}
  import AlgoliaSearchClient

  let client = SearchClient(appID: "ALGOLIA_APPLICATION_ID", apiKey: "ALGOLIA_API_KEY")
  let index = client.index(withName: "INDEX_NAME")
  ```
</CodeGroup>

Replace `INDEX_NAME` with the name of the index you want to use.
You can find your existing indices in the [Algolia dashboard](https://dashboard.algolia.com/explorer/indices)
or using the [List indices](/doc/rest-api/search/list-indices) operation.
If the index doesn't exist, a new, empty index is created locally.
It's created on Algolia's servers only if you add records to the index.

<Warning>
  **Don't use sensitive or personally identifiable information as your index name**,
  including usernames, IDs, or email addresses.
  Index names are publicly shared.
</Warning>

Methods that are scoped to your Algolia applications (methods of a `client` object):

* Managing indices
* Working with dictionaries
* Working with API keys

Methods that are scoped to an `index` are:

* Search, indexing, settings, synonyms, and rules methods

The Recommend, Personalization, Insights, and A/B testing APIs have their own clients:

* [Recommend API methods](/doc/libraries/sdk/v1/methods/get-frequently-bought-together)
* [A/B testing API methods](/doc/libraries/sdk/v1/methods/add-ab-test)
* [Insights API methods](/doc/libraries/sdk/v1/methods/clicked-object-ids-after-search)
* [Personalization API methods](/doc/libraries/sdk/v1/methods/add-strategy)

## Usage notes

<Note>Not all API clients have usage notes.</Note>

<Tabs>
  <Tab title="C#">
    ### Serialization

    The API client uses [Json.NET](https://www.newtonsoft.com/json) as the serializer for your [POCOs](https://wikipedia.org/wiki/Plain_old_CLR_object). You can index your POCOs directly if they follow the [.NET naming convention](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions).

    Example:

    ```cs C# icon=code theme={"system"}
    using Algolia.Search.Clients;
    using Algolia.Search.Models.Search;
    using System.Collections.Generic;

    public class Contact
    {
        public string ObjectID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class AlgoliaIntegration
    {
        private SearchClient client;
        private SearchIndex index;

        public AlgoliaIntegrationService(string applicationId, string apiKey)
        {
            client = new SearchClient(applicationId, apiKey);
            index = client.InitIndex("contact");
        }

        public void SaveContacts(IEnumerable<Contact> contacts)
        {
            // Ensure that contacts is not null and has data
            if (contacts != null)
            {
                index.SaveObjects(contacts);
            }
        }

        public Contact GetContact(string objectId)
        {
            try
            {
                Contact contact = index.GetObject<Contact>(objectId);
                return contact;
            }
            catch (Algolia.Search.Exceptions.AlgoliaApiException ex)
            {
                // Handle exceptions from the Algolia API here
                // Log the exception message: ex.Message
                return null;
            }
        }

        public IEnumerable<Contact> SearchForContact(string queryText)
        {
            try
            {
                var result = index.Search<Contact>(new Query(queryText));
                return result.Hits;
            }
            catch (Algolia.Search.Exceptions.AlgoliaApiException ex)
            {
                // Handle exceptions from the Algolia API here
                // Log the exception message: ex.Message
                return new List<Contact>();
            }
        }
    }

    // Usage:
    // AlgoliaIntegration algoliaService = new AlgoliaIntegration("YourApplicationID", "YourWriteAPIKey");
    // IEnumerable<Contact> contacts = ... // Fetch from DB or a Json file
    // algoliaService.SaveContacts(contacts);
    // Contact contact = algoliaService.GetContact("myId");
    // IEnumerable<Contact> searchResult = algoliaService.SearchForContact("contact");
    ```

    <Note>
      You can override the naming strategy with the following attribute:
      `[JsonProperty(PropertyName = "propertyName")]`
    </Note>

    You can also add and retrieve records via `JObject`:

    ```cs C# icon=code theme={"system"}
    using (StreamReader re = File.OpenText("contacts.json"))
    using (JsonTextReader reader = new JsonTextReader(re))
    {
       JArray batch = JArray.Load(reader);
       index.SaveObjects(batch).Wait();
    }

    // Retrieve one JObject Contact
    JObject contact = index.GetObject<JObject>("myId");
    ```

    Algolia objects such as `Rule`, `Synonym`, or `Settings` are now typed.

    An example with the `Settings` class:

    ```cs C# icon=code theme={"system"}
    IndexSettings settings = new IndexSettings
    {
        SearchableAttributes = new List<string> {"attribute1", "attribute2"},
        AttributesForFaceting = new List<string> {"filterOnly(attribute2)"},
        UnretrievableAttributes = new List<string> {"attribute1", "attribute2"},
        AttributesToRetrieve = new List<string> {"attribute3", "attribute4"}
        // etc.
    };

    index.SetSettings(settings);
    ```

    If you want to access all properties of the `SearchResponse` object,
    you must add these properties to your class.
    For example, to get the [`_rankingInfo`](/doc/api-reference/api-parameters/getRankingInfo) attribute with your search:

    ```cs C# icon=code theme={"system"}
    public class Contact
    {
      public string ObjectID { get; set; }
      public string Name { get; set; }
      public int Age { get; set; }

      public object _rankingInfo { get; set; }
    }
    ```

    ### Asynchronous and synchronous methods

    The API client provides both synchronous and asynchronous methods for every API endpoint.
    Asynchronous methods are suffixed with the `Async` keyword.

    ```cs C# icon=code theme={"system"}
    // Synchronous
    Contact res = index.GetObject<Contact>("myId");

    // Asynchronous
    Contact res = await index.GetObjectAsync<Contact>("myId");
    ```

    ### Custom HTTP clients

    The API client uses the built-in `HttpClient` of the .NET Framework.

    The `HttpClient` is wrapped in an interface: `IHttpRequester`.
    If you want to use a custom `HttpClient`,
    you can pass it to the constructors of `SearchClient`,
    `AnalyticsClient`, or `InsightsClient`.

    For example:

    ```cs C# icon=code theme={"system"}
    IHttpRequester myCustomHttpClient = new MyCustomHttpClient();

    SearchClient client = new SearchClient(
        new SearchConfig("YourApplicationID", "YourWriteAPIKey"),
        myCustomHttpClient
    );
    ```

    ### Thread safety

    The API client is thread-safe. You can use `SearchClient`, `AnalyticsClient`, and `InsightsClient` in a multi-threaded environment.
  </Tab>

  <Tab title="Java">
    ### JVM DNS caching

    By default, the JVM caches DNS resolutions infinitely.
    Since Algolia uses multiple IP addresses for load balancing,
    you should reduce the time to live (TTL) of the cache.

    For example, to set the cache to 60 seconds:

    ```java Java icon=code theme={"system"}
    java.security.Security.setProperty("networkaddress.cache.ttl", "60");
    ```

    ### Debug logging

    To **enable debug logging** in the API client,
    add the following line to your `logging.properties` file:

    ```xml XML icon=code-xml theme={"system"}
    com.algolia.search.HttpTransport=FINEST
    ```

    ### Builder

    The Java API client comes in two packages:

    * `algoliasearch-core` which implements the API methods, Java objects, transport layer, and retry strategy.
      This package is HTTP client agnostic.
    * `algoliasearch-apache`, `algoliasearch-jvm-net` are HTTP client implementations of the core library.

    If you want to use your own HTTP client,
    inject it into all client classes of the library.
    Your custom HTTP client must implement the `HttpRequester` interface.

    If you're using a custom HTTP client,
    you don't need to use `algoliasearch-apache` or `algoliasearch-jvm-net` as a dependency.

    ```java Java icon=code theme={"system"}
    SearchConfig config =
    new SearchConfig.Builder("YourApplicationID", "YourWriteAPIKey")
        .build();

    HttpRequester myCustomRequester = new myCustomRequester();

    SearchClient client = new SearchClient(config, myCustomRequester);
    ```

    All clients are safe to use as [singletons](https://www.geeksforgeeks.org/singleton-class-java).
    Reuse client instances as much as possible to avoid exhausting the number of available sockets.
    All clients implement the `Closeable` interface: close them when you're done using them.

    ### Serialization

    You can parametrize the `SearchIndex` class with a Java class which lets you use type-safe method results.

    The parametrized Java classes should follow the [POJO](https://en.wikipedia.org/wiki/Plain_old_Java_object)
    convention:

    * A constructor without parameters
    * Getters and setters for every field you want to (de)serialize

    For example:

    ```java Java icon=code theme={"system"}
    public class Contact {

      private String name;
      private int age;

      public Contact() {}

      public String getName() {
        return name;
      }

      public Contact setName(String name) {
        this.name = name;
        return this;
      }

      public int getAge() {
        return age;
      }

      public Contact setAge(int age) {
        this.age = age;
        return this;
      }
    }
    ```

    The Java API client uses [Jackson2](https://github.com/FasterXML/jackson-core/wiki) for serialization and deserialization.
    The default object mapper is set in: `com.algolia.search.Defaults.DEFAULT_OBJECT_MAPPER`.

    ### Asynchronous methods and completable futures

    All asynchronous methods have the suffix `Async` and are defined in the same classes as their synchronous counterparts.
    Asynchronous methods return a `CompletableFuture`.

    You can also pass a custom `ExecutorService` to the `Configuration builder`.
    By default, the API client uses `ForkJoinPool.commonPool`.

    ### Thread safety

    The Java API clients are thread-safe.
    You can use `SearchClient`, `AnalyticsClient`, and `InsightsClient` in multi-threaded environments.

    ### Handling exceptions

    The Java API clients can throw three types of runtime exceptions:

    * `AlgoliaApiException`: when Algolia APIs send back an HTTP error code
    * `AlgoliaRetryException`: when the retry strategy failed to target all hosts
    * `AlgoliaRuntimeException`: when an error occurred during serialization/deserialization or data processing
    * `IllegalArgumentException`: when you provide invalid parameters
    * `NullPointerException`: when you pass a null pointer

    ### Proxies

    To run the API client behind a proxy, you can set the following properties at the JVM level:

    ```java Java icon=code theme={"system"}
    System.setProperty("https.proxyHost", "https host");
    System.setProperty("https.proxyPort", "https port");
    System.setProperty("https.proxyUser", "https proxy login");
    System.setProperty("https.proxyPassword", "https proxy password");

    SearchConfig config = new SearchConfig.Builder("YourApplicationID", "YourWriteAPIKey")
        .setUseSystemProxy(true)
        .build();

    SearchClient client = DefaultSearchClient.create(config);
    ```

    For more information about JVM proxy settings, see the [Java documentation](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html).
  </Tab>

  <Tab title="Kotlin">
    ### Type safety

    Response and parameters objects are typed to provide extensive compile-time safety.
    For example, to initialize the API client without confusing application ID and the API key:

    ```kotlin Kotlin icon=code theme={"system"}
    val appID = ApplicationID("YourApplicationID")
    val apiKey = APIKey("YourWriteAPIKey")

    val client = ClientSearch(appID, apiKey)
    ```

    For example, to use typed attributes:

    ```kotlin Kotlin icon=code theme={"system"}
    val color = Attribute("color")
    val category = Attribute("category")
    val query = Query(attributesToRetrieve = listOf(color, category))
    ```

    Enumerated types are represented by [sealed classes](https://kotlinlang.org/docs/sealed-classes.html).
    This lets you quickly discover all possible values for each type.
    Each enumerated type includes `Other` to pass a custom value:

    ```kotlin Kotlin icon=code theme={"system"}
    val query = Query()

    query.sortFacetsBy = SortFacetsBy.Count
    // query.sortFacetsBy = SortFacetsBy.Alpha
    // query.sortFacetsBy = SortFacetsBy.Other("custom value")
    ```

    ### Domain-specific language

    The Kotlin API client lets you use a domain-specific language (DSL) to set parameters,
    configure your index, or use filters for your search:

    **Example for query parameters:**

    ```kotlin Kotlin icon=code theme={"system"}
    val query = query {
       attributesToRetrieve {
           +"color"
           +"category"
       }
    }
    ```

    **Example for settings:**

    ```kotlin Kotlin icon=code theme={"system"}
    val settings = settings {
       attributesToSnippet {
           +"content"(10)
       }
    }
    ```

    **Example for filters:**

    ```kotlin Kotlin icon=code theme={"system"}
    val query = query {
       filters {
           and {
               facet("color", "red")
               facet("category", "shirt")
           }
           orNumeric {
               range("price", 0 until 10)
               comparison("price", Equals, 15)
           }
       }
    }
    ```

    ### Serialization

    The Kotlin API client uses the kotlinx [serialization](https://github.com/Kotlin/kotlinx.serialization) library.

    #### Deserialize a search response

    To deserialize results from a search response, use the `deserialize` extension functions.

    ```kotlin Kotlin icon=code theme={"system"}
    @Serializable
    data class Contact(
        val firstname: String,
        val lastname: String
    )

    val response = index.search()
    val contacts: List<Contact> = response.hits.deserialize(Contact.serializer())
    ```

    #### Deserialize response from `getObject`

    To deserialize the response from `getObject`, pass `serializer` as a parameter.

    ```kotlin Kotlin icon=code theme={"system"}
    @Serializable
    data class Contact(
        val firstname: String,
        val lastname: String,
        override val objectID: ObjectID
    ) : Indexable

    val objectID = ObjectID("myID1")
    val contact: Contact = index.getObject(Contact.serializer(), objectID)
    ```

    #### Serialize and deserialize any Kotlin object

    Use the standard methods of the [kotlinx serialization](https://github.com/Kotlin/kotlinx.serialization) library.

    ```kotlin Kotlin icon=code theme={"system"}
    @Serializable
    data class Contact(
        val firstname: String,
        val lastname: String
    )

    // Create a new JSON object
    val json: JsonObject = buildJsonObject {
        put("firstname", "Jimmie")
        put("lastname", "Barninger")
    }

    // Transform the JSON object into a Kotlin object
    val contact: Contact = Json.decodeFromJsonElement(Contact.serializer(), json)

    // You can configure your own `Json` instance for custom options:
    val JsonNonStrict = Json {
        ignoreUnknownKeys = true
        isLenient = true
        allowSpecialFloatingPointValues = true
    }
    val contactNonStrict: Contact = JsonNonStrict.decodeFromJsonElement(Contact.serializer(), json)
    ```

    ### Handling exceptions

    A successful HTTP call returns a typed response object:

    ```kotlin Kotlin icon=code theme={"system"}
    val response: ResponseSearch = index.search()
    ```

    To handle [exceptions](https://kotlinlang.org/docs/exceptions.html),
    use a `try` / `catch` block:

    ```kotlin Kotlin icon=code theme={"system"}
    try {
        val response = index.search()
    } catch (exception: AlgoliaApiException) {
        when (exception.httpErrorCode) {
            404 -> TODO()
            400 -> TODO()
        }
    }
    ```

    Use multiple `catch` blocks to handle different types of exceptions:

    ```kotlin Kotlin icon=code theme={"system"}
    try {
        val response = index.search()
    } catch (exception: AlgoliaRuntimeException) {
        TODO()
    } catch (exception: IOException) {
        TODO()
    } catch (exception: Exception) {
        TODO()
    }
    ```

    ### Coroutines

    The Kotlin API client uses [suspending functions](https://kotlinlang.org/docs/composing-suspending-functions.html#composing-suspending-functions) for all HTTP calls. This means that you can call these functions only from a coroutine scope.

    The following example starts a coroutine in the main thread,
    then performs the search HTTP call in another thread.
    You can change the search response from the main thread.

    ```kotlin Kotlin icon=code theme={"system"}
    class Searcher : CoroutineScope {
        override val coroutineContext = SupervisorJob()

        fun search() {
            launch(Dispatchers.Main) {
                val response = withContext(Dispatchers.Default) { index.search() }
            }
        }
    }
    ```

    The Kotlin API client doesn't run any HTTP calls on any particular thread.
    You need to define this explicitly using coroutines.

    To learn more about coroutines, see the [Kotlin documentation](https://kotlinlang.org/docs/coroutines-guide.html).

    ### Waiting for operations

    Many operations with Algolia are asynchronous.
    To wait for operations, use [`apply`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/apply.html)
    or [`run`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run.html):

    ```kotlin Kotlin icon=code theme={"system"}
    index.apply {
        setSettings(Settings()).wait()
    }
    client.run {
        multipleBatchObjects(listOf<BatchOperationIndex>()).waitAll()
    }
    ```

    The `wait` functions are suspense functions and should be called from coroutines.

    ### Thread safety

    The Kotlin API client is thread-safe.
    You can use `SearchClient`, `AnalyticsClient`, and `InsightsClient` in a multi-threaded environment.
  </Tab>

  <Tab title="Python">
    ## Asynchronous methods

    To use the Python API client in asynchronous environment,
    install these extra dependencies:

    ```sh Command line icon=square-terminal theme={"system"}
    python -m pip install "asyncio>=3.4,<4.0" "aiohttp>=2.0,<4.0" "async_timeout>=2.0,<4.0"
    ```

    The asynchronous methods have an `_async` prefix.

    | Sync            | Async                 |
    | --------------- | --------------------- |
    | `search`        | `search_async`        |
    | `save_objects`  | `save_objects_async`  |
    | `set_settings`  | `set_settings_async`  |
    | `save_synonyms` | `save_synonyms_async` |

    The following example creates a new index and adds two test records to it asynchronously.

    ```python Python icon=code theme={"system"}
    import asyncio

    from algoliasearch.search_client import SearchClient

    app_id = "ALGOLIA_APPLICATION_ID"
    api_key = "ALGOLIA_API_KEY"


    async def main():
        async with SearchClient.create(app_id, api_key) as client:
            index = client.init_index("INDEX_NAME")

            response = await index.save_objects_async(
                [{"objectID": 1, "name": "foo"}, {"objectID": 2, "name": "bar"}]
            )

            results = await index.search_async("")

            print(results)

        asyncio.run(main())
    ```
  </Tab>

  <Tab title="Scala">
    ### JVM DNS caching

    By default, the JVM caches DNS resolutions infinitely.
    Since Algolia uses multiple IP addresses for load balancing,
    you should reduce the time to live (TTL) of the cache.

    For example, to set the cache to 60 seconds:

    ```java Java icon=code theme={"system"}
    java.security.Security.setProperty("networkaddress.cache.ttl", "60");
    ```

    ### Debug logging

    You can **enable debug logging** in the API client using the
    [slf4j](https://www.slf4j.org) library.
    The logger is named `algoliasearch`.

    ### Domain-specific language

    The Scala API client lets you use a domain-specific language (DSL).
    The entry point of the DSL is the [`algolia.AlgoliaDSL`](https://github.com/algolia/algoliasearch-client-scala/blob/master/src/main/scala/algolia/AlgoliaDsl.scala) object.
    This DSL is used in the `execute` method of [`algolia.AlgoliaClient`](https://github.com/algolia/algoliasearch-client-scala/blob/master/src/main/scala/algolia/AlgoliaClient.scala).

    The DSL is designed to be human-readable. For some tasks there may be more than one way of achieving it. For example, to get an object by its `objectID`:

    ```scala Scala icon=code theme={"system"}
    client.execute { from index "index" objectId "myId" }
    // or
    client.execute { get / "index" / "myId" }
    ```

    ### Futures

    The `execute` method always returns a [`scala.concurrent.Future`](https://www.scala-lang.org/api/current/scala/concurrent/Future.html).
    The `Future` can be parametrized by a case class:

    ```scala Scala icon=code theme={"system"}
    val future: Future[Search] =
        client.execute {
            search into "index" query "a"
        }
    ```

    ### JSON as case class

    The Scala API client uses [`json4s`](https://json4s.org) to serialize and deserialize objects and API responses and case classes.

    For example, to deserialize a search response:

    ```scala Scala icon=code theme={"system"}
    case class Contact(firstname: String,
                       lastname: String,
                       followers: Int,
                       company: String)

    val future: Future[Seq[Contact]] =
        client
            .execute {
                search into "index" query "a"
            }
            .map { search =>
                search.as[Contact]
            }
    ```

    To get the full results from the response:

    ```scala Scala icon=code theme={"system"}
    case class EnhanceContact(firstname: String,
                              lastname: String,
                              followers: Int,
                              company: String,
                              objectID: String,
                              _highlightResult: Option[Map[String, HighlightResult]],
                              _snippetResult: Option[Map[String, SnippetResult]],
                              _rankingInfo: Option[RankingInfo]) extends Hit

    val future: Future[Seq[EnhanceContact]] =
        client
            .execute {
                search into "index" query "a"
            }
            .map { search =>
                search.asHit[EnhanceContact]
            }
    ```

    When you index your data, pass an instance of your case class to the DSL:

    ```scala Scala icon=code theme={"system"}
    client.execute {
        index into "contacts" `object` Contact("Jimmie", "Barninger", 93, "California Paint")
    }
    ```
  </Tab>
</Tabs>
