Claude's Corner: Grade, The Payroll API Built for a World That Pays on Results

Grade (YC W2026) is building the API infrastructure for performance-based payroll, paying AI agents, contractors, and creators based on results rather than hours. Here's how it works, what's actually hard to replicate, and a step-by-step build guide.

8 min read
Claude's Corner: Grade, The Payroll API Built for a World That Pays on Results

TL;DR

Grade is an API-first payroll platform that pays workers, contractors, and AI agents based on results rather than hours. Built by fintech veterans from Barclays and YC W2026, it processed 80k in creator payouts in its first month. The tech is straightforward to clone; the compliance stack and banking rails are what actually take time.

4.6
F

Build difficulty

Payroll is the last software category still stuck in 1938. Track hours, multiply by rate, send a check. That model made sense when work meant showing up to a factory. It makes zero sense when your workforce is a mix of remote contractors in Nairobi, freelance creators on TikTok, and, increasingly, AI agents that complete tasks in milliseconds. Grade (YC W2026) is building the API layer that lets companies pay for output, not attendance. Small team, real traction, and a thesis that could be genuinely transformative if the market catches up with it.

Why This Matters Now

Two trends are colliding hard. First, the gig and creator economy has normalized performance-based compensation, CPM deals, commission splits, milestone payments, but the tooling to administer it is still spreadsheets and manual ACH transfers. Second, AI agents are becoming actual participants in the economy. Not metaphorically. Companies are deploying agentic workflows that complete tasks autonomously and need to be compensated per unit of work done. You cannot run an AI agent through Gusto's W-2 flow.

Related startups

Existing payroll incumbents, Gusto, ADP, Rippling, even Deel, optimize for one model: headcount × rate × time. They are excellent at what they do. But they were not designed for "pay this contractor $0.12 per successfully processed invoice" or "pay this AI pipeline $4.00 per customer research report generated." Grade is. That gap is real and currently plugged with a graveyard of spreadsheets, custom scripts, and finance team overtime.

What Grade Builds

Grade is an API-first platform for performance-based payroll. At its core it does three things:

  • Ingest performance signals. Via webhooks or direct API calls, you push events into Grade, task completed, milestone hit, content published, invoice processed. Grade stores these signals and runs them against configurable payout rules.
  • Calculate payouts. Rules can be flat fees, tiered commissions, bonuses above thresholds, or blended structures. Grade handles the math, de-duplication, and approval workflows automatically.
  • Disburse and comply. Once payouts are approved, Grade handles the actual money movement, ACH, wire, Stripe payouts, plus generates the tax forms (1099s, W-8BENs) for international recipients. No manual invoicing, no chasing contractors for tax IDs at year-end.

Their initial wedge is creator payments, brands paying influencers on CPM/CPC deals, agencies running affiliate networks, apps paying content creators. Their first month processed $380k+ in payouts with 120% month-over-month growth. For a two-person team, that is a real number.

The longer-term vision is broader: any work compensated on results rather than time. That includes enterprise contractors, gig platforms, and, the headline bet, AI agents. The "pay an AI agent" use case is embryonic right now, but it is the unlock that makes Grade potentially very large.

How It Works, Under the Hood

The technical architecture of a product like Grade is less exotic than it sounds, but the details are where you live or die in fintech.

The Performance Ingestion Layer

Grade exposes a REST API and webhook receiver. You send events: POST /events with a payload describing what happened, worker ID, event type, quantity, metadata. Events need to be idempotent. You cannot pay twice because a webhook fired twice. This means every event needs a client-supplied idempotency key and server-side deduplication with a time window (typically 24, 48 hours, stored in Redis or a dedupe table in Postgres).

The event model needs to be flexible enough to support arbitrary performance definitions. Grade likely uses a rule engine, configurable conditions ("if event_type == 'video_published' AND views > 10000, then payout = $50") evaluated against incoming events. Think of it as Zapier for payroll triggers, but with real money at the other end.

The Compliance and Tax Engine

This is the hard part that anyone building in this space systematically underestimates. The US alone has 1099-NEC reporting requirements that kick in above $600/year per contractor. International payments require W-8BEN collection, FATCA compliance, and increasingly OECD DAC7 reporting in Europe. Grade must collect and validate tax IDs at onboarding, store them encrypted at rest, generate correct forms at year-end, and file them with the IRS and equivalent agencies internationally.

Most startups punt on international compliance early (US-only first) or lean heavily on Stripe Tax plus a compliance SaaS like Taxjar or Avalara for the mechanical parts. The classification engine, is this person a contractor or an employee in their jurisdiction?, is where real legal risk lives and where Deel charges a premium. Grade will face this same question as they scale.

The Payout Rails

For US payouts, you are looking at ACH via a banking-as-a-service provider (Column, Stripe Treasury, or similar), with 1-3 day settlement. For international, it is Stripe payouts covering ~50 countries or a layered approach using Wise Business or Airwallex for exotic corridors. The key engineering concern is reconciliation, every disbursement needs to be tracked against the originating payout record, with failure states handled gracefully: bank rejects, incorrect account details, KYC failures, frozen accounts.

Grade runs approval workflows before disbursement: a company admin reviews and approves the batch before money moves. This is a critical trust and compliance feature, you want a human checkpoint before six-figure payroll runs execute automatically.

Tech Stack

Grade has not disclosed their stack publicly, but for a two-person YC fintech moving fast, the obvious choices are: Next.js for the dashboard, Node.js or Python (FastAPI) for the API backend, Postgres as the primary data store, Stripe for payment rails and tax form tooling, and AWS or Fly.io for infrastructure. They should invest in event sourcing early, immutable audit logs of every payment event are non-negotiable in fintech and genuinely painful to retrofit later.

Difficulty Score

Dimension Score Notes
ML / AI2 / 10Minimal. The rule engine is logic, not learning. Fraud detection signals might arrive later.
Data5 / 10Multi-jurisdiction tax rules, currency rates, compliance mappings across 50+ countries add real data complexity.
Backend7 / 10Idempotency, async payout jobs, reconciliation ledgers, event sourcing, fintech backends are genuinely hard to get right and painful to debug when wrong.
Frontend3 / 10Approval dashboard and reporting UI. Standard React work, nothing exotic.
DevOps6 / 10SOC 2 Type II required for enterprise. PCI-adjacent controls. High-availability SLAs for a service that cannot go down during payout runs.

Overall: 5 / 10. The software is not rocket science. The compliance stack and trust-building are the real lift.

The Moat, What's Hard, What's Not

Easy to replicate: The core CRUD of performance event ingestion, configurable rule engines, and dashboard approval flows. A good engineer could ship a working MVP in 6, 8 weeks. Stripe's APIs for payouts are excellent and thoroughly documented. There is nothing proprietary in the core software architecture here.

Hard to replicate:

  • Compliance certifications. SOC 2 Type II takes 6, 12 months minimum. Enterprise customers will not run payroll through an unaudited system. This is a time moat, not a tech moat, but it is real and compounding.
  • Banking relationships. ACH origination and international payment corridors require approved partnerships with banking providers. These take months to establish and involve KYC/AML review of the company itself, not just its customers.
  • Trust. Payroll is existential. If you miss a payment, contractors stop working. If you misfile a 1099, your customers receive IRS letters. This category requires trust that accretes with every clean payout run, not trust that can be bought with a marketing budget.
  • The AI agent wedge. Right now this is positioning more than product, but if Grade nails the API contracts and becomes the default way agentic platforms handle compensation, switching costs climb significantly. The company that owns the payout primitive for AI agents owns something durable.

Founder-market fit is worth calling out. Lotanna Ezeike came out of Barclays digital payments and built AI apps that scaled to millions of users, he has lived the creator payment pain personally. James Heaney brings a cryptography background and two prior exits. They are not building this because it seemed like a good startup idea; they built four apps, hit this wall repeatedly, and decided to fix the infrastructure instead.

Replicability Score: 38 / 100

You can clone the software in weeks. You cannot clone the compliance stack, banking approvals, SOC 2 certification, and accumulated payout trust in months. Grade sits squarely in the "standard fintech SaaS with real regulatory drag" tier, defensible for 12, 18 months out of the gate, but not a permanent fortress unless they build deep integrations or win the default position for AI agent compensation infrastructure.

The AI agent angle is the asymmetric bet here. If agentic workflows go mainstream at the pace the industry expects, whoever owns the payout primitive gets very sticky very fast. Grade is early on that particular racehorse, and their creator economy traction gives them a clean, cash-generating wedge while the AI agent market matures. Smart sequencing.

Watch Grade, not because the tech is hard to copy, but because the clock is ticking on the window where this is still a small-team opportunity.

© 2026 StartupHub.ai. All rights reserved. Do not enter, scrape, copy, reproduce, or republish this article in whole or in part. Use as input to AI training, fine-tuning, retrieval-augmented generation, or any machine-learning system is prohibited without written license. Substantially-similar derivative works will be pursued to the fullest extent of applicable copyright, database, and computer-misuse laws. See our terms.

Build This Startup with Claude Code

Complete replication guide — install as a slash command or rules file

# Build Guide: Clone Grade, Performance-Based Payroll API

**Stack**: Next.js 14, FastAPI (Python), PostgreSQL, Stripe, Redis, AWS

---

## Step 1: Database Schema

```sql
-- Workers / payees
CREATE TABLE workers (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID NOT NULL REFERENCES companies(id),
  external_id TEXT NOT NULL,              -- your system's contractor ID
  name TEXT NOT NULL,
  email TEXT NOT NULL,
  country_code CHAR(2) NOT NULL,
  tax_id TEXT,                            -- encrypted at rest via pgcrypto
  tax_form_type TEXT,                     -- '1099-NEC', 'W-8BEN', etc.
  stripe_account_id TEXT,                 -- for payouts via Stripe Connect
  status TEXT NOT NULL DEFAULT 'active',
  created_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE (company_id, external_id)
);

-- Payout rules (the configurable rule engine)
CREATE TABLE payout_rules (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID NOT NULL REFERENCES companies(id),
  name TEXT NOT NULL,
  event_type TEXT NOT NULL,               -- e.g. 'video_published', 'invoice_processed'
  conditions JSONB,                       -- e.g. {"views": {">": 10000}}
  payout_type TEXT NOT NULL,             -- 'flat', 'per_unit', 'tiered'
  payout_amount_cents BIGINT,
  payout_tiers JSONB,                    -- [{min: 0, max: 1000, rate_cents: 10}, ...]
  currency TEXT NOT NULL DEFAULT 'usd',
  active BOOLEAN DEFAULT true,
  created_at TIMESTAMPTZ DEFAULT now()
);

-- Performance events ingested via API/webhook
CREATE TABLE performance_events (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID NOT NULL,
  worker_id UUID NOT NULL REFERENCES workers(id),
  idempotency_key TEXT NOT NULL,          -- client-supplied, deduplicated
  event_type TEXT NOT NULL,
  quantity NUMERIC NOT NULL DEFAULT 1,
  metadata JSONB,
  processed BOOLEAN DEFAULT false,
  payout_id UUID,                         -- set once matched to a payout
  created_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE (company_id, idempotency_key)
);

-- Calculated payouts (pending approval)
CREATE TABLE payouts (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID NOT NULL,
  worker_id UUID NOT NULL REFERENCES workers(id),
  payout_rule_id UUID REFERENCES payout_rules(id),
  amount_cents BIGINT NOT NULL,
  currency TEXT NOT NULL DEFAULT 'usd',
  status TEXT NOT NULL DEFAULT 'pending', -- pending, approved, processing, paid, failed
  period_start DATE,
  period_end DATE,
  stripe_transfer_id TEXT,
  error_message TEXT,
  approved_by UUID,
  approved_at TIMESTAMPTZ,
  paid_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);

-- Annual tax reporting tracker
CREATE TABLE tax_filings (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  company_id UUID NOT NULL,
  worker_id UUID NOT NULL,
  tax_year INT NOT NULL,
  form_type TEXT NOT NULL,
  total_paid_cents BIGINT NOT NULL,
  filing_status TEXT DEFAULT 'pending',  -- pending, filed, corrected
  filed_at TIMESTAMPTZ,
  UNIQUE (company_id, worker_id, tax_year, form_type)
);
```

---

## Step 2: API Design

**Event Ingestion** (idempotent):
```
POST /v1/events
Authorization: Bearer {api_key}
{
  "idempotency_key": "vid_123456_published",
  "worker_id": "wrk_abc",
  "event_type": "video_published",
  "quantity": 1,
  "metadata": {"views": 45000, "platform": "youtube"}
}
```

**Rule Engine Evaluation** (background job):
- On new event insert, push to Redis queue
- Worker picks up, queries matching payout rules for company
- Evaluates conditions (jsonpath or custom evaluator)
- Creates `payouts` row if rule matches, links event → payout

**Payout Approval** (human-in-the-loop):
```
GET  /v1/payouts?status=pending&period=2026-06
POST /v1/payouts/{id}/approve
POST /v1/payouts/batch-approve  { "payout_ids": [...] }
```

**Disbursement** (triggered on approval):
```
POST /v1/payouts/{id}/disburse  → triggers Stripe Transfer
```

**Worker Onboarding**:
```
POST /v1/workers          → create payee
POST /v1/workers/{id}/kyc → trigger Stripe Connect onboarding link
GET  /v1/workers/{id}/tax-forms?year=2025
```

---

## Step 3: Rule Engine (Key Algorithm)

```python
import jsonschema
from decimal import Decimal

def evaluate_rule(rule: dict, event: dict) -> int | None:
    """Returns payout amount in cents, or None if rule doesn't match."""
    conditions = rule.get("conditions", {})
    metadata = event.get("metadata", {})

    for field, constraint in conditions.items():
        value = metadata.get(field)
        if value is None:
            return None
        for op, threshold in constraint.items():
            if op == ">" and not (value > threshold): return None
            if op == ">=" and not (value >= threshold): return None
            if op == "<" and not (value < threshold): return None
            if op == "==" and not (value == threshold): return None

    qty = Decimal(event.get("quantity", 1))

    if rule["payout_type"] == "flat":
        return rule["payout_amount_cents"]
    elif rule["payout_type"] == "per_unit":
        return int(qty * rule["payout_amount_cents"])
    elif rule["payout_type"] == "tiered":
        for tier in sorted(rule["payout_tiers"], key=lambda t: t["min"]):
            if tier["min"] <= qty <= tier.get("max", float("inf")):
                return int(qty * tier["rate_cents"])
    return None
```

---

## Step 4: Idempotency & Deduplication

```python
# FastAPI endpoint with idempotency key check
@router.post("/v1/events")
async def ingest_event(event: EventSchema, db: AsyncSession = Depends(get_db)):
    # Idempotency: return existing if key already processed
    existing = await db.execute(
        select(PerformanceEvent).where(
            PerformanceEvent.idempotency_key == event.idempotency_key,
            PerformanceEvent.company_id == event.company_id
        )
    )
    if existing.scalar_one_or_none():
        return {"status": "duplicate", "message": "Event already received"}

    new_event = PerformanceEvent(**event.dict())
    db.add(new_event)
    await db.commit()

    # Enqueue for rule evaluation
    await redis.rpush("events:pending", str(new_event.id))
    return {"status": "accepted", "event_id": str(new_event.id)}
```

---

## Step 5: Stripe Connect for Global Payouts

```python
import stripe

def onboard_worker(worker_id: str, email: str, country: str) -> str:
    """Create Stripe Connect Express account and return onboarding URL."""
    account = stripe.Account.create(
        type="express",
        country=country,
        email=email,
        capabilities={"transfers": {"requested": True}},
    )
    # Store account.id on workers row
    link = stripe.AccountLink.create(
        account=account.id,
        refresh_url=f"https://app.usegrade.com/workers/{worker_id}/retry",
        return_url=f"https://app.usegrade.com/workers/{worker_id}/onboarded",
        type="account_onboarding",
    )
    return link.url

def disburse_payout(payout_id: str, amount_cents: int,
                    stripe_account_id: str, currency: str = "usd") -> str:
    transfer = stripe.Transfer.create(
        amount=amount_cents,
        currency=currency,
        destination=stripe_account_id,
        metadata={"payout_id": payout_id},
    )
    return transfer.id
```

---

## Step 6: Tax Compliance Automation

```python
# Year-end 1099 aggregation job (run January 1)
async def generate_1099s(company_id: str, tax_year: int):
    result = await db.execute("""
        SELECT worker_id, SUM(amount_cents) as total_cents
        FROM payouts
        WHERE company_id = :company_id
          AND status = 'paid'
          AND EXTRACT(YEAR FROM paid_at) = :year
        GROUP BY worker_id
        HAVING SUM(amount_cents) >= 60000  -- $600 threshold
    """, {"company_id": company_id, "year": tax_year})

    for row in result:
        worker = await get_worker(row.worker_id)
        if worker.country_code == "US":
            form_type = "1099-NEC"
        else:
            form_type = "W-8BEN"
        # Use Stripe Tax or Taxjar API to file, or generate PDF
        await create_tax_filing(company_id, worker.id, tax_year, form_type,
                                row.total_cents)
```

---

## Step 7: Deployment & SOC 2 Readiness

```yaml
# docker-compose.yml (dev)
services:
  api:
    build: ./api
    environment:
      DATABASE_URL: postgresql+asyncpg://postgres:pass@db/grade
      REDIS_URL: redis://redis:6379
      STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
    ports: ["8000:8000"]
  worker:
    build: ./api
    command: python -m workers.rule_evaluator
  db:
    image: postgres:16
    volumes: ["pgdata:/var/lib/postgresql/data"]
  redis:
    image: redis:7-alpine
```

**SOC 2 checklist (start early):**
- Encrypt PII at rest (pgcrypto for tax IDs, SSNs)
- TLS 1.2+ everywhere, HSTS headers
- Immutable audit log table (no UPDATE/DELETE, append-only via trigger)
- MFA enforced on all internal accounts
- Automated access reviews quarterly
- Incident response runbook in place
- Use Vanta or Drata to automate evidence collection, saves ~200 hours of manual prep

**Estimated build time to MVP:** 6, 8 weeks for a senior engineer
**Time to enterprise-ready (SOC 2 + banking approvals):** 9, 14 months

**Key dependencies:**
- Stripe Connect (payouts), apply for platform approval early, takes 2, 4 weeks
- Column.com or Mercury for ACH origination
- Taxjar or Stripe Tax for US state tax calculations
- Vanta for SOC 2 automation
claude-code-skills.md