Claude-skill-registry api-route

Create a new Next.js API route with x402 micropayment middleware

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/api-route" ~/.claude/skills/majiayu000-claude-skill-registry-api-route && rm -rf "$T"
manifest: skills/data/api-route/SKILL.md
source content

Create API Route with x402

Create a new API route: $ARGUMENTS

x402 Pricing Reference (from IMPLEMENTATION_CHECKLIST.md)

EndpointPriceDescription
/api/solar/irradiance
0.001 USDCReal-time solar data
/api/grid/carbon
0.002 USDCCarbon intensity
/api/buildings/area
0.005 USDCBuilding footprints
/api/geocode/search
0.001 USDCAddress geocoding
/api/premium/analytics
0.01 USDCPremium aggregated data

File Structure

src/pages/api/
├── solar/
│   └── irradiance.ts
├── grid/
│   └── carbon.ts
├── buildings/
│   └── area.ts
├── geocode/
│   └── search.ts
└── premium/
    └── analytics.ts

API Route Template

// src/pages/api/{path}.ts
import type { NextApiRequest, NextApiResponse } from "next";

// Types for this endpoint
interface ResponseData {
  // Define response shape
}

interface ErrorResponse {
  error: string;
  message: string;
}

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseData | ErrorResponse>
) {
  // Only allow GET requests (or POST if needed)
  if (req.method !== "GET") {
    return res.status(405).json({
      error: "Method not allowed",
      message: "Only GET requests are supported"
    });
  }

  try {
    // Extract query parameters
    const { lat, lng } = req.query;

    // Validate required parameters
    if (!lat || !lng) {
      return res.status(400).json({
        error: "Bad request",
        message: "Missing required parameters: lat, lng"
      });
    }

    // TODO: Add x402 middleware check here
    // const paymentValid = await verifyX402Payment(req);
    // if (!paymentValid) {
    //   return res.status(402).json({ error: "Payment required" });
    // }

    // Fetch from upstream API
    const data = await fetchUpstreamData(
      parseFloat(lat as string),
      parseFloat(lng as string)
    );

    // Return response with caching headers
    res.setHeader("Cache-Control", "s-maxage=300, stale-while-revalidate");
    return res.status(200).json(data);

  } catch (error) {
    console.error("API error:", error);
    return res.status(500).json({
      error: "Internal server error",
      message: "Failed to fetch data"
    });
  }
}

async function fetchUpstreamData(lat: number, lng: number): Promise<ResponseData> {
  // Implement upstream API call
  throw new Error("Not implemented");
}

x402 Middleware Pattern (Future)

// src/lib/x402/middleware.ts
import { X402_PRICING } from "./config";

export async function withX402(
  req: NextApiRequest,
  res: NextApiResponse,
  endpoint: string,
  handler: () => Promise<void>
) {
  const pricing = X402_PRICING[endpoint];

  // Check for valid payment header
  const paymentHeader = req.headers["x-402-payment"];

  if (!paymentHeader && !pricing.freeTier) {
    return res.status(402).json({
      error: "Payment required",
      price: pricing.price,
      description: pricing.description,
    });
  }

  // Verify payment signature...

  return handler();
}

Upstream API Clients

Create corresponding client in

src/lib/api/
:

  • openMeteo.ts
    - Solar irradiance data
  • electricityMaps.ts
    - Carbon intensity
  • overpass.ts
    - Building footprints (OSM)
  • nominatim.ts
    - Geocoding

Checklist

  • Create API route file in correct path under
    src/pages/api/
  • Define TypeScript interfaces for request/response
  • Add input validation
  • Add error handling with proper status codes
  • Add caching headers where appropriate
  • Create upstream API client in
    src/lib/api/
    if needed
  • Document x402 pricing in config
  • Test with curl/Postman