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

# Add API key

> Add a new API Key with specific permissions and restrictions.

export const Legacy = ({title, href}) => {
  return <Note>

    This page documents an earlier version of the API client.
    For the latest version, see <a href={href}>{title}</a>.

    </Note>;
};

<Legacy title="Create an API key" href="/doc/libraries/sdk/methods/search/add-api-key" />

**Required ACL:** `Admin`

## Examples

### Create new API key

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a new API key that can only perform search actions
  var res = client.AddApiKey(new ApiKey
  {
    Acl = new List<string> { "search" }
  });

  // Wait until the key is added
  res.wait();

  // Asynchronous
  var res = await client.AddApiKeyAsync(new ApiKey
  {
    Acl = new List<string> { "search" }
  });
  ```

  ```go Go theme={"system"}
  // Create a new API key that can only perform search actions
  key := search.Key {
    ACL: []string{"search"},
  }

  res, err := client.AddAPIKey(key)

  if err != nil {
    panic(err)
  }

  fmt.Println(res.Key)
  ```

  ```java Java theme={"system"}
  // Create a new API key that can only perform search actions
  ApiKey apiKey = new ApiKey().setAcl(Collections.singletonList("search")));

  // Synchronous
  AddApiKeyResponse res = client.addApiKey(apiKey);

  // Asynchronous
  client.addApiKeyAsync(apiKey);
  ```

  ```js JavaScript theme={"system"}
  // Create a new API key that can only perform search actions
  client.addApiKey(['search']).then(({ key }) => {
    console.log(key);
  });
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a new API key that can only perform search actions
  val params = APIKeyParams(
      ACLs = listOf(ACL.Search)
  )
  client.apply {
      val response = addAPIKey(params)
  }
  ```

  ```php PHP theme={"system"}
  // Create a new API key that can only perform search actions
  $res = $client->addApiKey(['search']);
  echo 'key: ' . $res['key'] . "\n";
  ```

  ```python Python theme={"system"}
  # Create a new API key that can only perform search actions
  res = client.add_api_key(['search'])
  print(res['key'])
  ```

  ```ruby Ruby theme={"system"}
  # Create a new API key that can only perform search actions
  res = client.add_api_key(['search'])
  puts res.raw_response[:key]
  ```

  ```scala Scala theme={"system"}
  // Create a new API key that can only perform search actions
  client.execute {
    add key ApiKey(
      acl = Some(Seq(Acl.search)),
    )
  }
  ```

  ```swift Swift theme={"system"}
  // Create a new API key that can only perform search actions
  let params = APIKeyParameters(ACLs: [.search])

  client.addAPIKey(with: params) { result in
    if case .success(let apiKeyCreation) = result {
      print(apiKeyCreation.key)
    }
  }
  ```
</CodeGroup>

### Create new API Key with specific restrictions

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a new restricted search-only API key
  ApiKey param = new ApiKey
  {
      Acl = new List<string> { "search" },
      Description = "Restricted search-only API key for algolia.com",
      // Allow searching only in indices with names starting with `dev_*`
      Indexes = new List<string> { "dev_*" },
      // Retrieve up to 20 results per search query
      MaxHitsPerQuery = 20,
      // Rate-limit to 100 requests per hour per IP address
      MaxQueriesPerIPPerHour = 100,
      // Add fixed query parameters to every search request
      QueryParameters = "ignorePlurals=false",
      // Only allow searches from the `algolia.com` domain
      Referers = new List<string> { "algolia.com/*" },
      // This API key expires after 300 seconds (5 minutes)
      Validity = 300,
  };

  var res = index.AddApiKey(param);
  // Asynchronous:
  // var res = await index.AddApiKeyAsync(param);
  ```

  ```go Go theme={"system"}
  // Create a new restricted search-only API key
  key := search.Key {
    ACL: []string{"search"},
    Description: "Restricted search-only API key for algolia.com",
    // Allow searching only in indices with names starting with `dev_*`
    Indexes: []string{"dev_*"},
    // Retrieve up to 20 results per search query
    MaxHitsPerQuery: 20,
    // Rate-limit to 100 requests per hour per IP address
    MaxQueriesPerIPPerHour: 100,
    // Only allow searches from the `algolia.com` domain
    Referers: []string{"algolia.com/*"}
    // This API key expires after 300 seconds (5 minutes)
    Validity: 300
  }
  // Add fixed query parameters to every search request
  // add import: `github.com/algolia/algoliasearch-client-go/v3/algolia/opt`
  key.SetQueryParameters(opt.IgnorePlurals(false))

  res, err := client.AddAPIKey(key)

  if err != nil {
    panic(err)
  )
  ```

  ```java Java theme={"system"}
  // Create a new restricted search-only API key
  ApiKey apiKey = new ApiKey()
    // Allow only search
    .setAcl(Collections.singletonList("search"))
    .setDescription("Restricted search-only API key for algolia.com");
    // Allow searching only in indices with names starting with `dev_*`
    .setIndexes(Collections.singletonList("dev_*"))
    // Retrieve up to 20 results per search query
    .setMaxHitsPerQuery(20)
    // Rate-limit to 100 requests per hour per IP address
    .setMaxQueriesPerIPPerHour(100)
    // Add fixed query parameters to every search request
    .setQueryParameters("ignorePlurals=false")
    // Only allow searches from the `algolia.com` domain
    .setReferers(Collections.singletonList("algolia.com/*"))
    // This API key expires after 300 seconds (5 minutes)
    .setValidity(300L)

  AddApiKeyResponse res = client.addApiKey(apiKey);
  // Asynchronous:
  // client.addApiKeyAsync(apiKey);
  ```

  ```js JavaScript theme={"system"}
  // Create a new restricted search-only API key
  client.addApiKey(['search'], {
    description: 'Restricted search-only API key for algolia.com'
    // Allow searching only in indices with names starting with `dev_*`
    indexes: ['dev_*'],
    // Retrieve up to 20 results per search query
    maxHitsPerQuery: 20,
    // Rate-limit to 100 requests per hour per IP address
    maxQueriesPerIPPerHour: 100,
    // Add fixed query parameters to every search request
    queryParameters: 'ignorePlurals=false',
    // Only allow searches from the `algolia.com` domain
    referers: ['algolia.com/*'],
    // This API key expires after 300 seconds (5 minutes)
    validity: 300,
  }).then(({ key }) => {
    console.log(key);
  });
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a new restricted search-only API key
  val params = APIKeyParams(
      ACLs = listOf(ACL.Search),
      description = "Restricted search only API key for algolia.com",
      // Allow searching only in indices with names starting with `dev_*`
      indices = listOf(IndexName("dev_*")),
      // Retrieve up to 20 results per search query
      maxHitsPerQuery = 20,
      // Rate-limit to 100 requests per hour per IP address
      maxQueriesPerIPPerHour = 100,
      // Add fixed query parameters to every search request
      query = Query(
          ignorePlurals = IgnorePlurals.False
      ),
      // Only allow searches from the `algolia.com` domain
      referers = listOf("algolia.com/*"),
      // This API key expires after 300 seconds (5 minutes)
      validity = 300
  )
  client.apply {
      val response = client.addAPIKey(params).wait()

      client.deleteAPIKey(response.apiKey)
  }
  ```

  ```php PHP theme={"system"}
  // Create a new restricted search-only API key
  $res = $client->addApiKey(['search'],
    [
      'description'            => 'Restricted search-only API key for algolia.com',
      // Allow searching only in indices with names starting with `dev_*`
      'indexes'                => ['dev_*'],
      // Retrieve up to 20 results per search query
      'maxHitsPerQuery'        => 20,
      // Rate-limit to 100 requests per hour per IP address
      'maxQueriesPerIPPerHour' => 100,
      // Add fixed query parameters to every search request
      'queryParameters'        => 'ignorePlurals=false',
      // Only allow searches from the `algolia.com` domain
      'referers'               => ['algolia.com/*'],
      // This API key expires after 300 seconds (5 minutes)
      'validity'               => 300,
  ]);

  echo 'key=' . $res['key'] . "\n";
  ```

  ```python Python theme={"system"}
  # Create a new restricted search-only API key
  params = {
      'description': 'Restricted search-only API key for algolia.com',
      # Allow searching only in indices with names starting with `dev_*`
      'indexes': ['dev_*'],
      # Retrieve up to 20 results per search query
      'maxHitsPerQuery': 20,
      # Rate-limit to 100 requests per hour per IP address
      'maxQueriesPerIPPerHour': 100,
      # Add fixed query parameters to every search request
      'queryParameters': 'ignorePlurals=false',
      # Only allow searches from the `algolia.com` domain
      'referers': ['algolia.com/*'],
      # This API key expires after 300 seconds (5 minutes)
      'validity': 300,
  }

  acl = ['search']
  res = client.add_api_key(acl, params)
  print(res["key"])
  ```

  ```ruby Ruby theme={"system"}
  # Create a new restricted search-only API key
  opts = {
    description: 'Restricted search-only API key for algolia.com'
    # Allow searching only in indices with names starting with `dev_*`
    indexes: ['dev_*'],
    # Retrieve up to 20 results per search query
    maxHitsPerQuery: 20,
    # Rate-limit to 100 requests per hour per IP address
    maxQueriesPerIPPerHour: 100,
    # Add fixed query parameters to every search request
    queryParameters: 'ignorePlurals=false',
    # Only allow searches from the `algolia.com` domain
    referers: ['algolia.com/*'],
    # This API key expires after 300 seconds (5 minutes)
    validity: 300,
  }

  acl = ['search']
  res = client.add_api_key(acl, opts)
  puts res.raw_response[:key]
  ```

  ```scala Scala theme={"system"}
  // Create a new restricted search-only API key
  val apiKey = ApiKey(
    acl = Some(Seq(Acl.search)),
    description = Some("Restricted search-only API key for algolia.com")
    // Allow searching only in indices with names starting with `dev_*`
    indexes = Some(Seq("myIndex")),
    // Retrieve up to 20 results per search query
    maxHitsPerQuery = Some(20)),
    // Rate-limit to 100 requests per hour per IP address
    maxQueriesPerIPPerHour = Some(100),
    // Add fixed query parameters to every search request
    queryParameters = Some(Seq("ignorePlurals=false")),
    // Only allow searches from the `algolia.com` domain
    referers = Some(Seq("algolia.com/*")),
    // This API key expires after 300 seconds (5 minutes)
    validity = Some(300),
  )

  client.execute {
    add key apiKey
  }
  ```

  ```swift Swift theme={"system"}
  // Create a new restricted search-only API key
  let params = APIKeyParameters(ACLs: [.search])
    .set(\.description, to: "Restricted search-only API key for algolia.com")
    // Allow searching only in indices with names starting with `dev_*`
    .set(\.indices, to: ["dev_*"])
    // Retrieve up to 20 results per search query
    .set(\.maxHitsPerQuery, to: 20)
    // Rate-limit to 100 requests per hour per IP address
    .set(\.maxQueriesPerIPPerHour, to: 100)
    // Add fixed query parameters to every search request
    .set(\.query, to: Query()
      .set(\.ignorePlurals, to: false)
    )
    // Only allow searches from the `algolia.com` domain
    .set(\.referers, to: ["algolia.com/*"])
    // This API key expires after 300 seconds (5 minutes)
    .set(\.validity, to: 300)

  client.addAPIKey(with: params) { result in
    if case .success(let response) = result {
    }
  }
  ```
</CodeGroup>

## Parameters

<ParamField body="acl" type="string[]" required>
  Set of permissions associated with the key.

  The possible access controls are:

  * **Search** (`search`): allowed to perform search operations.
  * **Browse Index** (`browse`): allowed to retrieve all index data with the `browse` endpoint.
  * **Add records** (`addObject`): allowed to add or update records in the index.
  * **Delete records** (`deleteObject`): allowed to delete an existing record.
  * **List indices** (`listIndexes`): allowed to get a list of all existing indices.
  * **Delete index** (`deleteIndex`): allowed to delete an index.
  * **Get index settings** (`settings`): allowed to read all index settings.
  * **Set index settings** (`editSettings`): allowed to update all index settings.
  * **Use analytics API** (`analytics`): allowed to retrieve data with the Analytics API.
  * **Use personalization API** (`recommendation`): allowed to interact with the Personalization API.
  * **Use usage API** (`usage`): allowed to retrieve data with the Usage API.
  * **Access logs** (`logs`): allowed to query the logs.
  * **Get unretrievable attributes** (`seeUnretrievableAttributes`): allowed to retrieve [`unretrievableAttributes`](/doc/api-reference/api-parameters/unretrievableAttributes) for all operations that return records.
</ParamField>

<ParamField body="description" type="string">
  Specify a description of the API key.
  Used for informative purposes only. It has impact on the functionality
  of the API key.
</ParamField>

<ParamField body="indexes" type="string[]">
  Specify the list of targeted indices.
  By default, the API key can access all 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`.
</ParamField>

<ParamField body="maxHitsPerQuery" type="integer" default={0}>
  Maximum number of hits this API key can retrieve in one query.
  A value of `0` means the API key has no restrictions on the number of hits.

  You can set this parameter to prevent attempts at retrieving your
  entire index in a single API call.

  **This parameter must be a positive integer.**
</ParamField>

<ParamField body="maxQueriesPerIPPerHour" type="integer" default={0}>
  Maximum number of API calls per hour allowed from an IP address.
  A value of `0` means no restriction on the number of API requests.

  You can set this parameter to prevent attempts at retrieving your
  entire index through making many API calls.

  Each time an API call is performed with this key, a check is performed.

  If the IP address at the origin of the call made more than `maxQueriesPerIPPerHour` queries within the last hour,
  the API returns a `429 Too Many Requests` status code.

  Note that the rate limit computation is not accurate, and may be estimated individually by each server receiving the calls. On a three node server, you might have to take account that each of servers may accept up to the maximum limit each.

  **This parameter must be a positive integer.**
</ParamField>

<ParamField body="queryParameters" type="string">
  Specify the list of query parameters.
  You can force the query parameters for a query using the url string format.

  **Example:** `typoTolerance=strict&ignorePlurals=false`

  You can also add a restriction on the IPv4 network allowed to use the generated key.
  This is used for more protection against API key leaking and reuse.

  Note that you can only provide a single source, but you can specify a range of IPs (e.g., `192.168.1.0/24`).

  For security reasons, the creation of the key will fail if the server from which the key is created is not in the restricted network.

  **Example:** `typoTolerance=strict&restrictSources=192.168.1.0/24`
</ParamField>

<ParamField body="referers" type="string[]">
  Specify the list of referrers that can perform an operation.
  By default, all referrers are allowed.
  You can use the `*` (asterisk) character as a wildcard to match subdomains, or all pages of a website.
  For example, `https://algolia.com/*` matches all referrers starting with `https://algolia.com/`,
  and `*.algolia.com` matches all referrers ending with `.algolia.com`.
  To allow all possible referrers from the `algolia.com` domain, use `*algolia.com/*`.

  This also works with `localhost`, when you're developing your site:
  `*localhost*` matches all possible referrers on `localhost`.
</ParamField>

<ParamField body="requestOptions" type="object">
  A mapping of request options to send along with the request.
</ParamField>

<ParamField body="validity" type="integer" default={0}>
  How long this API key is valid, in seconds.
  A value of `0` means the API key doesn't expire.

  **This parameter must be a positive integer.**
</ParamField>

## Response

<ResponseField name="createdAt" type="string">
  The date at which the key has been created.
</ResponseField>

<ResponseField name="key" type="string">
  The created key.
</ResponseField>

### Response as JSON

This section shows the JSON response returned by the API.
Each API client wraps this response in language-specific objects, so the structure may vary.
To view the response, use the `getLogs` method.
Don't rely on the order of properties—JSON objects don't preserve key order.

```jsonc JSON icon=braces theme={"system"}
{
  "key": "1eb37de6308abdccf9b760ddacb418b4",
  "createdAt": "2017-12-16T22:21:31.871Z"
}
```
