> ## Documentation Index
> Fetch the complete documentation index at: https://docs.toju.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Payments (x402)

> Store files autonomously and pay with USDC on Base — no human intervention required

## Overview

`@toju.network/x402` implements the [x402 protocol](https://x402.org) for autonomous storage payments. An agent instantiates `AgentClient` with a funded Base wallet, calls `store()`, and the SDK handles the full payment negotiation automatically — no wallet prompts, no manual signing steps.

The flow under the hood:

<Steps>
  <Step title="Send request">
    Agent sends `POST /upload/agent` with the file and storage parameters
  </Step>

  <Step title="Receive 402">
    Server responds with `402 Payment Required` and a price quote in USDC
  </Step>

  <Step title="Sign off-chain">
    SDK signs an EIP-3009 authorization (no on-chain transaction yet)
  </Step>

  <Step title="Retry with payment">
    SDK retries the request with the signed `X-PAYMENT` header attached
  </Step>

  <Step title="Facilitator settles">
    Coinbase's public facilitator verifies and settles the USDC transfer on Base
  </Step>

  <Step title="File stored">
    Server pins to IPFS and returns the CID
  </Step>
</Steps>

## Install

```shell theme={null}
pnpm add @toju.network/x402
```

## Quick start

```ts theme={null}
import { createAgentClient } from '@toju.network/x402'

const client = createAgentClient({
  privateKey: process.env.AGENT_PRIVATE_KEY as `0x${string}`,
  environment: 'mainnet',
})

const file = new File([fileBuffer], 'report.pdf', { type: 'application/pdf' })
const result = await client.store(file, { durationDays: 30 })

console.log(result.cid)       // bafy...
console.log(result.expiresAt) // 2025-06-01T00:00:00.000Z
```

Your agent's wallet needs USDC on Base to pay. At our rate of 3×10⁻¹² USD/byte/day, storing 1 MB for 30 days costs about **\$0.0001**.

## createAgentClient

```ts theme={null}
import { createAgentClient } from '@toju.network/x402'

const client = createAgentClient(options)
```

### Options

<ParamField path="privateKey" type="`0x${string}`" required>
  EVM private key for the agent's wallet. Must hold USDC on Base to pay for storage.
</ParamField>

<ParamField path="environment" type="'mainnet'" required>
  Target environment. Use `'mainnet'` for Base Mainnet with real USDC.
</ParamField>

## estimateStorageCost

Check the cost before uploading.

```ts theme={null}
const estimate = await client.estimateStorageCost(
  1_000_000, // sizeInBytes
  30          // durationDays
)

console.log(estimate.usdc) // '0.000090' (USDC, 6 decimal places)
console.log(estimate.usd)  // '0.00'
```

### Parameters

<ParamField path="sizeInBytes" type="number" required>
  Raw byte count of the file
</ParamField>

<ParamField path="durationDays" type="number" required>
  How long to keep the file on IPFS
</ParamField>

### Response

<ResponseField name="usdc" type="string">
  Cost in USDC, formatted to 6 decimal places (e.g. `'0.000090'`)
</ResponseField>

<ResponseField name="usd" type="string">
  Approximate USD cost, formatted to 2 decimal places
</ResponseField>

## store

Upload a file and pay autonomously via x402.

```ts theme={null}
const result = await client.store(file, { durationDays: 30 })
```

### Parameters

<ParamField path="file" type="File" required>
  The file to upload. Use the standard Web API `File` object — works in Node.js 20+ and all modern runtimes.
</ParamField>

<ParamField path="options.durationDays" type="number" required>
  Storage duration in days
</ParamField>

### Response

<ResponseField name="cid" type="string">
  IPFS content identifier for the uploaded file (e.g. `bafybei...`)
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO 8601 date string when the file will be removed from IPFS
</ResponseField>

<ResponseField name="fileName" type="string">
  Original file name
</ResponseField>

<ResponseField name="fileSize" type="number">
  File size in bytes
</ResponseField>

## USDC on Base

USDC uses 6 decimal places on all EVM chains (Circle standard). The SDK and server handle conversion automatically.

| Network      | USDC Contract                                |
| ------------ | -------------------------------------------- |
| Base Mainnet | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` |

<Info>
  Your agent wallet needs enough USDC to cover the storage cost, plus a small amount of ETH on Base for gas. Gas fees on Base are typically under \$0.001 per transaction.
</Info>

## AI Agent Integrations

`@toju.network/x402` works with any AI agent framework that can hold an EVM private key and execute TypeScript. The SDK handles all payment logic — you just need to wrap it as a tool or action.

### LangChain

This example shows how to integrate `@toju.network/x402` with LangChain. See the complete working example in the [x402-langchain repo](https://github.com/kaf-lamed-beyt/x402-langchain).

```ts theme={null}
import { createAgent, tool } from "langchain"
import * as z from "zod"
import { createAgentClient } from "@toju.network/x402"
import * as fs from "fs/promises"
import * as path from "path"

// Create the storage tool
const storeFileTool = tool(
  async ({ filePath, durationDays }) => {
    const client = createAgentClient({
      privateKey: process.env.AGENT_PRIVATE_KEY as `0x${string}`,
      environment: "sepolia",
    })
    const buffer = await fs.readFile(filePath)
    const file = new File([buffer], path.basename(filePath))
    const result = await client.store(file, { durationDays })
    return JSON.stringify(result)
  },
  {
    name: "store_file_ipfs",
    description: "Store a file on IPFS via decentralized storage and pay with USDC autonomously on Base.",
    schema: z.object({
      filePath: z.string().describe("Absolute path to the file to store"),
      durationDays: z.number().describe("How many days to store the file"),
    }),
  }
)

// Use with LangChain agent
const agent = createAgent({
  model: "openai:gpt-4o",
  tools: [storeFileTool],
})

const result = await agent.invoke({
  messages: [
    { role: "user", content: "Store ./test-data/sample.txt on IPFS for 30 days." },
  ],
})
```

This example demonstrates:

1. Agent receives natural language request
2. LLM decides to use the `store_file_ipfs` tool
3. Tool reads file from disk and pays via x402
4. File uploaded to IPFS, CID returned

### Langchain demo

[Autonomous AI Agent Storing Files on IPFS](https://youtu.be/7M0RPbH89HE)

## Related

<CardGroup cols={2}>
  <Card title="Pricing" icon="coins" href="/pricing">
    Storage rate and cost calculator
  </Card>

  <Card title="Upload (SOL)" icon="arrow-up" href="/sdk/deposit">
    Human wallet uploads with Solana
  </Card>

  <Card title="CID Computation" icon="hashtag" href="/concepts/cid-computation">
    How content identifiers work
  </Card>

  <Card title="Storage Payments" icon="credit-card" href="/concepts/storage-payments">
    Payment mechanics
  </Card>
</CardGroup>
