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

# kosli_service_account_api_key resource

> Manages an API key for a Kosli service account. The raw key value is returned only once, at creation time, and is stored in Terraform state as a sensitive value.

Manages an API key for a Kosli service account. API keys authenticate a service account against the Kosli API. Use this resource to mint and revoke keys for a service account managed with the [`kosli_service_account` resource](/terraform-reference/resources/service_account).

<Warning>
  The raw `key` value is returned **only once**, at creation time, and is stored in Terraform state as a sensitive value. It is SHA-256 hashed server-side and can never be retrieved again — protect your Terraform state accordingly.
</Warning>

<Note>
  API keys are immutable. Changing `description`, `expires_at`, or `service_account_name` revokes the existing key and creates a new one. On `terraform import`, the `key` attribute cannot be populated because the raw value is not retrievable.
</Note>

## Example usage

```terraform theme={"theme":"dracula","languages":{"custom":["/languages/rego.json"]}}
terraform {
  required_providers {
    kosli = {
      source = "kosli-dev/kosli"
    }
  }
}

# Service account that the API key belongs to
resource "kosli_service_account" "ci" {
  name        = "ci-pipeline"
  description = "CI/CD pipeline service account"
  privilege   = "member"
}

# A non-expiring API key
resource "kosli_service_account_api_key" "ci_key" {
  service_account_name = kosli_service_account.ci.name
  description          = "Production CI key"
}

# An API key that expires (RFC3339 timestamp)
resource "kosli_service_account_api_key" "ci_key_expiring" {
  service_account_name = kosli_service_account.ci.name
  description          = "Temporary CI key"
  expires_at           = "2100-01-01T00:00:00Z"
}

# The raw key is only available on creation and is sensitive
output "ci_api_key" {
  value     = kosli_service_account_api_key.ci_key.key
  sensitive = true
}
```

## Expiry

The `expires_at` attribute is an RFC3339 timestamp, e.g. `2100-01-01T00:00:00Z` (offsets such as `+01:00` are accepted and normalized to UTC). Omit it for a key that never expires. The timestamp must not be in the past.

To derive dates dynamically, use Terraform's built-in functions, e.g. `timeadd("2026-01-01T00:00:00Z", "8760h")`.

<Note>
  All timestamps (`expires_at`, `created_at`, `last_used_at`) are RFC3339 UTC strings. `last_used_at` is null for a key that has never been used; `expires_at` is null for a key that never expires.
</Note>

## Import

API keys can be imported using the `<service_account_name>/<key_id>` format:

```shell theme={"theme":"dracula","languages":{"custom":["/languages/rego.json"]}}
# Import an existing API key using the "<service_account_name>/<key_id>" format.
# Note: the raw key value cannot be recovered on import (it is only returned once
# at creation), so the "key" attribute will be empty after import.
terraform import kosli_service_account_api_key.ci_key ci-pipeline/01HXYZ0123456789ABCDEFGHIJ
```

Because the raw key value is only returned at creation time, the `key` attribute is empty after an import.

## Schema

### Required

* `description` (String) Description of the API key (at least one character). Changing this forces creation of a new key.
* `service_account_name` (String) Name of the service account this API key belongs to. Changing this forces creation of a new key.

### Optional

* `expires_at` (String) RFC3339 timestamp at which the key expires, e.g. `2100-01-01T00:00:00Z` (offsets allowed; whole seconds only). Omit for a key that never expires. Must not be in the past (validated server-side at apply time). Changing this forces creation of a new key. Removing a previously set value from configuration leaves the existing expiry unchanged; to get a non-expiring key again, the key must be recreated (e.g. via `terraform taint` or by changing another argument).

### Read-only

* `created_at` (String) RFC3339 UTC timestamp of when the API key was created.
* `id` (String) Server-assigned identifier of the API key.
* `key` (String, Sensitive) The raw API key value. Only available at creation time and stored as a sensitive value. Empty when the resource is imported.
* `last_used_at` (String) RFC3339 UTC timestamp of when the API key was last used. Null if the key has never been used.
