d402distributed 402
For application developers

Buy d402 work without joining the peer network.

Your app calls one or more HTTP gateways, handles a payment challenge, and receives result data plus receipts. Gateway operators absorb discovery, worker selection, validation, and settlement.

Integration contract

  • User applications call one or more d402 HTTP gateways.
  • Gateways handle payment challenges, peer discovery, routing, validation, and settlement.
  • Workers sell capabilities to the peer network and advertise payout wallets.
  • Discovery nodes improve peer reachability but do not define the application API.
  • Applications should store task IDs, receipts, payment responses, and evidence for auditability.

1. Discover a gateway

discovery request
GET /.well-known/d402-gateway.json
discovery response
{
  "d402GatewayVersion": 1,
  "dncGatewayVersion": 1,
  "nodeId": "gateway:abc123",
  "roles": ["gateway", "ingress"],
  "protocol": {
    "transport": "https",
    "taskApi": "d402-http-task-v1",
    "legacyTaskApi": "dnc-http-task-v1",
    "paymentChallenge": "solana-direct"
  },
  "endpoints": {
    "health": "https://gateway.example/health",
    "createTask": "https://gateway.example/tasks",
    "task": "https://gateway.example/tasks/{taskId}",
    "result": "https://gateway.example/tasks/{taskId}/result",
    "receipt": "https://gateway.example/tasks/{taskId}/receipt"
  },
  "capabilities": [{
    "capabilityId": "web.page_to_markdown@1",
    "price": "$0.01",
    "mode": "single",
    "fanout": 1,
    "quorum": 1
  }],
  "payment": {
    "rail": "solana-direct",
    "network": "solana:mainnet-beta",
    "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    "price": "$0.01",
    "creatorCommission": {
      "pricingMode": "included",
      "scope": "exact-manifest",
      "maxRateBps": 2000,
      "payoutRail": "solana"
    }
  }
}

The legacy /.well-known/dnc-gateway.json endpoint is supported by the prototype for compatibility. New clients should prefer the d402 path.

2. Create a task

sync web-to-markdown request
POST /tasks
Content-Type: application/json

{
  "input": {
    "url": "https://example.com",
    "timeoutMs": 10000
  }
}
async request
{
  "sync": false,
  "input": {
    "url": "https://example.com"
  }
}

Public gateways may ignore client-supplied capabilityId, mode, fanout, quorum, maxBudget, price, and payTo. Server-owned policy prevents underpriced or unsafe work. The displayed price is all-in; worker payouts, creator commissions, validator payouts, and refunds are settlement details, not extra buyer charges.

3. Handle payment required

If payment is required, the gateway returns HTTP 402. For x402-compatible rails, read the PAYMENT-REQUIRED header and response body. For Solana direct payment, the response body includes a d402-solana-transfer requirement.

RailClient retry proofNotes
x402PAYMENT-SIGNATUREUse an x402 wallet or client package to sign the accepted requirement.
Solana directAuthorization: Payment <base64-json>Send native Solana USDC transfer with the required d402: memo. Legacy dnc: memos remain accepted.
Solana channelBuyer-signed channel debit authorizationBest for repeated low-value requests from the same buyer.
solana payment credential
{
  "scheme": "d402-solana-transfer",
  "network": "solana:mainnet-beta",
  "transaction": "SolanaTransactionSignature",
  "payer": "BuyerSolanaWallet"
}

4. Read result and receipt

accepted response
{
  "taskId": "task:...",
  "status": "accepted",
  "result": {
    "url": "https://example.com/",
    "title": "Example Domain",
    "markdown": "# Example Domain\n\n...",
    "snapshotCid": "sha256:...",
    "contentHash": "sha256:...",
    "evidence": {
      "converter": "defuddle",
      "snapshotterVersion": "playwright"
    }
  },
  "settlement": {
    "payouts": [
      {
        "account": "WorkerSolanaWallet...",
        "amount": 0.009,
        "grossAmount": 0.01,
        "reason": "accepted-result"
      },
      {
        "account": "CreatorSolanaWallet...",
        "amount": 0.001,
        "reason": "creator-commission",
        "rateBps": 1000,
        "manifestCid": "sha256:..."
      }
    ]
  },
  "validationReceipt": {},
  "links": {
    "task": "/tasks/task-id",
    "result": "/tasks/task-id/result",
    "receipt": "/tasks/task-id/receipt"
  }
}

Clients should treat any non-accepted status as non-success unless the application has a specific fallback policy.

Creator commission visibility

A buyer does not calculate or separately pay creator commissions. A compliant gateway publishes commission policy in discovery and OpenAPI metadata, enforces the maximum rate, rejects paid routes that cannot split funds, and exposes the actual split in the task receipt.

  • Price remains all-in, for example $0.01.
  • Commission applies only when a signed accepted registration for the selected exact manifestCid declares it.
  • Receipts may include worker net payouts and aggregated creator-commission payout entries.
  • No commission entry should appear for failed, rejected, refunded, or missed-deadline tasks.

JavaScript client skeleton

requestMarkdown.js
export async function requestMarkdown({ gatewayUrl, url, pay }) {
  const taskBody = { input: { url } };
  const first = await fetch(new URL("/tasks", gatewayUrl), {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(taskBody)
  });

  if (first.status !== 402) {
    return first.json();
  }

  const paymentRequired = first.headers.get("payment-required");
  const challenge = paymentRequired
    ? JSON.parse(Buffer.from(paymentRequired, "base64").toString("utf8"))
    : await first.json();

  const paymentHeaders = await pay({ challenge, taskBody });
  const paid = await fetch(new URL("/tasks", gatewayUrl), {
    method: "POST",
    headers: {
      "content-type": "application/json",
      ...paymentHeaders
    },
    body: JSON.stringify(taskBody)
  });

  if (!paid.ok) {
    throw new Error(`d402 task failed with HTTP ${paid.status}: ${await paid.text()}`);
  }
  return paid.json();
}

The pay function is supplied by your app. It can use an x402 wallet, Solana wallet, Zero agent, or custom payment agent.

Gateway selection and failover

  • Keep an allowlist of trusted gateway URLs.
  • Probe GET /health and discovery before sending user traffic.
  • Prefer gateways with the desired capability, price, rail, latency, and availability.
  • Retry idempotently against the same gateway after payment to avoid replay ambiguity.
  • Fail over to another gateway before payment, or after proving the first gateway did not accept payment.
  • Store task ID, payment proof, PAYMENT-RESPONSE, validation receipt, settlement receipt, and evidence fields.