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

# ApiKey

> Reference for the ApiKey type for programmatic backend access.

export const MethodReturns = ({type, children}) => <ContentSection title="Returns">
    <code className="inline-flex rounded-md border border-zinc-950/10 bg-zinc-950/[0.04] px-2 py-0.5 text-[13px] font-medium text-zinc-950 dark:border-white/10 dark:bg-white/[0.08] dark:text-white">
      {type}
    </code>
    {children ? <div className="text-sm leading-6 text-zinc-700 dark:text-zinc-300">{children}</div> : null}
  </ContentSection>;

export const MethodLayout = ({children}) => <div className="grid gap-4 md:grid-cols-2 md:items-start xl:gap-6">
    {children}
  </div>;

export const MethodContent = ({children}) => <div className="min-w-0 space-y-4">{children}</div>;

export const MethodAside = ({title, children}) => <div className="min-w-0 self-start space-y-4 rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.02] p-4 dark:border-white/10 dark:bg-white/[0.03]">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-4">{children}</div>
  </div>;

export const ContentSection = ({title, children}) => <div className="space-y-3">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-3">{children}</div>
  </div>;

export const CollapsibleTypesSection = ({type, property, signature, defaultOpen = false, deprecated = false, badge, children}) => {
  const id = `${String(type ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}${String(property ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}`;
  const [isOpen, setIsOpen] = useState(defaultOpen);
  useEffect(() => {
    if (typeof window === "undefined") {
      return undefined;
    }
    const syncWithHash = () => {
      if (window.location.hash === `#${id}`) {
        setIsOpen(true);
      }
    };
    syncWithHash();
    window.addEventListener("hashchange", syncWithHash);
    return () => window.removeEventListener("hashchange", syncWithHash);
  }, [id]);
  const label = signature ? `${property}(${signature})` : property;
  const fullLabel = type ? `${type}.${label}` : label;
  return <details id={id} open={isOpen} onToggle={event => setIsOpen(event.currentTarget.open)} className={`not-prose my-4 scroll-mt-24 overflow-hidden rounded-2xl border bg-white dark:bg-zinc-950 ${deprecated ? "border-orange-400/40 dark:border-orange-500/30" : "border-zinc-950/10 dark:border-white/10"}`}>
      <summary className="cursor-pointer list-none px-4 py-4 [&::-webkit-details-marker]:hidden">
        <div className="flex items-center gap-3">
          <code className={`text-[15px] font-medium ${deprecated ? "text-zinc-500 line-through decoration-zinc-400/60 dark:text-zinc-400 dark:decoration-zinc-500/60" : "text-zinc-950 dark:text-white"}`}>{fullLabel}</code>
          <span className="ml-auto flex items-center gap-2">
            {deprecated ? <Badge color="orange" size="sm" shape="pill">deprecated</Badge> : null}
            {badge ?? null}
            <span aria-hidden="true" className="text-sm text-zinc-500 transition-transform dark:text-zinc-400">
              {isOpen ? "▾" : "›"}
            </span>
          </span>
        </div>
      </summary>

      <div className="border-t border-zinc-950/10 px-4 py-5 dark:border-white/10">
        {children}
      </div>
    </details>;
};

export const ClickableTableOfContents = ({title, code}) => {
  const lines = String(code ?? "").replace(/\r\n/g, "\n").split("\n");
  return <div className="not-prose my-6 overflow-hidden rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.03] dark:border-white/10 dark:bg-white/[0.03]">
      {title ? <div className="border-b border-zinc-950/10 px-4 py-3 text-sm font-medium text-zinc-950/80 dark:border-white/10 dark:text-white/80">
          {title}
        </div> : null}

      <pre className="overflow-x-auto px-2 py-3 text-[13px] leading-6 text-zinc-900 dark:text-zinc-100">
        <code>
          {lines.map((line, index) => {
    if (line.trim().startsWith("// NEXT_LINE_PLATFORM")) {
      return null;
    }
    const match = line.match(/^(.*?)(?:\s*\/\/\s*\$stack-link-to:(#[a-zA-Z0-9_-]+))\s*$/);
    const href = match?.[2] ?? null;
    const text = match?.[1] ?? line;
    if (text.trim() === "") {
      return <span key={`blank-${index}`} className="block h-6" />;
    }
    const content = <span className="block whitespace-pre rounded-lg px-3 py-0.5">
                {text.replace(/\s+$/, "")}
              </span>;
    if (!href) {
      return <span key={`line-${index}`} className="block text-zinc-700 dark:text-zinc-300">
                  {content}
                </span>;
    }
    return <a key={`line-${index}`} href={href} className="block no-underline transition-colors hover:bg-zinc-950/[0.04] hover:text-zinc-950 dark:hover:bg-white/[0.05] dark:hover:text-white">
                {content}
              </a>;
  })}
        </code>
      </pre>
    </div>;
};

export const AsideSection = ({title, children}) => <div className="space-y-3">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-3">{children}</div>
  </div>;

export const ApiKeySection = props => <CollapsibleTypesSection badge={<Badge color="green" size="sm" shape="pill">
        apiKey
      </Badge>} {...props} />;

`ApiKey` represents an authentication token that allows programmatic access to your application's backend. API keys can be associated with individual users or teams.

On this page:

* [`ApiKey`](#apikey)
* Types:
  * [`UserApiKey`](#userapikey)
  * [`TeamApiKey`](#teamapikey)

***

# `ApiKey`

API keys provide a way for users to authenticate with your backend services without using their primary credentials. They can be created for individual users or for teams, allowing programmatic access to your application.

API keys can be obtained through:

* [`user.createApiKey()`](/sdk/types/user#currentusercreateapikeyoptions)
* [`user.listApiKeys()`](/sdk/types/user#currentuserlistapikeys)
* [`user.useApiKeys()`](/sdk/types/user#currentuseruseapikeys) (React hook)
* [`team.createApiKey()`](/sdk/types/team#teamcreateapikeyoptions)
* [`team.listApiKeys()`](/sdk/types/team#teamlistapikeys)
* [`team.useApiKeys()`](/sdk/types/team#teamuseapikeys) (React hook)

## Table of Contents

<ClickableTableOfContents
  title="ApiKey Table of Contents"
  code={`type ApiKey = {
id: string; //$stack-link-to:#apikeyid
description: string; //$stack-link-to:#apikeydescription
expiresAt?: Date; //$stack-link-to:#apikeyexpiresat
manuallyRevokedAt?: Date | null; //$stack-link-to:#apikeymanuallyrevokedat
createdAt: Date; //$stack-link-to:#apikeycreatedat
value: string | { lastFour: string }; //$stack-link-to:#apikeyvalue
type: "user" | "team"; //$stack-link-to:#apikeytype
userId?: string; //$stack-link-to:#apikeyuserid
teamId?: string; //$stack-link-to:#apikeyteamid

isValid(): boolean; //$stack-link-to:#apikeyisvalid
whyInvalid(): string | null; //$stack-link-to:#apikeywhyinvalid
revoke(): Promise<void>; //$stack-link-to:#apikeyrevoke
update(options): Promise<void>; //$stack-link-to:#apikeyupdate
};`}
/>

## Properties

<ApiKeySection type="apiKey" property="id" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The unique identifier for this API key.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const id: string; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="description" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      A human-readable description of the API key's purpose.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const description: string; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="expiresAt" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The date and time when this API key will expire. If not set, the key does not expire.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const expiresAt: Date | undefined; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="manuallyRevokedAt" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The date and time when this API key was manually revoked. If `null`, the key has not been revoked. May be `undefined` if the information is not available.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const manuallyRevokedAt: Date | null | undefined; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="createdAt" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The date and time when this API key was created.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const createdAt: Date; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="value" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      The full API key string on first creation; subsequently returns `{ lastFour: string }` for security.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const value: string | { lastFour: string }; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="type" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Whether this is a `"user"` or `"team"` API key.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const type: "user" | "team"; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="userId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      For user API keys, the ID of the user that owns this API key.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const userId: string | undefined; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="teamId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      For team API keys, the ID of the team that owns this API key.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const teamId: string | undefined; `
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

## Methods

<ApiKeySection type="apiKey" property="isValid" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Checks if the API key is still valid, meaning it is neither expired nor revoked.

      <MethodReturns type="boolean" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function isValid(): boolean;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```typescript theme={null}
        if (apiKey.isValid()) {
          console.log("API key is still valid");
        } else {
          console.log("API key is invalid");
        }
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="whyInvalid" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Returns the reason why the API key is invalid, or `null` if it is valid.

      <MethodReturns type="&#x22;manually-revoked&#x22; | &#x22;expired&#x22; | null" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function whyInvalid(): "manually-revoked" | "expired" | null;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```typescript theme={null}
        const reason = apiKey.whyInvalid();
        if (reason) {
          console.log(`API key is invalid because it was ${reason}`);
        } else {
          console.log("API key is valid");
        }
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="revoke" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Revokes the API key, preventing it from being used for authentication.

      <MethodReturns type="Promise<void>" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function revoke(): Promise<void>;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```typescript theme={null}
        await apiKey.revoke();
        console.log("API key has been revoked");
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

<ApiKeySection type="apiKey" property="update" signature="options" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Updates the API key properties.

      <ContentSection title="Parameters">
        <ParamField body="options.description" type="string">
          A new description for the API key.
        </ParamField>

        <ParamField body="options.expiresAt" type="Date | null">
          A new expiration date, or `null` to remove the expiration.
        </ParamField>

        <ParamField body="options.revoked" type="boolean">
          Set to `true` to revoke the API key.
        </ParamField>
      </ContentSection>

      <MethodReturns type="Promise<void>" />
    </MethodContent>

    <MethodAside>
      <AsideSection title="Signature">
        ```typescript theme={null}
        declare function update(options: {
          description?: string;
          expiresAt?: Date | null;
          revoked?: boolean;
        }): Promise<void>;
        ```
      </AsideSection>

      <AsideSection title="Examples">
        ```typescript theme={null}
        await apiKey.update({
          description: "Updated description",
          expiresAt: new Date(Date.now() + 60 * 24 * 60 * 60 * 1000),
        });
        ```
      </AsideSection>
    </MethodAside>
  </MethodLayout>
</ApiKeySection>

***

# Types

### `UserApiKey`

A type alias for an API key owned by a user.

```typescript theme={null}
type UserApiKey = ApiKey<"user", false>;
```

### `UserApiKeyFirstView`

A type alias for a newly created user API key, which includes the full key value instead of just the last four characters.

```typescript theme={null}
type UserApiKeyFirstView = ApiKey<"user", true>;
```

### `TeamApiKey`

A type alias for an API key owned by a team.

```typescript theme={null}
type TeamApiKey = ApiKey<"team", false>;
```

### `TeamApiKeyFirstView`

A type alias for a newly created team API key, which includes the full key value instead of just the last four characters.

```typescript theme={null}
type TeamApiKeyFirstView = ApiKey<"team", true>;
```

***

# Creation Options

When creating an API key using [`user.createApiKey()`](/sdk/types/user#currentusercreateapikeyoptions) or [`team.createApiKey()`](/sdk/types/team#teamcreateapikeyoptions), you need to provide an options object.

<ParamField body="description" type="string" required>
  A human-readable description of the API key's purpose.
</ParamField>

<ParamField body="expiresAt" type="Date | null" required>
  The date when the API key will expire. Use `null` for keys that don't expire.
</ParamField>

<ParamField body="isPublic" type="boolean">
  Whether the API key is public. Defaults to `false`. **Secret API Keys** are
  monitored by Hexclave's secret scanner, which can revoke them if detected in
  public code repositories. **Public API Keys** are designed for client-side
  code where exposure is not a concern.
</ParamField>

```typescript theme={null}
const user = await hexclaveApp.getUser();

const secretKey = await user.createApiKey({
  description: "Backend integration",
  expiresAt: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),
  isPublic: false,
});

const publicKey = await user.createApiKey({
  description: "Client-side access",
  expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
  isPublic: true,
});
```
