Skip to content

Repository files navigation

PayGate

PayGate is a pay-per-call gateway for APIs on Stellar testnet.

It lets a developer register a normal API, expose it through a PayGate paid proxy, let AI agents or machine clients pay per request through Stellar MPP, and track revenue, fees, calls, and withdrawals from a developer dashboard.

PayGate V1 is a testnet beta candidate. It is designed to prove the product loop, not to handle mainnet funds yet.

Detailed Docs · Developer Guide · V1 Product Spec · Demo Guide · Beta Readiness · OpenSpec

Stellar Testnet MPP Payments Soroban Escrow Supabase Vercel


Table of Contents


What Is PayGate?

PayGate is a gateway layer for developers who want to monetize API calls without building payment infrastructure from scratch.

Instead of asking API buyers to subscribe, create accounts, or go through human-style checkout, PayGate exposes a paid proxy endpoint:

AI agent / machine client
-> PayGate paid proxy
-> original developer API

The developer keeps their API normal. PayGate handles:

  • Freighter wallet login for developer identity.
  • API registration and paid proxy generation.
  • HTTP 402 Payment Required challenges.
  • Stellar MPP payment verification.
  • Soroban escrow crediting.
  • 90% developer / 10% PayGate fee split.
  • Dashboard reporting.
  • Developer withdrawal.

The original SOW/V0 code generator still exists at /generate, but it is now treated as a legacy helper. The main V1 product flow starts at /dashboard and /apis/new.

Developers integrating their own API should start with the Developer Guide. It explains the PayGate proxy URL, API secret, upstream guard, and 401/402/200 testing flow.


Why This Matters

Most API monetization assumes a human buyer:

  1. create an account,
  2. enter a card,
  3. choose a plan,
  4. manage subscription billing,
  5. then call the API.

That flow is awkward for AI agents and machine clients. Agents need something more direct:

  1. request a resource,
  2. receive a payment challenge,
  3. pay for that single call,
  4. retry with proof,
  5. receive the API response.

PayGate demonstrates that pattern with Stellar testnet USDC, MPP, and a PayGate-controlled paid gateway.


Current Status

PayGate V1 currently supports the full testnet beta loop locally and in deploy-ready code:

Area Status
Freighter wallet login Done
Supabase-backed auth challenges Done
API registry Done
API lifecycle: pending setup -> active -> archived Done
Upstream ownership verification Done
Duplicate live endpoint prevention Done
API delete/archive for demo reset Done
API secret encryption Done
Paid proxy /api/pay/:apiId Done
MPP unpaid 402 flow Done
MPP paid 200 flow Done, testnet proof captured
Soroban escrow contract Done for testnet demo
90% developer / 10% PayGate split Done
Dashboard summary Done
Developer withdrawal Done
Platform fee withdrawal command Done
Beta evidence package Done
Production live replay Pending
Demo video Pending

Read the current readiness note in docs/evidence/PAYGATE_V1_BETA_READINESS.md.


Review Path

For a reviewer or demo session, the shortest path is:

  1. Open the deployed PayGate app.
  2. Connect Freighter on Stellar Testnet.
  3. Open /apis/new and register the demo upstream API.
  4. Copy the generated proxy URL and API secret.
  5. Set PAYGATE_DEMO_UPSTREAM_SECRET to the generated secret.
  6. Redeploy the upstream so the secret guard is live.
  7. Open the API detail page and click Verify setup; the API should move from Pending setup to Active.
  8. Call the original upstream without the secret and confirm 401.
  9. Call the PayGate proxy without payment and confirm 402.
  10. Run the local agent/client to pay with testnet USDC.
  11. Confirm the proxy returns 200 with the upstream JSON response.
  12. Open /dashboard and verify calls, payment tx, credit tx, revenue, fee, and withdrawable balance.
  13. Withdraw developer balance with Freighter.

The detailed replay script lives in docs/PAYGATE_V1_DEMO_GUIDE.md.


Core Flow

sequenceDiagram
  participant Dev as Developer
  participant PayGate
  participant Agent as AI Agent / Client
  participant MPP as Stellar MPP
  participant Escrow as Soroban Escrow
  participant API as Original API

  Dev->>PayGate: Connect Freighter and sign login challenge
  Dev->>PayGate: Register API URL, path, and USDC price
  PayGate-->>Dev: Return paid proxy URL, API secret, and Pending setup state
  Dev->>API: Add X-PayGate-Secret guard
  Dev->>PayGate: Verify setup
  PayGate->>API: Probe upstream with X-PayGate-Secret
  PayGate-->>Dev: Mark API Active
  Agent->>PayGate: GET /api/pay/:apiId
  PayGate-->>Agent: 402 Payment Required
  Agent->>MPP: Pay USDC testnet
  Agent->>PayGate: Retry request with payment credential
  PayGate->>MPP: Verify payment
  PayGate->>Escrow: credit_payment(paymentId, developer, amount)
  PayGate->>API: Forward request with X-PayGate-Secret
  API-->>PayGate: Protected JSON response
  PayGate-->>Agent: 200 OK + response
  Dev->>PayGate: Open dashboard and withdraw balance
Loading

Architecture

flowchart LR
  Frontend["React SPA"] --> Auth["Wallet Auth Functions"]
  Frontend --> Registry["API Registry Functions"]
  Frontend --> Dashboard["Dashboard Functions"]

  Agent["AI Agent / Machine Client"] --> Proxy["PayGate Paid Proxy"]
  Proxy --> MPP["Stellar MPP Charge"]
  Proxy --> Store["Supabase Postgres"]
  Proxy --> Escrow["Soroban Escrow Contract"]
  Proxy --> Upstream["Original Developer API"]

  Auth --> Store
  Registry --> Store
  Dashboard --> Store
  Dashboard --> Escrow
Loading

Stack

  • Frontend: React 18, Vite, React Router, Tailwind CSS, lucide-react.
  • API runtime: Vercel Functions in api/.
  • Legacy generator backend: Express in backend/.
  • Database: Supabase Postgres.
  • Payments: @stellar/mpp, mppx, Stellar testnet USDC.
  • Settlement: Soroban escrow contract.
  • Wallet: Freighter.
  • Demo client: Node.js script in examples/express-paid-api.

Features

Developer Side

  • Connect Freighter wallet.
  • Sign a challenge to prove wallet ownership.
  • Register a GET JSON API.
  • Set price per call in USDC.
  • Receive a PayGate paid proxy URL while the API starts in Pending setup.
  • Receive a unique X-PayGate-Secret for upstream protection.
  • Verify setup before the API becomes Active.
  • Delete unused APIs or archive paid APIs for demo reset without losing history.
  • See API calls, successful calls, failed calls, and payment history.
  • See gross revenue, developer revenue, and PayGate fee.
  • Withdraw escrow balance with a Freighter-signed transaction.

Agent / Buyer Side

  • Call a paid proxy endpoint.
  • Receive HTTP 402 Payment Required when unpaid.
  • Pay Stellar testnet USDC through MPP.
  • Retry the request with payment proof.
  • Receive the upstream API response after settlement.

PayGate Operator Side

  • Verify MPP payment credentials.
  • Credit the Soroban escrow ledger.
  • Track request and payment state in Supabase.
  • Withdraw accumulated platform fees.
  • Generate evidence for grant/demo review.

API Surface

Method Path Description
POST /api/generate Legacy V0 middleware generator
GET /api/auth/me Reads the current wallet session
POST /api/auth/challenge Creates a Freighter sign-message challenge
POST /api/auth/verify Verifies the signed challenge and creates a session
POST /api/auth/logout Clears the wallet session
GET /api/apis Lists APIs owned by the connected wallet
POST /api/apis Registers a new API
GET /api/apis/:apiId Reads one registered API
PATCH /api/apis/:apiId Updates API metadata such as name
DELETE /api/apis/:apiId Deletes unused APIs or archives APIs with activity
POST /api/apis/:apiId/verify Verifies upstream X-PayGate-Secret setup and activates the API
GET /api/pay/:apiId Paid proxy endpoint
GET /api/dashboard/summary Dashboard summary for the connected wallet
POST /api/withdraw/prepare Prepares a Freighter-signed withdrawal transaction
POST /api/withdraw/submit Submits a signed withdrawal transaction
GET /api/upstream/market-signal Secret-protected demo upstream API
GET /api/demo/market-signal Legacy standalone paid sample API

Register API Example

POST /api/apis
Content-Type: application/json
Cookie: paygate_session=...
{
  "name": "PayGate Demo Market Signal",
  "upstreamBaseUrl": "https://your-paygate-domain.vercel.app",
  "path": "/api/upstream/market-signal",
  "priceUsdc": 0.01
}

Example response:

{
  "api": {
    "id": "api_id",
    "name": "PayGate Demo Market Signal",
    "status": "pending_setup",
    "active": false,
    "proxyUrl": "https://your-paygate-domain.vercel.app/api/pay/api_id",
    "secret": "pgsec_...",
    "setup": {
      "requiredHeader": "X-PayGate-Secret"
    }
  }
}

Paid Proxy Example

GET /api/pay/:apiId

Without payment, PayGate returns HTTP 402 Payment Required. A compatible MPP client pays, retries with the payment credential, and receives the upstream JSON response.


Local Development

Use Node.js 22+ locally.

npm install
npm --prefix frontend install
vercel env pull .env.local --environment=development --yes
vercel dev

Open:

http://localhost:3000

Verify that V1 API functions are loaded:

curl -i http://localhost:3000/api/auth/me

Expected before login:

{"authenticated":false}

If this request logs a Vite proxy ECONNREFUSED, your linked Vercel project is still using frontend as the Root Directory. Change the Vercel project Root Directory to the repo root.

Frontend-Only Visual Mode

Use this only for visual checks. It does not load V1 API functions.

cd frontend
npm install
npm run dev

Open:

http://localhost:5173

Environment Variables

Copy the template:

cp .env.example .env.local

Required server env for V1:

SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=
SESSION_SECRET=
API_SECRET_ENCRYPTION_KEY=
MPP_SECRET_KEY=
CRON_SECRET=
ESCROW_CONTRACT_ID=
PAYGATE_OPERATOR_SECRET=
PAYGATE_DEMO_UPSTREAM_SECRET=
STELLAR_NETWORK=stellar:testnet
STELLAR_RPC_URL=https://soroban-testnet.stellar.org

Generate strong random secrets:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Important rules:

  • Do not commit .env.local.
  • Do not put payer wallet secrets in Vercel.
  • STELLAR_SECRET belongs only in the local agent/client environment.
  • Do not use PAYGATE_AUTH_CHALLENGE_STORE=memory or PAYGATE_REGISTRY_STORE=memory in Vercel.
  • Set CRON_SECRET to a random value of at least 16 characters in Vercel Production.

Supabase Setup

Run these migrations in the Supabase SQL Editor:

supabase/migrations/20260604000000_paygate_v1_registry.sql
supabase/migrations/20260604000001_paygate_v1_paid_proxy.sql

They create the V1 storage layer:

developers
auth_challenges
apis
proxy_requests
payments
withdrawals
mpp_store

Use the Supabase service role key only on the server side.

Supabase Free Plan projects may be paused after sustained low activity. PayGate uses a secured daily Vercel cron request to perform three read-only health queries. This reduces pause risk for the testnet beta, but a paid Supabase plan is still required when uninterrupted production availability becomes a requirement.


Deployment

PayGate is intended to run as a single Vercel project from the repo root.

Vercel project settings:

Root Directory: repo root
Build Command: npm run build
Output Directory: frontend/dist
Install Command: npm install
Node.js Version: 22.x or 24.x

Check the linked project:

vercel project inspect paygate-stellar

The output must not show:

Root Directory: frontend

If it does, /api/* will fall through to the Vite frontend proxy instead of loading Vercel Functions.

After setting env vars in Vercel:

vercel env pull .env.local --environment=development --yes

The Hobby-compatible cron schedule is defined in vercel.json and calls /api/cron/database-health once per day. Vercel sends CRON_SECRET as a Bearer token; requests without the matching token are rejected.


Verification Checklist

Run from the repo root:

npm run test:beta
npm run audit:prod
npm run test:browser
npm run test:database-health
git diff --check

Optional deployed readiness checks:

npm run beta:preflight
npm run test:auth:supabase

Quick API checks:

curl -i http://localhost:3000/api/auth/me
curl -i http://localhost:3000/api/upstream/market-signal
curl -i http://localhost:3000/api/pay/<apiId>

Expected behavior:

  • /api/auth/me returns {"authenticated":false} before login.
  • /api/upstream/market-signal returns 401 without X-PayGate-Secret.
  • /api/pay/<apiId> returns 402 without payment.
  • A paid agent/client retry returns 200 with the protected JSON response.

Demo Evidence

Existing testnet evidence is tracked under docs/evidence/.

Evidence File
Escrow deploy/init/withdraw/platform fee Phase 1 settlement proof
Wallet auth Phase 2 wallet auth proof
API registry Phase 3 registry proof
Upstream API protection Phase 4 upstream proof
Unpaid proxy 402 Phase 5 unpaid proxy proof
Paid proxy 200 and escrow credit Phase 6 paid proxy proof
Dashboard Phase 7 dashboard proof
Withdrawal Phase 8 withdrawal proof

Important testnet tx hashes already captured:

Action Tx hash
Agent pays escrow through MPP c7cc23efa9130c1178343d22bd98a0fd5f6e23fde2a2224715a0a7a99b3734a6
PayGate credits escrow ledger db5e1e1c6d9e6b9d24887ac96cb18a227fd7866d044da6d0db8ccc45c8708ee1
Developer withdraw proof 8f0647f5595020a394df833b1545e2d4c0e192af960db2b1e3c68dfd679d50d7
Platform fee withdraw proof 0bf30b3fd0b5385f933dd9b22de39a6c8167e2c6405ac075a2bd13466a26d04b

Create a new replay folder:

npm run evidence:init

Project Structure

paygate/
├── api/                       # Vercel Functions for V1 auth, registry, proxy, dashboard, withdrawal
├── backend/                   # Legacy Express generator backend
├── contracts/                 # Soroban escrow contract
├── docs/                      # Specs, demo guide, handoff docs, evidence
├── examples/express-paid-api  # Demo API and local agent/client
├── frontend/                  # React SPA
├── openspec/                  # OpenSpec changes and capability specs
├── scripts/                   # Smoke tests, beta preflight, evidence tooling
├── supabase/                  # SQL migrations
├── package.json
└── vercel.json

V1 Boundaries

  • Testnet only.
  • USDC only.
  • GET JSON APIs only.
  • Buyer is represented by a local script/agent client.
  • No buyer account system yet.
  • No prepaid balance yet.
  • No refund flow if upstream fails after payment.
  • No mainnet, fiat checkout, compliance workflow, or production incident response yet.

Roadmap

  • Complete deployed Vercel replay with real env and screenshots.
  • Record a concise demo video.
  • Add POST/body forwarding.
  • Add refund or pending-credit handling for upstream failure.
  • Add buyer-side UX or agent SDK.
  • Add mainnet readiness review.
  • Add provider onboarding polish and API secret rotation.
  • Add analytics, webhooks, and richer dashboard filters.

References

License

MIT © 2026 PayGate

About

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages