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

# Create secured API key

> Generate a secured API key without any calls to Algolia's servers.

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="Generate secured API key" href="/doc/libraries/sdk/methods/search/generate-secured-api-key" />

When you need to restrict the scope of an API key, generate a [secured API key](/doc/guides/security/api-keys#secured-api-keys) on your server, without any calls to Algolia.

You can't generate secured API keys from your Admin API key or from other secured API keys.

When you generate a secured API key, you can define several restrictions, such as how long the key is valid for and which indexes it can access.
The more restrictions you set, the longer the key will be.
If the key is longer than 500 characters, you may have problems using it on some networks.

If you want to limit the number of requests that can be made with a secured API key, you must also rate-limit the key that you use to generate it.
You can create a rate-limited key in the Algolia dashboard or use the [`add_api_key`](/doc/libraries/sdk/v1/methods/add-api-key) or [`update_api_key`](/doc/libraries/sdk/v1/methods/update-api-key) methods of an API client.

<Info>
  Secured API keys must have stricter permissions than their base API key.
  If you use the same permissions and restrictions as the base API key,
  using this key generates a `403` status error.
</Info>

## Examples

### Generate a secured API key containing a filter

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a public API key with a fixed filter
  SecuredApiKeyRestriction restriction = new SecuredApiKeyRestriction
  {
    Query = new Query { Filters = "_tags:user_42" },
  };

  client.GenerateSecuredApiKeys("YourSearchOnlyApiKey", restriction);
  ```

  ```go Go theme={"system"}
  // Create a public API key with a fixed filter
  key, err := search.GenerateSecuredAPIKey(
      "YourSearchOnlyApiKey",
      opt.Filters("_tags:user_42"),
  )
  ```

  ```java Java theme={"system"}
  // Create a public API key with a fixed filter
  SecuredApiKeyRestriction restriction =
  new SecuredApiKeyRestriction()
      .setQuery(new Query().setFilters("_tags:user_42"));

  String publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    restriction
  );
  ```

  ```js JavaScript theme={"system"}
  // Create a public API key with a fixed filter
  const publicKey = client.generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    {
      filters: '_tags:user_42'
    }
  );

  console.log(publicKey);
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a public API key with a fixed filter
  val parentAPIKey = APIKey("YourSearchOnlyApiKey")
  val restriction = SecuredAPIKeyRestriction(
      query = Query(filters = "_tags:user_42")
  )

  ClientSearch.generateAPIKey(parentAPIKey, restriction)
  ```

  ```php PHP theme={"system"}
  // Create a public API key with a fixed filter
  use \Algolia\AlgoliaSearch\SearchClient;
  $public_key = SearchClient::generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    [
      'filters' => '_tags:user_42'
    ]
  );
  ```

  ```python Python theme={"system"}
  # Create a public API key with a fixed filter
  from algoliasearch.search_client import SearchClient

  public_key = SearchClient.generate_secured_api_key(
      "YourSearchOnlyApiKey",
      {"filters": "_tags:user_42"}
  )
  ```

  ```ruby Ruby theme={"system"}
  # Create a public API key with a fixed filter
  public_key = Algolia::Search::Client.generate_secured_api_key(
    'YourSearchOnlyApiKey',
    { filters: '_tags:user_42' }
  )
  ```

  ```scala Scala theme={"system"}
  // Create a public API key with a fixed filter
  val publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    Query(filters = Some("_tags:user_42"))
  )
  ```

  ```swift Swift theme={"system"}
  // Create a public API key with a fixed filter
  let parentAPIKey = APIKey("YourSearchOnlyApiKey")
  let restriction = SecuredAPIKeyRestriction()
    .set(\.query, to: Query()
      .set(\.filters, to: "_tags:user_42"))

  let publicKey = client.generateSecuredApiKey(parentApiKey: parentAPIKey, with: restriction)
  ```
</CodeGroup>

### Generate a secured API key with an expiration date

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a public API key that expires in 1 hour
  var date = DateTime.UtcNow.AddHours(1);
  SecuredApiKeyRestriction restriction = new SecuredApiKeyRestriction
  {
    ValidUntil = ((DateTimeOffset)date).ToUnixTimeSeconds()
  };

  client.GenerateSecuredApiKeys("YourSearchOnlyApiKey", restriction);
  ```

  ```go Go theme={"system"}
  // Create a public API key that expires in 1 hour
  valid_until = time.Now().Unix() + int64(time.Hour.Seconds())
  key, err := search.GenerateSecuredAPIKey(
      "YourSearchOnlyApiKey",
      valid_until
  )
  ```

  ```java Java theme={"system"}
  // Create a public API key that expires in 1 hour
  int validUntil = (int) (System.currentTimeMillis() / 1000 + 3600);

  SecuredApiKeyRestriction restriction =
  new SecuredApiKeyRestriction()
      .setQuery(new Query().setValidUntil(validUntil));

  String publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    restriction
  );
  ```

  ```js JavaScript theme={"system"}
  // Create a public API key that expires in 1 hour
  const validUntil = Math.floor(Date.now() / 1000) + 3600;
  const publicKey = client.generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    {
      validUntil
    }
  );
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a public API key that expires in 1 hour
  val parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  val hourInMilliseconds = 60 * 60 * 1000
  val restriction = SecuredAPIKeyRestriction(
      validUntil = Time.getCurrentTimeMillis() + hourInMilliseconds
  )

  ClientSearch.generateAPIKey(parentAPIKey, restriction)
  ```

  ```php PHP theme={"system"}
  // Create a public API key that expires in 1 hour
  use \Algolia\AlgoliaSearch\SearchClient;
  $validUntil = time() + 3600;
  $public_key = SearchClient::generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    [
      'validUntil' => $validUntil
    ]
  );
  ```

  ```python Python theme={"system"}
  import time

  from algoliasearch.search_client import SearchClient

  # Create a public API key that expires in 1 hour
  valid_until = int(time.time())  + 3600
  public_key = SearchClient.generate_secured_api_key(
      "YourSearchOnlyApiKey",
      {"validUntil": valid_until}
  )
  ```

  ```ruby Ruby theme={"system"}
  # Create a public API key that expires in 1 hour
  valid_until = Time.now.to_i + 3600
  public_key = Algolia::Search::Client.generate_secured_api_key('YourSearchOnlyApiKey', { validUntil: valid_until })
  ```

  ```scala Scala theme={"system"}
  // Create a public API key that expires in 1 hour
  val validUntil = System.currentTimeMillis() / 1000 + 3600
  val publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    Query(validUntil = Some(validUntil)
  )
  ```

  ```swift Swift theme={"system"}
  // Create a public API key that expires in 1 hour
  let parentAPIKey = APIKey("YourSearchOnlyApiKey")
  let restriction = SecuredAPIKeyRestriction()
    .set(\.validUntil, to: Date().addingTimeInterval(3600).timeIntervalSince1970)

  let publicKey = client.generateSecuredApiKey(parentApiKey: parentAPIKey, with: restriction)
  ```
</CodeGroup>

### Generate a secured API key with indices restriction

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  SecuredApiKeyRestriction restriction = new SecuredApiKeyRestriction
  {
    RestrictIndices = new List<string> { "index1", "index2" }
  };

  client.GenerateSecuredApiKeys("YourSearchOnlyApiKey", restriction);
  ```

  ```go Go theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"

  key, err := search.GenerateSecuredAPIKey(
      "YourSearchOnlyApiKey",
      opt.RestrictIndices("index1", "index2"),
  )
  ```

  ```java Java theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  SecuredApiKeyRestriction restriction =
      new SecuredApiKeyRestriction()
          .setRestrictIndices(Arrays.asList("index1", "index2"))

  String publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    restriction
  );
  ```

  ```js JavaScript theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  const publicKey = client.generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    {
      restrictIndices: ['index1', 'index2']
    }
  );
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  val parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  val restriction = SecuredAPIKeyRestriction(
      restrictIndices = listOf(
          IndexName("index1"),
          IndexName("index2")
      )
  )

  ClientSearch.generateAPIKey(parentAPIKey, restriction)
  ```

  ```php PHP theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  use \Algolia\AlgoliaSearch\SearchClient;
  $public_key = SearchClient::generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    [
      'restrictIndices' => ['index1', 'index2']
    ]
  );
  ```

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

  # Create a public API key that is restricted to "index1" and "index2"
  public_key = SearchClient.generate_secured_api_key(
      "YourSearchOnlyApiKey",
      {"restrictIndices": ["index1", "index2"]}
  )
  ```

  ```ruby Ruby theme={"system"}
  # Create a public API key that is restricted to "index1" and "index2"
  public_key = Algolia::Search::Client.generate_secured_api_key(
    'YourSearchOnlyApiKey',
    {
      restrictIndices: ['index1', 'index2']
    }
  )
  ```

  ```scala Scala theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  val publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    Query(restrictIndices = Some(Seq("index1", "index2"))
  )
  ```

  ```swift Swift theme={"system"}
  // Create a public API key that is restricted to "index1" and "index2"
  let parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  let restriction = SecuredAPIKeyRestriction()
    .set(\.restrictIndices, to: ["index1", "index2"])

  let publicKey = client.generateSecuredApiKey(parentApiKey: parentAPIKey, with: restriction)

  ```
</CodeGroup>

### Generate a secured API key with a network restriction

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  SecuredApiKeyRestriction restriction = new SecuredApiKeyRestriction
  {
      RestrictSources = "192.168.1.0/24",
  };

  client.GenerateSecuredApiKeys("YourSearchOnlyApiKey", restriction);
  ```

  ```go Go theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  key, err := search.GenerateSecuredAPIKey(
      "YourSearchOnlyApiKey",
      opt.RestrictSources("192.168.1.0/24"),
  )
  ```

  ```java Java theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  SecuredApiKeyRestriction restriction =
  new SecuredApiKeyRestriction()
      .setRestrictSources(Collections.singletonList("192.168.1.0/24"));

  String publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    restriction
  );
  ```

  ```js JavaScript theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  const publicKey = client.generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    {
      restrictSources: '192.168.1.0/24'
    }
  );
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  val parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  val restriction = SecuredAPIKeyRestriction(
      restrictSources = listOf("192.168.1.0/24")
  )

  ClientSearch.generateAPIKey(parentAPIKey, restriction)
  ```

  ```php PHP theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  use \Algolia\AlgoliaSearch\SearchClient;
  $public_key = SearchClient::generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    [
      'restrictSources' => '192.168.1.0/24'
    ]
  );
  ```

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

  # Create a public API key that is restricted to `192.168.1.0/24`
  public_key = SearchClient.generate_secured_api_key(
      'YourSearchOnlyApiKey',
      {'restrictSources': '192.168.1.0/24'}
  )
  ```

  ```ruby Ruby theme={"system"}
  # Create a public API key that is restricted to `192.168.1.0/24`
  public_key = Algolia::Search::Client.generate_secured_api_key('YourSearchOnlyApiKey', { restrictSources: '192.168.1.0/24' })
  ```

  ```scala Scala theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  String publicKey = client.generateSecuredApiKey(
      "YourSearchOnlyApiKey",
      Query(restrictSources = Some("192.168.1.0/24"))
  )
  ```

  ```swift Swift theme={"system"}
  // Create a public API key that is restricted to `192.168.1.0/24`
  let parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  let restriction = SecuredAPIKeyRestriction()
    .set(\.restrictSources, to: ["192.168.1.0/24"])

  let publicKey = client.generateSecuredApiKey(parentApiKey: parentAPIKey, with: restriction)
  ```
</CodeGroup>

### Generate a secured API key with rate-limiting applied per user

<CodeGroup>
  ```cs C# theme={"system"}
  // Create a public API key for a specific user
  SecuredApiKeyRestriction restriction = new SecuredApiKeyRestriction
  {
      UserToken = "42"
  };

  client.GenerateSecuredApiKeys("YourSearchOnlyApiKey", restriction);
  ```

  ```go Go theme={"system"}
  // Create a public API key for a specific user
  key, err := search.GenerateSecuredAPIKey(
      "YourSearchOnlyApiKey",
      opt.UserToken("user_42"),
  )
  ```

  ```java Java theme={"system"}
  // Create a public API key for a specific user
  SecuredApiKeyRestriction restriction =
  new SecuredApiKeyRestriction()
      .setQuery(new Query().setUserToken("42"));

  String publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    restriction
  );
  ```

  ```js JavaScript theme={"system"}
  // Create a public API key for a specific user
  const publicKey = client.generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    {
      userToken: 'user_42'
    }
  );
  ```

  ```kotlin Kotlin theme={"system"}
  // Create a public API key for a specific user
  val parentAPIKey = APIKey("YourSearchOnlyAPIKey")
  val restriction = SecuredAPIKeyRestriction(
      userToken = UserToken("42")
  )

  ClientSearch.generateAPIKey(parentAPIKey, restriction)
  ```

  ```php PHP theme={"system"}
  // Create a public API key for a specific user
  use \Algolia\AlgoliaSearch\SearchClient;
  $public_key = SearchClient::generateSecuredApiKey(
    'YourSearchOnlyApiKey',
    [
      'userToken' => 'user_42'
    ]
  );
  ```

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

  # Create a public API key for a specific user
  public_key = SearchClient.generate_secured_api_key(
      'YourSearchOnlyApiKey',
      {'userToken': 'user_42'}
  )
  ```

  ```ruby Ruby theme={"system"}
  # The rate limit will be based on the passed user token
  public_key = Algolia::Search::Client.generate_secured_api_key('YourSearchOnlyApiKey', { userToken: 'user_42' })
  ```

  ```scala Scala theme={"system"}
  // The rate limit will be based on the passed user token
  // Create a public API key for a specific user

  val publicKey = client.generateSecuredApiKey(
    "YourSearchOnlyApiKey",
    Query(userToken = Some("42"))
  )
  ```

  ```swift Swift theme={"system"}
  // Create a public API key for a specific user
  let parentAPIKey = APIKey("SearchOnlyAPIKey")
  let restriction = SecuredAPIKeyRestriction()
    .set(\.query, to: Query()
      .set(\.userToken, to: "42")
    )

  let publicKey = client.generateSecuredApiKey(parentApiKey: parentAPIKey, with: restriction)
  ```
</CodeGroup>

## Parameters

<ParamField body="apiKey" type="string" required>
  The search-only API key that the secured API key will inherit its restrictions from.
</ParamField>

<ParamField body="filters" type="string">
  Filters that apply to every search made with the secured API key.
  You can add extra filters at search time with the [`filters`](/doc/api-reference/api-parameters/filters) parameter.

  For example, if you set the filter `group:admin` on your generated API key, and you add `groups:press OR groups:visitors` with the `filters` query parameter, your final search filter is equivalent to `groups:admin AND (groups:press OR groups:visitors)`.
</ParamField>

<ParamField body="restrictIndices" type="list">
  Index names that can be queried.
  By default, all indices are queried.
</ParamField>

<ParamField body="restrictSources" type="string">
  IPv4 network allowed to use the generated key. Use this to protect against API key leaking and reuse.

  You can only provide a single source, but you can specify a range of IPs (for example, `192.168.1.0/24`).
</ParamField>

<ParamField body="searchParameter" type="object">
  [Search parameters](/doc/api-reference/search-api-parameters) applied at query time.

  If you specify any of the following parameters in both the API key (`A`) and in your search (`B`),
  they are combined (`A AND B`):

  * [`filters`](/doc/api-reference/api-parameters/filters)
  * [`facetFilters`](/doc/api-reference/api-parameters/facetFilters)
  * [`optionalFilters`](/doc/api-reference/api-parameters/optionalFilters)
  * [`numericFilters`](/doc/api-reference/api-parameters/numericFilters)
</ParamField>

<ParamField body="userToken" type="string">
  Unique user IP address.

  This can be useful when you want to impose [a rate limit on specific users](/doc/guides/security/api-keys/in-depth/api-key-restrictions#rate-limit). By default, rate limits are set based on the IP address. This can become an issue when several users search from the same IP address. To avoid this, you can set a unique `userToken` for each user when generating their API key. This lets you restrict each user to a maximum number of API calls per hour, even if they share their IP with another user.

  Specifying the `userToken` in a secured API key is also a good security practice as it ensures users don't change it.
  Many features like Analytics, Personalization, and Dynamic Re-ranking rely on the authenticity of user identifiers.
  Setting the `userToken` at the API key level ensures that downstream services work as expected and prevents abuse.
</ParamField>

<ParamField body="validUntil" type="integer">
  [Unix timestamp](https://www.unixtimestamp.com/) used to set the expiration date of the API key.
</ParamField>

## Response

<ResponseField name="api_key" type="string">
  The generated API 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"}
"YTgyMzMwOTkzMjA2Mzk5OWUxNjhjYmIwMGZkNGFmMzk2NDU3ZjMyYTg1NThiZjgxNDRiOTk3ZGE3NDU4YTA3ZWZpbHRlcnM9X3RhZ3MlM0F1c2VyXzQy"
```
