API keys
Create, list, rotate, and revoke machine-scoped API keys with convex-auth.
convex-auth has a native api_keys table and a set of helpers for creating, hashing, verifying, and rotating API keys. The @vortex-api/convex-auth/react package ships useConvexApiKeys, ConvexApiKeyCreated, and the lower-level ConvexApiKeyCreateForm and ConvexApiKeyList components.
How it works
- API keys are scoped to a user and an active organization.
- The full token is returned once on creation or rotation. Only a hash and prefix are stored.
- Keys carry scopes, an optional expiration, and optional IP allowlist ranges.
- The
useConvexApiKeyshook wires a consumer Convex API to the presentational components.
Mount the API keys component
If you need service/API-key authentication, mount the apiKeys component alongside the core component:
import { defineApp } from "convex/server";
import { v } from "convex/values";
import authCore from "@vortex-api/convex-auth/convex.config/core";
import authApiKeys from "@vortex-api/convex-auth/convex.config/apiKeys";
const app = defineApp({
env: {
JWT_PRIVATE_KEY: v.string(),
JWKS: v.string(),
},
});
app.use(authCore, {
env: {
JWT_PRIVATE_KEY: app.env.JWT_PRIVATE_KEY,
JWKS: app.env.JWKS,
},
});
app.use(authApiKeys, {
env: {
JWT_PRIVATE_KEY: app.env.JWT_PRIVATE_KEY,
JWKS: app.env.JWKS,
},
});
export default app;
Consumer functions
Add queries and mutations in your own convex/ directory that call the component and map to public client shapes. The example app uses:
api.apiKeys.listMyApiKeys— list active keys for the active organization.api.apiKeys.createApiKey— issue a new key and return the one-time token.api.apiKeys.revokeApiKey— revoke a key.api.apiKeys.rotateApiKey— issue a replacement and revoke the old key.
React hooks and components
useConvexApiKeys
import { useConvexApiKeys, ConvexApiKeyCreated } from "@vortex-api/convex-auth/react";
import { api } from "../convex/_generated/api";
const SCOPES = ["read", "write", "delete"] as const;
export function ApiKeys() {
const { formProps, listProps, created, clearCreated } = useConvexApiKeys(api, {
scopeOptions: SCOPES,
});
return (
<>
<ConvexApiKeyCreateForm {...formProps} />
{created && <ConvexApiKeyCreated apiKey={created.apiKey} onClose={clearCreated} />}
<ConvexApiKeyList {...listProps} />
</>
);
}
The hook returns:
formProps— ready forConvexApiKeyCreateForm.listProps— ready forConvexApiKeyList.created— the one-time{ apiKey, apiKeyId, keyPrefix, keyStart }after a successful create or rotate.clearCreated— a callback to dismiss the created token display.
ConvexApiKeyCreated
Render this once, immediately after create or rotate, so the user can copy the plaintext token. The full token is not recoverable after this step.
import { ConvexApiKeyCreated } from "@vortex-api/convex-auth/react";
<ConvexApiKeyCreated apiKey={created.apiKey} onClose={() => setCreated(null)} />;
Server-side helpers
@vortex-api/convex-auth/convex re-exports the machine helpers you need to build apiKeys mutations and actions:
normalizeConvexApiKeyCreateInput— turn a user payload into a validated create shape.createConvexApiKeyCreateArgsValidator— build the validator for your mutation.deriveApiKeySecret/hashApiKeySecret/verifyApiKeySecret— generate and verify the secret token.requireActiveApiKeyRecord— resolve an API key from a secret in a request.resolveApiKeyRecordStatus— check active, expired, revoked, or disabled status.
These run inside Convex actions because they need crypto.subtle and other non-deterministic work. The component’s api_keys table stores only the hash, prefix, scopes, and metadata.