A self-hosted API-platform starter for teams that need secure API keys, scoped access, quotas, idempotent writes, request tracing, and a typed client without assembling those primitives from scratch.
ForgeAPI is built for platform engineers, backend developers, and small teams building internal, partner, multi-tenant, or AI/tool APIs. It is also a concrete reference project for understanding how these concerns fit together.
Current status (September 2026): Early-stage reference implementation. The Todo API is the example resource; ForgeAPI is not a hosted SaaS product.
Framed captures of the live control-plane dashboard (current UI).
Most teams eventually need the same API foundation:
- Give each service, tenant, or partner its own credentials.
- Limit usage without scattering quota logic across application code.
- Make retries safe when networks fail or clients time out.
- Show developers how to authenticate, handle errors, and use a typed client.
- Keep enough request context to investigate failures.
ForgeAPI packages those concerns into one runnable control plane, data plane, database, quota store, and SDK so a team can start from a working boundary instead of a blank repository.
ForgeAPI is a good starting point for:
- Internal APIs shared by multiple services or teams
- Partner and integration APIs with scoped credentials and rotation
- Multi-tenant SaaS APIs with per-project quotas
- AI and tool backends that need typed clients, retries, and idempotent writes
It is not the right choice yet if you need a hosted API gateway, billing-grade metering, a complete OpenAPI portal, multi-region operations, or a turnkey production deployment.
See use cases, production-readiness guidance, and the roadmap before adopting it for an external customer-facing API.
| If you want to... | Start here |
|---|---|
| Run a working API platform locally | Follow the 5-minute quick start |
| See the SDK and retry/idempotency behavior | Run pnpm demo |
| Understand the system boundary | Read the architecture |
| Decide whether it fits your product | Read the use cases |
| Plan a real deployment | Read production readiness |
| Contribute or extend the example | Read CONTRIBUTING.md |
| Capability | User value |
|---|---|
| Project-scoped API keys | Give services and partners isolated credentials |
| Scopes and key rotation | Reduce blast radius and support safe credential changes |
| Redis-backed quotas | Apply plan limits consistently per project |
| Transactional idempotency | Make retryable writes safe during network failures |
| Request IDs and logs | Trace a request across client, API, and persistence |
| Typed zero-dependency SDK | Give TypeScript consumers a fast, predictable integration path |
| Dashboard control plane | Manage projects, keys, usage, and request activity |
- API key creation, revocation, expiration, and rotation
- Separate test and live API key environments
- SHA-256 API key hashing with a configurable server-side pepper
- Scoped Bearer-token authentication
- Project ownership and access control
- Redis-backed quota enforcement
- Daily and monthly quota windows
- Configurable quota fail-open and fail-closed behavior
- Cursor-based Todo API pagination
- Transaction-safe idempotency for write requests
- Consistent structured API errors with request IDs
- Request logging and rate-limit response headers
- Next.js dashboard for projects, keys, usage, and request activity
- Typed, zero-dependency TypeScript SDK
- PostgreSQL persistence through Prisma
- Docker Compose development infrastructure
- Turborepo-based monorepo workflows
- Automated formatting, typechecking, builds, tests, and dependency auditing
flowchart LR
Consumer["Consumer application"] --> SDK["@mangeshraut/forge-sdk"]
SDK --> API["Fastify REST API"]
Dashboard["Next.js control plane"] --> PostgreSQL["PostgreSQL"]
API --> PostgreSQL
API --> Redis["Redis quota counters"]
Dashboard --> Projects["Projects and API keys"]
API --> Auth["Authentication and scopes"]
API --> Quotas["Quota enforcement"]
API --> Idempotency["Transactional idempotency"]
ForgeAPI is split into two logical planes:
- Control plane: The Next.js dashboard used to manage users, projects, API keys, usage, and request logs.
- Data plane: The Fastify REST API consumed by applications using generated API keys.
apps/
├── api/ Fastify REST API
├── dashboard/ Next.js control-plane dashboard
└── todo-demo/ CLI application exercising the SDK
packages/
├── auth/ Ownership and soft-delete helpers
├── config/ Shared TypeScript configuration
├── db/ Prisma client and PostgreSQL schema
├── sdk/ Typed ForgeAPI client
└── shared/ Schemas, types, plans, quotas, errors, and scopes
tests/ Cross-package SDK tests
docs/ Architecture and design documentation
docker-compose.yml PostgreSQL and Redis development services
| Area | Technology |
|---|---|
| Runtime | Node.js 22 |
| Package manager | pnpm |
| Monorepo | Turborepo |
| API | Fastify 5 |
| Dashboard | Next.js 15 App Router |
| Authentication | NextAuth |
| Database | PostgreSQL 16 |
| ORM | Prisma 6 |
| Quotas | Redis 7 and ioredis |
| Validation | Zod |
| SDK | TypeScript and Fetch |
| Testing | Vitest |
| CI | GitHub Actions |
- Node.js 22.x
- pnpm 9.x
- Docker and Docker Compose
The repository includes an .nvmrc file for the expected Node.js version.
git clone https://github.com/mangeshraut712/forge-api-platform.git
cd forge-api-platform
nvm install
nvm use
corepack enable
pnpm installcp .env.example .envThe development environment uses:
- PostgreSQL on
localhost:5432 - Redis on
localhost:6379 - API on
localhost:4000 - Dashboard on
localhost:3000
pnpm docker:uppnpm db:generate
pnpm db:push
pnpm db:seedThe seed command creates a development user, a demo project, and a live API key. The raw API key is printed once in the terminal.
Copy that key into .env:
FORGE_API_KEY=forge_live_your_key_herepnpm devOpen the dashboard at:
http://localhost:3000
The development credentials login accepts:
dev@forge.local
No password is required when AUTH_DEV_LOGIN=true.
The API is available at:
http://localhost:4000
Run applications individually when needed:
pnpm --filter @forge/api dev
pnpm --filter @forge/dashboard dev
pnpm demo| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Liveness check |
GET |
/ready |
PostgreSQL and Redis readiness check |
All /v1/* endpoints require a valid Bearer token.
| Method | Endpoint | Scope | Description |
|---|---|---|---|
GET |
/v1/todos |
todos:read |
List todos with cursor pagination |
GET |
/v1/todos/:id |
todos:read |
Retrieve one todo |
POST |
/v1/todos |
todos:write |
Create a todo |
PUT |
/v1/todos/:id |
todos:write |
Replace a todo |
PATCH |
/v1/todos/:id |
todos:write |
Partially update a todo |
DELETE |
/v1/todos/:id |
todos:write |
Delete a todo |
Authorization: Bearer forge_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAPI keys are only displayed in raw form once. The API stores a hash and a visible prefix rather than the original key.
export FORGE_API_KEY="forge_live_your_key_here"
curl -X POST http://localhost:4000/v1/todos \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: todo-example-1" \
-d '{"title":"Ship ForgeAPI"}'curl "http://localhost:4000/v1/todos?limit=20" \
-H "Authorization: Bearer $FORGE_API_KEY"Write requests support the Idempotency-Key header.
Retrying a request with the same key and request body replays the original response. Reusing the same key with a different request body returns a conflict response.
Idempotent write operations:
POST /v1/todosPUT /v1/todos/:idPATCH /v1/todos/:id
API responses include quota information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1742956800{
"error": {
"code": "unauthorized",
"message": "Invalid API key",
"request_id": "request-id"
}
}The SDK is configured as @mangeshraut/forge-sdk.
import { createForgeClient } from "@mangeshraut/forge-sdk";
const client = createForgeClient({
apiKey: process.env.FORGE_API_KEY!,
baseUrl: "http://localhost:4000",
});
const created = await client.createTodo({
title: "Ship ForgeAPI",
});
const todos = await client.listTodos({
limit: 20,
});
await client.updateTodo(created.id, {
completed: true,
});
await client.deleteTodo(created.id);The SDK also provides:
- Runtime API key format validation
- Typed Todo operations
- Typed API errors
- Request ID access
- Configurable request timeouts
- Retry handling for safe requests
- Idempotency-key support for writes
| Plan | Default limit | Window |
|---|---|---|
FREE |
100 requests | Day |
DEVELOPER |
10,000 requests | Month |
CUSTOM |
Configurable | Day or month |
Quota counters are maintained in Redis using atomic increments and expiration windows.
When Redis is unavailable, behavior is controlled by:
QUOTA_FAIL_MODE=openUse open to prioritize availability or closed to prioritize strict quota enforcement. Closed mode responds with HTTP 503 and quota_unavailable, which is distinct from a project that has actually used its quota.
pnpm dev # Start the API, dashboard, and demo
pnpm demo # Run the end-to-end Todo SDK demo
pnpm build # Build all packages and applications
pnpm test # Run the test suite
pnpm typecheck # Type-check the monorepo
pnpm lint # Check formatting
pnpm format # Format supported source files
pnpm db:generate # Generate the Prisma client
pnpm db:push # Apply the schema to the local database
pnpm db:migrate # Create and apply a development migration
pnpm db:migrate:deploy # Apply checked-in migrations to a deployment database
pnpm db:seed # Seed local development data
pnpm docker:up # Start PostgreSQL and Redis
pnpm docker:down # Stop PostgreSQL and Redis
pnpm audit --prod # Audit production dependenciesMake sure the API is running and FORGE_API_KEY is configured.
pnpm --filter @forge/todo-demo devThe demo exercises:
- Todo listing, creation, updates, and deletion
- Idempotency replay
- Invalid and unknown API key handling
- Request timeouts
- Network retries
- Rate-limit headers
Copy .env.example to .env for local development.
Important production values include:
- A long random
AUTH_SECRET - A separate
API_KEY_HASH_PEPPERwith at least 32 characters - Production PostgreSQL and Redis URLs
- Explicit
CORS_ORIGINS(cookie credentials are not allowed) TRUST_PROXYleftfalseunless the API sits behind a known proxy, in which case set the hop countQUOTA_FAIL_MODEselected according to availability requirements (closedreturns HTTP 503quota_unavailablewhen Redis is down)- Google OAuth credentials if Google login is enabled
Never commit .env, API keys, OAuth secrets, or database credentials.
For a deployment database, set DATABASE_URL in the deployment
environment and run pnpm db:migrate:deploy. The repository includes
an initial Prisma migration; use pnpm db:push only for local
schema prototyping.
ForgeAPI applies several security controls:
- API keys are hashed before storage.
- API keys are validated for environment and format.
- API routes require explicit scopes and return
insufficient_scopewhen a key is missing one. - Project resources are ownership-scoped. Todo list cursors must belong to the same project.
- Deleted users are prevented from authenticating, including keys that were still inside a rotation grace window.
- The dashboard rejects unverified Google emails and requires
AUTH_SECRETto be at least 32 characters in production. - IP rate limits do not apply to
/healthor/ready, andTRUST_PROXYdefaults to false so clients cannot spoofX-Forwarded-For. - Request logs store the path without the query string.
- Request IDs are generated and returned with errors.
- Request bodies are size-limited.
- Idempotency records are committed with their write side effects.
- Production key hashing requires a strong pepper.
- Dependency vulnerabilities are checked in CI.
This repository is a reference implementation and should be threat-modeled and configured separately before production deployment.
GitHub Actions runs on pushes and pull requests targeting main.
The workflow performs:
- Frozen dependency installation
- Prisma client generation
- Formatting checks
- Typechecking
- Builds
- Tests
The current implementation uses the Todo resource to demonstrate the platform lifecycle. The architecture is intended to support additional API resources, dashboard views, plans, and integrations over time. See the roadmap and production-readiness guide for the intended adoption path and current boundaries.
See CONTRIBUTING.md for local setup, quality checks, and pull request guidance.
Please do not report security vulnerabilities in public issues. See SECURITY.md for the responsible disclosure process.
MIT. See LICENSE.



