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

# Rotate an Existing API Key

> Invalidate an existing AgriBackup API key and issue a replacement with identical scopes. The new raw key is returned exactly once.

Key rotation is a security best practice that lets you replace an API key without permanently losing access — for example, when a key has been accidentally exposed, as part of a scheduled rotation policy, or after a personnel change. When you rotate a key, AgriBackup immediately deactivates the existing key identified by `keyId` and issues a brand-new key that inherits the same name and permission scopes. Any in-flight requests using the old key will begin to receive `401 Unauthorized` responses as soon as the rotation completes. Store the new `rawApiKey` immediately — it is returned only once.

**`POST /api/v1/enterprise/api-keys/{keyId}/rotate`**

## Path Parameters

<ParamField path="keyId" type="string" required>
  The unique identifier of the API key you want to rotate. You can find this value in the `id` field returned by the [List API Keys](/sdks/enterprise-api-keys/list-api-keys) or [Generate API Key](/sdks/enterprise-api-keys/generate-a-new-api-key) endpoints.

  **Example:** `key_a1b2c3d4e5f6`
</ParamField>

## Code Examples

<CodeGroup>
  ```python Python theme={null}
  import agribackup
  from agribackup.rest import ApiException

  configuration = agribackup.Configuration(host="https://live.agribackup.com/api/v1")
  configuration.api_key["ApiKeyAuth"] = "sk_live_YOUR_API_KEY"

  key_id = "key_a1b2c3d4e5f6"

  with agribackup.ApiClient(configuration) as api_client:
      try:
          api_instance = agribackup.EnterpriseAPIKeysApi(api_client)
          response = api_instance.rotate_api_key(key_id=key_id)
          # Update your secrets store with response.raw_api_key immediately
          print(response)
      except ApiException as e:
          print("Exception when calling API: %s\n" % e)
  ```

  ```javascript Node.js theme={null}
  import { AgriBackupClient } from "@agribackup/sdk";

  const client = new AgriBackupClient({
    apiKey: "sk_live_YOUR_API_KEY",
    baseUrl: "https://live.agribackup.com/api/v1",
  });

  async function rotateApiKey(keyId) {
    try {
      const response = await client.keys.rotateApiKey(keyId);
      // Update your secrets store with response.rawApiKey immediately
      console.log(response);
    } catch (error) {
      console.error(error);
    }
  }

  rotateApiKey("key_a1b2c3d4e5f6");
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url https://live.agribackup.com/api/v1/enterprise/api-keys/key_a1b2c3d4e5f6/rotate \
    --header "Authorization: Bearer sk_live_YOUR_API_KEY"
  ```
</CodeGroup>

## Response

A `200 OK` response confirms the old key has been invalidated and a replacement has been issued. The `rawApiKey` in the response is the new key value — update your secrets store with it before closing the response.

```json theme={null}
{
  "id": "key_m3n4o5p6q7r8",
  "name": "Production ERP Integration",
  "rawApiKey": "sk_live_NewKeyValueXyZ9876543210AbCdEfGhIj",
  "scopes": ["*"],
  "createdAt": "2026-07-01T08:15:00Z"
}
```

<ResponseField name="id" type="string">
  The identifier of the **newly issued** replacement key. Note that this differs from the `keyId` you submitted in the path — the old key has been deactivated and replaced with this new one.
</ResponseField>

<ResponseField name="name" type="string">
  The name inherited from the rotated key, unchanged.
</ResponseField>

<ResponseField name="rawApiKey" type="string">
  The plaintext value of the newly generated replacement key. This is returned **exactly once**. Update your secrets manager immediately. The previous key is now permanently invalidated.
</ResponseField>

<ResponseField name="scopes" type="array of strings">
  The permission scopes inherited from the rotated key, unchanged.
</ResponseField>

<ResponseField name="createdAt" type="string (ISO 8601)">
  The UTC timestamp at which the replacement key was generated.
</ResponseField>

## Error Responses

| HTTP Status             | Error Code     | Description                                                                                             |
| ----------------------- | -------------- | ------------------------------------------------------------------------------------------------------- |
| `401 Unauthorized`      | `UNAUTHORIZED` | The `Authorization` header is absent or the bearer token is invalid.                                    |
| `403 Forbidden`         | `FORBIDDEN`    | The authenticated identity does not have permission to rotate API keys for this organization.           |
| `404 Not Found`         | `NOT_FOUND`    | No API key with the provided `keyId` exists for this organization, or the key has already been deleted. |
| `429 Too Many Requests` | `RATE_LIMITED` | You have exceeded the hourly rate limit. Check `X-RateLimit-Reset` for your reset time.                 |

```json theme={null}
{
  "code": "NOT_FOUND",
  "message": "API key not found",
  "details": [
    {
      "code": "KEY_NOT_FOUND",
      "field": "keyId",
      "issue": "No active API key with ID 'key_a1b2c3d4e5f6' exists for this organization"
    }
  ]
}
```
