# API Scaffolding

API Scaffolding is a separate Valiron product for exposing existing HTTPS APIs through hosted, agent-facing URLs. It can add x402 or MPP payment handling, optional Valiron trust checks, rate limits, upstream forwarding, and usage logs without requiring immediate SDK middleware integration.

Use this flow when Valiron should host the payment and optional trust layer for an existing HTTPS API:

```text
Agent or client
  -> Valiron-hosted wrapper URL
  -> x402 or MPP payment check
  -> optional Valiron trust check
  -> provider's existing API
  -> response returned through Valiron
```

The wrapper is intentionally narrow: Valiron forwards valid HTTP requests to an existing upstream API. It does not need direct database access, internal service access, or provider infrastructure credentials beyond the optional upstream auth secret needed to call the API.

## When To Use This

Use API Scaffolding when:

- You already have an HTTPS API and want to sell per-call access to agents.
- You want x402 or MPP payment challenges without implementing those protocols yourself.
- You want Valiron trust checks before paid traffic reaches your API.
- You need a no-code or low-code path from an existing API to an agent-compatible endpoint.

Use the SDK middleware instead when:

- You want payments to be handled entirely by your own server.
- You need custom payment terms, subscriptions, account billing, or business-specific authorization.
- Valiron should run directly in the API backend as the primary trust and policy enforcement layer.

## Provider Setup

Providers configure one wrapper per public endpoint.

| Field | Required | Description |
|-------|----------|-------------|
| Public path | Yes | Path callers use on Valiron, for example `/weather`. |
| HTTP method | Yes | `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, or `HEAD`. |
| Upstream base URL | Yes | Existing HTTPS API base URL, for example `https://api.example.com`. |
| Price per call | Yes | USD amount charged for paid requests. Use `0` for a free wrapper. |
| Payment protocol | Yes | `x402` or `MPP`. |
| Payment network | Yes | x402: `eip155:8453` or `eip155:84532`; MPP: `tempo:4217` or `tempo:42431`. |
| Payout wallet | Paid only | EVM address receiving payment. |
| Upstream auth | No | Secret Valiron injects when forwarding to your upstream. |
| Rate limit | No | Max requests per minute per client. |
| Trust check | No | Whether callers must pass Valiron agent trust evaluation before forwarding. |

Example existing API:

```text
GET https://api.example.com/weather
```

Example Valiron URL:

```text
GET https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather
```

Valiron preserves query strings and appends the public wrapper path to the upstream base URL. If your upstream base URL is `https://api.example.com/v1` and your public path is `/weather`, Valiron forwards to:

```text
https://api.example.com/v1/weather
```

## Dashboard Flow

1. Open [valiron.co/dashboard](https://www.valiron.co/dashboard).
2. Go to **Make API Agent-Ready**.
3. Click **Make API Agent-Ready**.
4. Enter the upstream URL, public path, method, price, protocol, network, and payout wallet.
5. Choose whether Valiron trust checks are required.
6. Configure upstream auth only if your API needs it.
7. Create the wrapper.
8. Distribute the generated Valiron URL to agent clients or API customers.

## HTTP API Flow

The dashboard calls the same operator API you can call directly.

### Register

```bash
curl -X POST https://valiron-edge-proxy.onrender.com/operator/register \
  -H "content-type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "a-long-password",
    "name": "Example Operator"
  }'
```

### Login

```bash
curl -X POST https://valiron-edge-proxy.onrender.com/operator/login \
  -H "content-type: application/json" \
  -d '{
    "email": "you@example.com",
    "password": "a-long-password"
  }'
```

### Create A Free Wrapper

```bash
curl -X POST https://valiron-edge-proxy.onrender.com/operator/endpoints \
  -H "authorization: Bearer $VALIRON_JWT" \
  -H "content-type: application/json" \
  -d '{
    "path": "/weather",
    "method": "GET",
    "pricePerCall": 0,
    "targetUrl": "https://api.example.com",
    "paymentProtocol": "x402",
    "paymentNetwork": "eip155:8453",
    "trustEnabled": false,
    "upstreamAuthType": "none"
  }'
```

### Create A Paid x402 Wrapper

```bash
curl -X POST https://valiron-edge-proxy.onrender.com/operator/endpoints \
  -H "authorization: Bearer $VALIRON_JWT" \
  -H "content-type: application/json" \
  -d '{
    "path": "/weather",
    "method": "GET",
    "pricePerCall": 0.001,
    "targetUrl": "https://api.example.com",
    "paymentProtocol": "x402",
    "paymentNetwork": "eip155:8453",
    "payoutAddress": "0xYourPayoutWallet",
    "trustEnabled": false,
    "upstreamAuthType": "none"
  }'
```

### Create A Paid MPP Wrapper

```bash
curl -X POST https://valiron-edge-proxy.onrender.com/operator/endpoints \
  -H "authorization: Bearer $VALIRON_JWT" \
  -H "content-type: application/json" \
  -d '{
    "path": "/research",
    "method": "GET",
    "pricePerCall": 0.001,
    "targetUrl": "https://api.example.com",
    "paymentProtocol": "mpp",
    "paymentNetwork": "tempo:4217",
    "payoutAddress": "0xYourPayoutWallet",
    "trustEnabled": false,
    "upstreamAuthType": "none"
  }'
```

For Tempo testnet, use:

```json
{ "paymentNetwork": "tempo:42431" }
```

### List Wrappers

```bash
curl https://valiron-edge-proxy.onrender.com/operator/endpoints \
  -H "authorization: Bearer $VALIRON_JWT"
```

### Deactivate A Wrapper

```bash
curl -X DELETE https://valiron-edge-proxy.onrender.com/operator/endpoints/{endpointId} \
  -H "authorization: Bearer $VALIRON_JWT"
```

Deactivation is a soft delete. Existing logs remain available.

## Calling A Wrapper

Call the generated URL directly:

```bash
curl -i https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather
```

For a free wrapper, Valiron forwards immediately and returns the upstream response with Valiron wrapper headers:

```text
x-valiron-wrapper-id: ...
x-valiron-payment-protocol: free
x-valiron-trust-enabled: false
```

For a paid x402 wrapper without payment, Valiron returns `402` and an x402 payment challenge:

```text
HTTP/1.1 402 Payment Required
x-payment-required: ...
```

For a paid MPP wrapper without payment, Valiron returns `402` and an MPP challenge:

```text
HTTP/1.1 402 Payment Required
WWW-Authenticate: Payment ...
```

## x402 Paid Client

Use an x402-capable client to retry with payment. The repo includes a local buyer test client in `services/x402-test-server/src/buyer-test.ts`, and the production smoke path uses the same libraries:

- `@x402/fetch`
- `@x402/core/client`
- `@x402/evm/exact/client`
- `viem/accounts`

Minimal client shape:

```typescript
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.BUYER_PRIVATE_KEY as `0x${string}`);

const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(account));

const fetchWithPayment = wrapFetchWithPayment(fetch, client);

const response = await fetchWithPayment(
  "https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/weather",
  { method: "GET", headers: { "x-agent-id": "25459" } }
);

console.log(response.status);
console.log(await response.text());
```

The buyer wallet must hold the required token on the selected x402 network. For Base mainnet, the default production path expects USDC on Base.

## MPP Paid Client

Valiron MPP support uses the official `mppx` SDK with the Tempo `charge` intent.

Server behavior:

- Unpaid request returns `402`.
- Response includes `WWW-Authenticate: Payment ...`.
- Paid request includes `Authorization: Payment ...`.
- Successful paid response includes `Payment-Receipt`.

Recommended testnet client flow:

```bash
pnpm exec mppx account create
pnpm exec mppx https://valiron-edge-proxy.onrender.com/wrap/{operatorId}/research
```

Use `tempo:42431` for Tempo testnet and `tempo:4217` for Tempo mainnet.

Default Tempo currencies from `mppx`:

| Network | Chain ID | Default currency |
|---------|----------|------------------|
| Tempo mainnet | `4217` | USDC (`0x20C000000000000000000000b9537d11c60E8b50`) |
| Tempo testnet | `42431` | pathUSD (`0x20c0000000000000000000000000000000000000`) |

## Optional Trust Checks

When `trustEnabled` is `false`, Valiron only handles payment, rate limiting, upstream auth, and forwarding.

When `trustEnabled` is `true`, callers must identify the agent:

```text
x-agent-id: 25459
```

Valiron evaluates the agent before forwarding. If the agent is denied, the upstream API is not called.

Use trust checks when:

- You want to block risky agents even if they can pay.
- You want route decisions and call logs tied to agent IDs.
- You plan to vary pricing, limits, or access based on trust tiers.

Use payment-only wrappers when:

- You want the lowest-friction paid endpoint.
- You do not need agent identity yet.
- You are testing x402 or MPP integration.

## Upstream Auth

If your existing API requires auth, Valiron stores the secret encrypted and injects it only when forwarding a valid request upstream.

Supported auth modes:

| Mode | Behavior |
|------|----------|
| `none` | No upstream auth is added. |
| `bearer` | Adds `Authorization: Bearer <secret>`. |
| `api_key` | Adds the secret to the configured header name. |
| `hmac` | Signs the request using the secret and adds signature headers. |

The calling agent never sees your upstream secret.

Production requires `VALIRON_SECRET_ENCRYPTION_KEY` to store upstream auth secrets. Use a 32-byte hex key:

```bash
openssl rand -hex 32
```

## Security Defaults

In production, Valiron wrappers:

- Require HTTPS upstream URLs.
- Block localhost, private IP ranges, link-local IPs, metadata hosts, and internal hostnames.
- Resolve upstream DNS and block private resolved IPs.
- Strip hop-by-hop and sensitive inbound headers before forwarding.
- Do not forward inbound `Authorization`, `Cookie`, `x-payment`, or `payment-signature` headers to the upstream.
- Add Valiron wrapper metadata headers to forwarded requests.
- Apply per-endpoint rate limits.
- Enforce request body size limits.
- Time out slow upstream calls.

Local development can set:

```bash
VALIRON_ALLOW_INSECURE_UPSTREAMS=true
```

Only use this for local testing. Do not enable it in production.

## Production Environment Variables

Render / edge proxy:

| Variable | Required | Purpose |
|----------|----------|---------|
| `VALIRON_SECRET_ENCRYPTION_KEY` | Required for upstream auth | AES-256-GCM key for storing upstream secrets. |
| `X402_RECEIVING_ADDRESS` | Required for paid x402 without per-endpoint payout | Default payout wallet. Per-endpoint `payoutAddress` can also be used. |
| `X402_FACILITATOR_URL` | Optional | Defaults to `https://facilitator.payai.network`. |
| `MPP_SECRET_KEY` | Required for MPP | Secret used by `mppx` to sign/verify payment challenges. |
| `MPP_TEMPO_CURRENCY` | Optional | Override Tempo currency. Defaults come from `mppx`. |
| `MPP_TEMPO_CHAIN_ID` | Optional | Fallback Tempo chain ID when not set by endpoint. |
| `MPP_TEMPO_TESTNET` | Optional | Fallback testnet flag when not set by endpoint. |
| `MPP_TEMPO_WAIT_FOR_CONFIRMATION` | Optional | Defaults to `true`; set `false` only for specific test flows. |
| `MPP_REALM` | Optional | Defaults to `Valiron`. |
| `VALIRON_WRAPPER_MAX_BODY_BYTES` | Optional | Request body size limit. |
| `VALIRON_WRAPPER_UPSTREAM_TIMEOUT_MS` | Optional | Upstream request timeout. |

Vercel / website:

| Variable | Required | Purpose |
|----------|----------|---------|
| `NEXT_PUBLIC_API_URL` | Recommended | Edge proxy base URL used by the dashboard. |

## Local Test Example

Run the local x402 test server:

```bash
pnpm --filter x402-test-server dev
```

Run the edge proxy with local upstreams allowed:

```bash
VALIRON_ALLOW_INSECURE_UPSTREAMS=true pnpm --filter edge-proxy dev
```

Create a free test wrapper pointing at:

```text
http://localhost:4021
```

with public path:

```text
/health
```

Then call:

```bash
curl -i http://localhost:3005/wrap/{operatorId}/health
```

For paid x402 tests, use the buyer test client with a funded buyer key and the configured facilitator/network.

## Current Limits

The first wrapper release supports:

- Per-call x402 payments.
- Per-call MPP Tempo charge payments.
- Free wrappers.
- Optional trust checks.
- Optional upstream auth injection.
- Per-endpoint rate limits.

It does not yet support:

- MPP sessions or subscriptions.
- Multi-upstream routing.
- Cross-protocol fallback on a single endpoint.
- Non-HTTPS production upstreams.
