Dhruv.Contact
Back home

Stipulate

Stipulate icon
2025–26TypeScriptMicro StartupFeatured

Abstract

Parse the stipulations. Route the payment. Stipulate turns opaque credit-card fine print into a machine-readable benefit graph across 200+ US card programs, enriches transactions with merchant category codes, and exposes POST /v1/route to pick the card that maximizes net return — at 25K+ requests/min and <45ms P95 across a TypeScript monorepo (Hono, Next.js 15, Expo, Prisma, Redis, Stripe).

Highlights

  • Semantic benefit graph across 200+ US card programs with issuer normalization and MCC enrichment
  • 150+ API endpoints supporting 25K+ requests/min at <45ms P95 with Redis caching and multi-tenant billing
  • Full-stack monorepo — Hono API, Next.js 15 web, Expo mobile wallet, Stripe, AWS ingestion workers
TypeScriptHonoNext.jsExpoPrismaRedisFintech

Stipulate Platform Specification

Document ID: STIPULATE-README-1.0
Normative status: Informative (repository root)
Maintainer: ddvhegde100
License: MIT


1. Scope and definitions

1.1 Scope

This document specifies the Stipulate monorepo: a card-benefit intelligence platform that ingests issuer stipulations, structures benefit rules, enriches merchant transactions, and routes spend to maximize net cardholder return. The specification covers repository topology, runtime surfaces, API contracts at the repository boundary, operational interfaces, and deployment obligations.

1.2 Normative terminology

The keywords MUST, MUST NOT, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in RFC 2119.

1.3 Definitions

TermDefinition
Benefit ruleA structured, versioned representation of an issuer benefit (earn rate, cap, exclusion, activation window).
CatalogThe canonical JSON card registry (packages/schema/data/cards/) validated by Zod schemas.
ConsumerAn end-user wallet holder authenticated via session cookies on /public/auth.
EnrichmentAssignment of network-specific merchant category and override metadata to a transaction (POST /v1/enrich).
IssuerA card network program operator (Chase, Amex, etc.) represented in the catalog.
MCCMerchant Category Code per ISO 18245, possibly overridden per issuer.
Organization (Org)A B2B API customer scoped by org-scoped API keys.
RoutingSelection of the optimal card from a wallet for a given transaction (POST /v1/route).
StipulationFine-print benefit language extracted from issuer documents.
WalletThe set of cards associated with a consumer or routing request.

1.4 Product identity

  • Name: Stipulate
  • Tagline: Parse the stipulations. Route the payment.
  • Primary domain: stipulate.io
  • API origin: https://api.stipulate.io
  • Package scope: @stipulate/*

2. System architecture

2.1 Logical decomposition

┌─────────────────────────────────────────────────────────────────┐
│                        Client surfaces                          │
│  @stipulate/web (Next.js 15)  @stipulate/mobile (Expo SDK 52)   │
└────────────────────────────┬────────────────────────────────────┘
                             │ HTTPS / JSON
┌────────────────────────────▼────────────────────────────────────┐
│                    @stipulate/api (Hono on Node 20)             │
│  /v1/* (org API)  /public/* (consumer)  /admin/*  /webhooks/*   │
└─────┬──────────┬──────────┬──────────┬──────────┬───────────────┘
      │          │          │          │          │
      ▼          ▼          ▼          ▼          ▼
 PostgreSQL   Redis      S3/SQS     Stripe     Plaid
 (state)     (cache/RL)  (async)   (billing)  (link)
      │
      ▼
┌─────────────────────────────────────────────────────────────────┐
│ Shared packages: schema · parser · routing · mcc · brand · ui │
└─────────────────────────────────────────────────────────────────┘

2.2 Monorepo topology

stipulate/
├── apps/
│   ├── api/        # Hono routing API — POST /v1/route, /v1/enrich, issuing, plaid
│   ├── web/        # Next.js 15 marketing, developer console, consumer dashboard
│   ├── mobile/     # Expo SDK 52 iOS/Android consumer wallet
│   └── docs/       # Static OpenAPI and SDK reference host
├── packages/
│   ├── brand/      # Design tokens, logos, Tailwind preset
│   ├── schema/     # Shared Zod schemas and card catalog
│   ├── parser/     # LLM benefit parsing pipeline
│   ├── routing/    # Wallet routing engine and scoring
│   ├── mcc/        # Merchant category enrichment
│   ├── ui/         # React component library
│   └── sdk/        # TypeScript client SDK
├── docker/         # Postgres init, LocalStack bootstrap
├── docs/           # Environment, launch runbook, production checklist
└── .github/        # CI, scheduled jobs, deploy workflows

2.3 Build orchestration

The monorepo uses Turborepo (turbo.json) with pnpm workspaces (pnpm-workspace.yaml). Package graph dependencies MUST respect: schemarouting, mcc, parserapi; brand, ui, schemaweb, mobile.


3. Runtime surfaces

3.1 API server (@stipulate/api)

PropertyValue
RuntimeNode.js ≥ 20
FrameworkHono 4.x on @hono/node-server
Default port3000
API version prefix/v1 (configurable via API_VERSION)

3.1.1 Health and observability endpoints

EndpointPurposeSuccess criterion
GET /healthLightweight livenessHTTP 200, status: ok
GET /health/liveProcess liveness probeHTTP 200
GET /health/readyReadiness (Postgres + Redis)HTTP 200 when dependencies healthy
GET /statusPublic status page dataHTTP 200, SLO and queue metrics
GET /v1/openapiOpenAPI 3.1 specificationHTTP 200

3.1.2 Authentication models

  1. Org API keysX-API-Key header on /v1/*; keys are org-scoped, rate-limited per plan.
  2. Consumer sessions — HTTP-only cookies on /public/auth/* and wallet routes.
  3. AdminX-Admin-Key on /admin/* via ADMIN_API_KEY.
  4. Webhooks — Stripe signature (STRIPE_WEBHOOK_SECRET), issuing shipping (ISSUING_WEBHOOK_SECRET).

3.1.3 Core API operations

# Routing — select optimal card for a transaction
curl -X POST http://localhost:3000/v1/route \
  -H "Content-Type: application/json" \
  -H "X-API-Key: stip_dev_local_key_change_in_production" \
  -d '{
    "merchant_category_code": "5812",
    "amount_cents": 5000,
    "card_ids": ["chase_sapphire_preferred", "amex_gold"]
  }'

# Enrichment — resolve MCC and issuer overrides before routing
curl -X POST http://localhost:3000/v1/enrich \
  -H "Content-Type: application/json" \
  -H "X-API-Key: stip_dev_local_key_change_in_production" \
  -d '{
    "merchant_name": "Starbucks",
    "mcc": "5814",
    "amount_cents": 650
  }'

3.2 Web application (@stipulate/web)

PropertyValue
FrameworkNext.js 15 (App Router)
Default port3001
DeploymentVercel production → https://stipulate.io

Surfaces: marketing, pricing, developer playground, org dashboard, consumer wallet UI, proxy-pay staging.

3.3 Mobile application (@stipulate/mobile)

PropertyValue
FrameworkExpo SDK 52, Expo Router
Bundle IDsio.stipulate.app (iOS/Android)
DistributionEAS Build → App Store / Play Store

3.4 Background workers

Workers run as separate processes (see apps/api/scripts/):

WorkerScheduleCommand
Webhook supervisorContinuousworker:supervisor
Benefit reparseWeeklyschedule:reparse
Stripe reconcileWeeklyreconcile:stripe
GDPR purgeDailypurge:deletions
Ingestion drainEvery 30 minschedule:ingestion
Benefit digestWeeklyschedule:digest

4. Data and persistence

4.1 PostgreSQL

  • Version: 16+ (production)
  • Migrations: apps/api/migrations/*.sql — applied via pnpm db:migrate
  • Seeding: db:seed, db:seed-benefits --top75|--top150

4.2 Redis

  • Version: 7+
  • Uses: Routing benefit index cache, rate-limit sliding windows, cap spend state
  • Key prefix: REDIS_PREFIX (default stipulate:)

4.3 Object storage and queues

  • S3: Benefit PDFs, parser artifacts
  • SQS: Async parser job queue (optional for v1)
  • Local dev: LocalStack via docker compose

5. Security model

5.1 Production obligations

Production deployments MUST:

  1. Set NODE_ENV=production and LOG_LEVEL=info or warn.
  2. Use TLS for DATABASE_URL (sslmode=require) and REDIS_URL (rediss://).
  3. Restrict CORS_ORIGINS to explicit production hostnames (wildcard * is rejected at startup).
  4. Rotate org API keys; the static API_KEY env var is for development only.
  5. Configure SENTRY_DSN for error tracking.
  6. Enable Stripe webhook signature verification before accepting billing events.

5.2 Rate limiting

Org routes apply a Redis-backed sliding-window limiter. In production, Redis outage MUST fail closed (HTTP 503) per apps/api/src/middleware/rate-limit.ts.

5.3 GDPR

Consumers MAY export data (GET /public/auth/export) and schedule deletion (POST /public/auth/delete) with a 30-day grace period. Purge runs daily via purge:deletions.


6. Service level objectives

MetricTargetMeasurement
Route P99 latency (warm cache)< 20 msGET /statuschecks.slo.routeP99Ms
API error rate (5xx)< 0.1%Sentry / PostHog api.request
Health probe availability≥ 99.9%External monitor on /health/ready
Webhook delivery success> 99%Worker supervisor metrics

7. Local development

7.1 Prerequisites

DependencyMinimum version
Node.js20.0.0
pnpm9.0.0
Docker24+ (for Postgres, Redis, LocalStack)

7.2 Bootstrap sequence

cp .env.example .env
pnpm install
pnpm docker:up          # Postgres + Redis + LocalStack
pnpm db:migrate
pnpm dev                # Turborepo — all apps

# Individual surfaces
pnpm dev:api            # http://localhost:3000
pnpm dev:web            # http://localhost:3001
pnpm dev:mobile         # Expo dev server
pnpm dev:docs           # Static docs host

7.3 Verification

pnpm typecheck
pnpm test
pnpm lint
pnpm catalog:validate
pnpm --filter @stipulate/api smoke

8. Build, test, and release

8.1 Root scripts

CommandDescription
pnpm buildBuild all packages and apps
pnpm testRun all test suites (Vitest, Jest)
pnpm typecheckTypeScript validation across workspace
pnpm lintESLint
pnpm format:checkPrettier validation
pnpm docker:upStart local infrastructure
pnpm docker:prodProduction compose profile
pnpm catalog:validateValidate card catalog JSON

8.2 CI pipeline

GitHub Actions workflow ci.yml gates merge on: catalog validation, lint, typecheck, unit tests, API smoke, Playwright e2e, production build, and Docker compose smoke (main only).

8.3 Production deployment

See docs/PRODUCTION.md, docs/launch.md, and docs/stripe-live-checklist.md.

Deploy triggers:

SurfaceTriggerTarget
APITag v*.*.*Fly.io (deploy-production.yml)
WebVercel main branchstipulate.io
MobileTag v*.*.*EAS → stores (mobile-release.yml)

9. Versioning and compatibility

  • Repository version: 0.1.0 (see package.json)
  • API version: /v1 — breaking changes require a new major API prefix
  • Catalog: Semver-independent; validated on every CI run
  • SDK: @stipulate/sdk tracks /v1 OpenAPI surface

10. Contributing and git policy

All commits MUST be authored by the repository maintainer (ddvhegde100@users.noreply.github.com). Use:

pnpm commit -- <conventional-commit-args>

Co-authored-by trailers from automated tooling are stripped by Husky hooks. See CONTRIBUTING.md and SECURITY.md.


11. References

DocumentPath
Environment matrixdocs/environment.md
Production checklistdocs/PRODUCTION.md
Launch runbookdocs/launch.md
Monitoringdocs/monitoring.md
Proxy paydocs/PROXY_PAY.md
Branch protectiondocs/branch-protection.md
OpenAPI specapps/api/docs/openapi.yaml
Architecture specificationdocs/ARCHITECTURE.md

12. License

MIT © ddvhegde100


Author: Dhruv Hegde · CS @ University of Michigan

Connect with Dhruv Hegde

More of Dhruv Hegde's open-source work on GitHub and LinkedIn.

More projects

← Project gallery