Keysmith
1.x
Docs/Keysmith/Getting Started
Open

Reading4 min
Updated31 Jul 2026
Sourcev1/getting-started.mdx

This guide walks you through installing Keysmith, creating an API key, validating it, and setting up policies. By the end you will have a working program that exercises the core key management lifecycle.

Prerequisites01

  • Go 1.24+ (the module uses go 1.25.7 but any recent version works)

  • A Go module (go mod init)

Install02

go get github.com/xraph/keysmith

This pulls in the root module and all sub-packages (key, policy, scope, usage, rotation, plugin, store/memory, etc.).

Step 1 -- Create a store03

Every Keysmith operation needs a store backend. Start with the in-memory store for development and testing.

import "github.com/xraph/keysmith/store/memory"

store := memory.New()

The memory.Store implements the full store.Store composite interface -- keys, policies, scopes, usage, and rotation -- all in-process with no external dependencies.

Step 2 -- Create the engine04

The keysmith.Engine is the central coordinator. It connects a store, a hasher, a key generator, and an optional rate limiter.

import "github.com/xraph/keysmith"

eng, err := keysmith.NewEngine(keysmith.WithStore(store))
if err != nil {
    log.Fatal(err)
}

Step 3 -- Set the tenant context05

Keysmith uses context.Context to carry tenant scope across all operations. Use the WithTenant helper to inject app ID and tenant ID.

ctx := keysmith.WithTenant(context.Background(), "my-app", "tenant-1")

Or if using the Forge framework, scope is extracted automatically from forge.Scope.

Step 4 -- Create an API key06

import "github.com/xraph/keysmith/key"

result, err := eng.CreateKey(ctx, &keysmith.CreateKeyInput{
    Name:        "Production Key",
    Prefix:      "sk",
    Environment: key.EnvLive,
    Scopes:      []string{"read:users", "write:users"},
})
if err != nil {
    log.Fatal(err)
}

fmt.Println("API Key:", result.RawKey)
// Output: API Key: sk_live_a3f8b2c9e1d4...
// Save this key — it will never be shown again.

The raw key is returned exactly once. Only the SHA-256 hash is stored in the database.

Step 5 -- Validate a key07

When a request comes in with an API key, validate it against the store.

vr, err := eng.ValidateKey(ctx, result.RawKey)
if err != nil {
    log.Fatal("invalid key:", err)
}

fmt.Println("Key ID:", vr.Key.ID)
fmt.Println("Tenant:", vr.Key.TenantID)
fmt.Println("State:", vr.Key.State)
fmt.Println("Scopes:", vr.Scopes)
// Output:
// Key ID: akey_01h2xce...
// Tenant: tenant-1
// State: active
// Scopes: [read:users write:users]

Step 6 -- Rotate a key08

Rotate a key with a grace period. Both old and new keys will validate during the grace window.

import "github.com/xraph/keysmith/rotation"

newResult, err := eng.RotateKey(ctx,
    vr.Key.ID,
    rotation.ReasonScheduled,
    24*time.Hour, // grace period
)
if err != nil {
    log.Fatal(err)
}

fmt.Println("New Key:", newResult.RawKey)
// The old key remains valid for 24 hours.

Step 7 -- Switch to PostgreSQL09

When you are ready for production, swap the memory store for PostgreSQL. The API does not change.

import "github.com/xraph/keysmith/store/postgres"

pgStore, err := postgres.NewFromDSN(ctx, "postgres://user:pass@localhost:5432/mydb")
if err != nil {
    log.Fatal(err)
}
defer pgStore.Close()

// Run embedded migrations to create all Keysmith tables.
if err := pgStore.Migrate(ctx); err != nil {
    log.Fatal(err)
}

// Use pgStore everywhere you previously used memory.New().
eng, _ := keysmith.NewEngine(keysmith.WithStore(pgStore))

Next steps10

  • Architecture -- Understand the package dependency graph and request flow.

  • Entities -- Learn about the core data types (Key, Policy, Scope, Usage, Rotation).

  • Multi-tenancy -- How context-based tenant isolation works across all subsystems.

  • Plugins -- Extend Keysmith with audit trails, metrics, and Warden authorization sync.

  • REST API -- Mount the full API key management REST API via Forge.