# IApiKeyStore

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.iapikeystore/
> Summary: IApiKeyStore: The store for per-tenant API keys.

<div class="api-provenance">Namespace Tracon · Assembly <code>Tracon.Abstractions.dll</code></div>

The store for per-tenant API keys.

```csharp
public interface IApiKeyStore
```

## Remarks

A second identity source alongside the static bearer token,
bound to a tenant and carrying a scope; it does not replace the static
token.

## Methods

### <a id="Tracon_IApiKeyStore_CreateAsync_Tracon_ApiKeyDraft_System_Threading_CancellationToken_"></a> CreateAsync\(ApiKeyDraft, CancellationToken\)

Generates and stores a new key.

```csharp
ValueTask<ApiKeyCreationResult> CreateAsync(ApiKeyDraft draft, CancellationToken cancellationToken = default)
```

#### Parameters

`draft` [ApiKeyDraft](/api/tracon.apikeydraft/)

The key's draft.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[ApiKeyCreationResult](/api/tracon.apikeycreationresult/)\>

The saved record and the raw key value. The raw value cannot be
produced again after this call.

#### Remarks

Produce the raw value, its digest, and its display prefix with
[ApiKeyGenerator.Generate](/api/tracon.apikeygenerator/#Tracon_ApiKeyGenerator_Generate_System_String_). A presented key is looked up by
[ApiKeyGenerator.ComputeHash](/api/tracon.apikeygenerator/#Tracon_ApiKeyGenerator_ComputeHash_System_String_), so a key made any other way
never authenticates.

### <a id="Tracon_IApiKeyStore_FindByHashAsync_System_ReadOnlyMemory_System_Byte__System_Threading_CancellationToken_"></a> FindByHashAsync\(ReadOnlyMemory<byte\>, CancellationToken\)

Looks up a key by its SHA-256 digest.

```csharp
ValueTask<ApiKeyRecord?> FindByHashAsync(ReadOnlyMemory<byte> keyHash, CancellationToken cancellationToken = default)
```

#### Parameters

`keyHash` [ReadOnlyMemory](https://learn.microsoft.com/dotnet/api/system.readonlymemory\-1)<[byte](https://learn.microsoft.com/dotnet/api/system.byte)\>

The digest of the presented raw value, as [ApiKeyGenerator.ComputeHash](/api/tracon.apikeygenerator/#Tracon_ApiKeyGenerator_ComputeHash_System_String_)
computes it.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[ApiKeyRecord](/api/tracon.apikeyrecord/)?\>

The record; [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) if it does not exist.

#### Remarks

No tenant filter **is applied**: the tenant is the
OUTPUT of this call, not its INPUT — while authenticating a request,
which tenant it belongs to is not yet known. The lookup
always goes through the digest; the raw value never enters any query directly.

### <a id="Tracon_IApiKeyStore_HasActiveScopeAsync_Tracon_ApiKeyScope_System_Threading_CancellationToken_"></a> HasActiveScopeAsync\(ApiKeyScope, CancellationToken\)

Reports whether at least one key exists in the system (in any tenant)
that carries the given scope, is not revoked, and has not expired.

```csharp
ValueTask<bool> HasActiveScopeAsync(ApiKeyScope scope, CancellationToken cancellationToken = default)
```

#### Parameters

`scope` [ApiKeyScope](/api/tracon.apikeyscope/)

The scope to look for.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[bool](https://learn.microsoft.com/dotnet/api/system.boolean)\>

[true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) if found.

#### Remarks

There is deliberately no tenant filter: this is an installation
health check, not specific
to any tenant — it asks whether the system has at least one valid
`external:invoke` key, so the external surface can be opened
TOGETHER with `AllowRemoteAccess`.

### <a id="Tracon_IApiKeyStore_ListAsync_System_String_System_Threading_CancellationToken_"></a> ListAsync\(string, CancellationToken\)

Lists a tenant's keys. The raw value and digest are not returned.

```csharp
ValueTask<IReadOnlyList<ApiKeyRecord>> ListAsync(string tenantId, CancellationToken cancellationToken = default)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The tenant identifier.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[IReadOnlyList](https://learn.microsoft.com/dotnet/api/system.collections.generic.ireadonlylist\-1)<[ApiKeyRecord](/api/tracon.apikeyrecord/)\>\>

The keys, by creation time.

### <a id="Tracon_IApiKeyStore_RevokeAsync_System_String_System_Guid_System_Threading_CancellationToken_"></a> RevokeAsync\(string, Guid, CancellationToken\)

Revokes a key. The row is not DELETED; `revoked_at` is written.

```csharp
ValueTask<bool> RevokeAsync(string tenantId, Guid id, CancellationToken cancellationToken = default)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The tenant the key is bound to.

`id` [Guid](https://learn.microsoft.com/dotnet/api/system.guid)

The key identifier.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[bool](https://learn.microsoft.com/dotnet/api/system.boolean)\>

[true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) if the key was found in this tenant and revoked.

### <a id="Tracon_IApiKeyStore_TouchLastUsedAsync_System_Guid_System_DateTimeOffset_System_Threading_CancellationToken_"></a> TouchLastUsedAsync\(Guid, DateTimeOffset, CancellationToken\)

Updates the last-used timestamp.

```csharp
ValueTask TouchLastUsedAsync(Guid id, DateTimeOffset usedAt, CancellationToken cancellationToken = default)
```

#### Parameters

`id` [Guid](https://learn.microsoft.com/dotnet/api/system.guid)

The key identifier.

`usedAt` [DateTimeOffset](https://learn.microsoft.com/dotnet/api/system.datetimeoffset)

The usage time.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The cancellation token.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask)

The completion task.

#### Remarks

There is no tenant filter: the caller (`ApiKeyAuthenticator`)
has already found the key through its digest and RESOLVED the tenant;
a second check here is unnecessary — the same reason as
[IApiKeyStore.FindByHashAsync](/api/tracon.iapikeystore/#Tracon_IApiKeyStore_FindByHashAsync_System_ReadOnlyMemory_System_Byte__System_Threading_CancellationToken_).
