diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml new file mode 100644 index 000000000..80e5e53e5 --- /dev/null +++ b/.github/workflows/update-docs.yml @@ -0,0 +1,170 @@ +name: Update Docs + +on: + push: + branches: [main] + paths-ignore: + - 'docs/**' + - '**/*.test.ts' + - '**/*.test.js' + - '**/__tests__/**' + - '**/test/**' + - '**/tests/**' + - '**/typescript/site/*' + +jobs: + update-docs: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + env: + MINTLIFY_API_KEY: ${{ secrets.MINTLIFY_API_KEY }} + PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} + with: + script: | + const { owner, repo } = context.repo; + const projectId = process.env.PROJECT_ID; + const apiKey = process.env.MINTLIFY_API_KEY; + + if (!projectId || !apiKey) { + core.setFailed('Missing MINTLIFY_PROJECT_ID or MINTLIFY_API_KEY secrets'); + return; + } + + // Get SHAs from push payload + const beforeSha = context.payload.before; + const afterSha = context.payload.after; + + // Skip initial commits (no previous SHA to compare against) + if (/^0+$/.test(beforeSha)) { + core.notice('Initial commit detected. Skipping documentation update.'); + return; + } + + // Get changed files using GitHub Compare API (reliable for all merge types) + let uniqueFiles = []; + + try { + const compareResponse = await github.rest.repos.compareCommits({ + owner, + repo, + base: beforeSha, + head: afterSha + }); + + // Extract filenames, excluding test files + const testFilePattern = /\.(test|spec)\.(ts|js|tsx|jsx)$|__tests__|\/test\/|\/tests\//; + uniqueFiles = (compareResponse.data.files || []) + .map(f => f.filename) + .filter(f => !testFilePattern.test(f)); + + } catch (error) { + core.setFailed('Failed to compare commits: ' + error.message); + return; + } + + // Log changed files for debugging + console.log('Changed files (' + uniqueFiles.length + '):', uniqueFiles.slice(0, 10)); + if (uniqueFiles.length > 10) { + console.log('... and ' + (uniqueFiles.length - 10) + ' more'); + } + + // Skip if no non-test files changed + if (uniqueFiles.length === 0) { + core.notice('No documentation-relevant files changed. Skipping agent trigger.'); + return; + } + + // Get commit message from head commit + const headCommit = context.payload.head_commit; + const commitMessage = headCommit + ? '- ' + headCommit.message.split('\n')[0] + : '- No commit message available'; + + // Compare URL for reference + const compareUrl = context.payload.compare || ''; + + // Build the system prompt + const systemPrompt = [ + 'You are a documentation updater that ONLY updates docs directly related to specific code changes.', + '', + 'CRITICAL RULES:', + '- ONLY update documentation that is directly affected by the code changes provided', + '- DO NOT perform general documentation audits or sync operations', + '- DO NOT add documentation for unrelated features, ecosystem partners, or missing content', + '- If the code changes do not require documentation updates, report "No documentation updates needed" and exit without creating a PR', + '- Focus on the specific files and commits mentioned, not the entire repository state', + '- Read the AGENTS.md file in the docs directory for additional guidance' + ].join('\n'); + + // Build the user prompt + const userPrompt = [ + 'Review these SPECIFIC code changes and update documentation ONLY if directly related:', + '', + '**Repository:** ' + owner + '/' + repo, + '**Compare URL:** ' + compareUrl, + '', + '**Changed Files (' + uniqueFiles.length + '):**', + uniqueFiles.join('\n'), + '', + '**Commit Message:**', + commitMessage, + '', + 'IMPORTANT: Only update documentation that is directly impacted by these specific file changes. Do not add documentation for unrelated features or perform general audits. If these changes do not affect documentation, do NOT create a PR.' + ].join('\n'); + + const url = 'https://api.mintlify.com/v1/agent/' + projectId + '/job'; + const payload = { + branch: 'mintlify/docs-update-' + Date.now(), + messages: [ + { + role: 'system', + content: systemPrompt + }, + { + role: 'user', + content: userPrompt + } + ], + asDraft: false + }; + + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Authorization': 'Bearer ' + apiKey, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!response.ok) { + const errorText = await response.text(); + throw new Error('API request failed with status ' + response.status + ': ' + errorText); + } + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop() || ''; + for (const line of lines) { + if (line.trim()) { + console.log(line); + } + } + } + if (buffer.trim()) { + console.log(buffer); + } + + core.notice('Documentation update job triggered for ' + owner + '/' + repo); + } catch (error) { + core.setFailed('Failed to create documentation update job: ' + error.message); + } diff --git a/docs/AGENTS.md b/docs/AGENTS.md new file mode 100644 index 000000000..4f8ead708 --- /dev/null +++ b/docs/AGENTS.md @@ -0,0 +1,106 @@ +# Documentation Agent Instructions + +## Package Identity +- Mintlify documentation source for docs.x402.org +- MDX/Markdown files with `docs.json` as navigation configuration + +## Directory Structure +- `core-concepts/` — Protocol explanations (HTTP 402, client-server, facilitator, wallet) +- `getting-started/` — Quickstart guides for buyers and sellers (MDX files with tabs) +- `guides/` — How-to guides (MCP server, v1→v2 migration) +- `README.md` — Welcome/landing page +- `docs.json` — Mintlify navigation and configuration + +## Code-to-Doc Mapping +- Changes to `typescript/packages/core/src/` affect Core Concepts docs +- Changes to `typescript/packages/*/src/` affect SDK references and quickstart guides +- Changes to `python/x402/src/` affect Python SDK references +- Changes to `go/` affect Go SDK references +- Changes to facilitator endpoints affect quickstart guides +- Changes to `specs/` may require updates to core-concepts docs + +## Style Guidelines +- Use TypeScript for primary code examples (it's the reference SDK) +- Include error handling in all API examples +- Write for developers with 2-5 years experience +- Use MDX components (``, ``, ``, ``) for interactive content +- Show both success and error response examples for API endpoints +- Use real-world parameter values in examples (not foo/bar placeholders) + +## Conventions +- DO: Add new pages to `docs.json` navigation +- DO: Include code examples from real SDK files (not made-up snippets) +- DO: Link to relevant specs in `specs/` for protocol details +- DO: Use `` for multi-language code examples +- DO: Add frontmatter (title, description) to all pages +- DON'T: Duplicate protocol details from `specs/` — link instead +- DON'T: Add pages without updating `docs.json` +- **Git: Create PRs for review; NEVER commit directly to main** + +## Touch Points / Key Files +- `README.md` — Landing page +- `docs.json` — Navigation and configuration (MUST update when adding pages) +- `core-concepts/*.md` — Conceptual documentation +- `getting-started/*.mdx` — Quickstart guides (MDX for tab components) +- `guides/*.md` — How-to guides + +## File Extensions +- Use `.md` for standard markdown pages +- Use `.mdx` for pages with React components (Tabs, Cards, etc.) + +## Common Gotchas +- `docs.json` controls Mintlify navigation; pages not listed won't appear +- Images/diagrams go in project root `static/` directory +- Code examples should reference actual SDK file paths +- Links between pages should omit file extensions (e.g., `../core-concepts/http-402` not `../core-concepts/http-402.md`) + +## Pre-PR Checks +- All links work (no broken references) +- New pages added to `docs.json` navigation +- Code examples are from actual SDK files and compile +- Frontmatter present on all pages (title, description) +- MDX syntax is valid (run `mint dev` to verify) + +## Agent Behavior Rules (Automated Workflows) + +When triggered by GitHub Actions or other automated workflows: + +### DO +- ONLY update documentation directly related to the specific code changes +- Focus on the files and commits mentioned in the trigger +- Update SDK references if API signatures change +- Update quickstart guides if SDK usage patterns change +- Update core-concepts if protocol behavior changes + +### DO NOT +- Perform general documentation audits or sync operations +- Add documentation for ecosystem partners not mentioned in the code change +- Add documentation for features unrelated to the trigger +- Create PRs for trivial changes (comment removal, formatting, etc.) +- Sync ecosystem partner data from `typescript/site/app/ecosystem/` unless explicitly changed + +### Code-to-Doc Mapping (for automated updates) + +| Code Change | Doc Update Required | +|-------------|---------------------| +| `typescript/packages/*/src/*.ts` API changes | SDK reference, quickstart guides | +| `python/x402/src/*.py` API changes | Python SDK reference | +| `go/*.go` API changes | Go SDK reference | +| `java/src/**/*.java` API changes | Java SDK reference | +| `specs/*.md` protocol changes | core-concepts docs | +| Comment removal, formatting | NO update needed | +| Test file changes | NO update needed | +| Build/CI config changes | NO update needed | +| Ecosystem partner metadata only | NO update needed (site handles this) | + +### When to Skip (No PR) + +If the code changes are limited to: +- Removing or adding code comments +- Formatting/style changes (prettier, linting) +- Test files only (`*.test.ts`, `__tests__/`, etc.) +- CI/build configuration only (`.github/`, `turbo.json`, etc.) +- Dependency updates without API changes (`package.json`, `go.mod`, etc.) +- Ecosystem partner metadata (`typescript/site/app/ecosystem/partners-data/`) + +Then report "No documentation updates needed" and **do not create a PR**. diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md deleted file mode 100644 index da25f2e95..000000000 --- a/docs/SUMMARY.md +++ /dev/null @@ -1,26 +0,0 @@ -# Table of contents - -* [Welcome to x402](README.md) -* [x402 Landing Page](https://x402.org) -* [GitBook Repo (open for contributions)](https://github.com/coinbase/x402) -* [Vercel x402 Starter Template](https://vercel.com/templates/ai/x402-ai-starter) -* [FAQ](faq.md) - -## Getting Started - -* [Quickstart for Buyers](getting-started/quickstart-for-buyers.md) -* [Quickstart for Sellers](getting-started/quickstart-for-sellers.md) - -## Core Concepts - -* [HTTP 402](core-concepts/http-402.md) -* [Client / Server](core-concepts/client-server.md) -* [Facilitator](core-concepts/facilitator.md) -* [Wallet](core-concepts/wallet.md) -* [Networks & Token Support](core-concepts/network-and-token-support.md) -* [Bazaar (Discovery Layer)](core-concepts/bazaar-discovery-layer.md) - -## Guides - -* [MCP Server with x402](guides/mcp-server-with-x402.md) -* [Migration Guide: V1 to V2](guides/migration-v1-to-v2.md) diff --git a/docs/core-concepts/bazaar-discovery-layer.md b/docs/core-concepts/bazaar-discovery-layer.md deleted file mode 100644 index 7cb4b404c..000000000 --- a/docs/core-concepts/bazaar-discovery-layer.md +++ /dev/null @@ -1,426 +0,0 @@ -# Bazaar (Discovery Layer) - -The x402 Bazaar is the discovery layer for the x402 ecosystem - a machine-readable catalog that helps developers and AI agents find and integrate with x402-compatible API endpoints. Think of it as a search index for payable APIs, enabling the autonomous discovery and consumption of services. - -The x402 Bazaar is in early development. While our vision is to build the "Google for agentic endpoints," we're currently more like "Yahoo search" - functional but evolving. Features and APIs may change as we gather feedback and expand capabilities. - -### Overview - -The Bazaar solves a critical problem in the x402 ecosystem: **discoverability**. Without it, x402-compatible endpoints are like hidden stalls in a vast market. The Bazaar provides: - -* **For Buyers (API Consumers)**: Programmatically discover available x402-enabled services, understand their capabilities, pricing, and schemas -* **For Sellers (API Providers)**: Automatic visibility for your x402-enabled services to a global audience of developers and AI agents -* **For AI Agents**: Dynamic service discovery without pre-baked integrations - query, find, pay, and use - -### How It Works - -The Bazaar currently provides a simple `/list` endpoint that returns all x402-compatible services registered with the CDP facilitator. Services are automatically opted-in when they use the CDP facilitator and enable the bazaar extension, making discovery frictionless for sellers. - -**Note:** While a discovery layer is live today for the CDP Facilitator, the spec for the marketplace items is open and part of the x402 scheme, meaning any facilitator can create their own discovery layer. - -#### Basic Flow - -1. **Discovery**: Clients query the `/list` endpoint to find available services -2. **Selection**: Choose a service based on price, capabilities, and requirements -3. **Execution**: Use x402 to pay for and access the selected service -4. **No Manual Setup**: No API keys, no account creation, just discover and pay - -### API Reference - -#### List Endpoint - -Retrieve all available x402-compatible endpoints: - -```bash -GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources -``` - -**Note**: The recommended way to use this endpoint is to use the `useFacilitator` hook as described below. - -**Response Schema** - -Each endpoint in the list contains the following fields: - -```json -{ - "accepts": [ - { - "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", - "description": "", - "extra": { - "name": "USD Coin", - "version": "2" - }, - "maxAmountRequired": "200", - "maxTimeoutSeconds": 60, - "mimeType": "", - "network": "eip155:8453", - "outputSchema": { - "input": { - "method": "GET", - "type": "http" - }, - "output": null - }, - "payTo": "0xa2477E16dCB42E2AD80f03FE97D7F1a1646cd1c0", - "resource": "https://api.example.com/x402/weather", - "scheme": "exact" - } - ], - "lastUpdated": "2025-08-09T01:07:04.005Z", - "metadata": {}, - "resource": "https://api.example.com/x402/weather", - "type": "http", - "x402Version": 2 -} -``` - -### Quickstart for Buyers - -See the full example here for [Python](https://github.com/coinbase/x402/tree/main/examples/python/discovery) and [Node.js](https://github.com/coinbase/x402/tree/main/examples/typescript/discovery). - -#### Step 1: Discover Available Services - -Fetch the list of available x402 services using the facilitator client: - -{% tabs %} -{% tab title="TypeScript" %} -```typescript -import { HTTPFacilitatorClient } from "@x402/core/http"; -import { withBazaar } from "@x402/extensions"; - -// Create facilitator client with Bazaar discovery extension -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://x402.org/facilitator" -}); -const client = withBazaar(facilitatorClient); - -// Fetch all available services -const response = await client.extensions.discovery.listResources({ type: "http" }); - -// NOTE: in an MCP context, you can see the full list then decide which service to use - -// Find services under $0.10 -const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; -const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals) - -const affordableServices = response.items.filter(item => - item.accepts.find(paymentRequirements => - paymentRequirements.asset === usdcAsset && - Number(paymentRequirements.maxAmountRequired) < maxPrice - ) -); -``` -{% endtab %} - -{% tab title="Python" %} -```python -from x402.facilitator import FacilitatorClient - -# Set up facilitator client (defaults to https://x402.org/facilitator) -facilitator = FacilitatorClient() - -# Fetch all available services -response = await facilitator.list() - -# NOTE: in an MCP context, you can see the full list then decide which service to use - -# Find services under $0.10 -usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" -max_price = 100000 # $0.10 in USDC atomic units (6 decimals) - -affordable_services = [ - item - for item in response.items - if any( - payment_req.asset == usdc_asset - and int(payment_req.max_amount_required) < max_price - for payment_req in item.accepts - ) -] -``` -{% endtab %} -{% endtabs %} - -#### Step 2: Call a Discovered Service - -Once you've found a suitable service, use an x402 client to call it: - -{% tabs %} -{% tab title="TypeScript" %} -```typescript -import { wrapAxiosWithPayment, x402Client } from "@x402/axios"; -import { registerExactEvmScheme } from "@x402/evm/exact/client"; -import axios from "axios"; -import { privateKeyToAccount } from "viem/accounts"; - -// Set up your payment account -const account = privateKeyToAccount("0xYourPrivateKey"); -const client = new x402Client(); -registerExactEvmScheme(client, { signer: account }); - -// Select a service from discovery -const selectedService = affordableServices[0]; - -// Create a payment-enabled client for that service -const api = wrapAxiosWithPayment( - axios.create({ baseURL: selectedService.resource }), - client -); - -// Select the payment method of your choice -const selectedPaymentRequirements = selectedService.accepts[0]; -const inputSchema = selectedPaymentRequirements.outputSchema.input; - -// Build the request using the service's schema -const response = await api.request({ - method: inputSchema.method, - url: inputSchema.resource, - params: { location: "San Francisco" } // Based on inputSchema -}); - -console.log("Response data:", response.data); -``` -{% endtab %} - -{% tab title="Python" %} -```python -from x402.client import X402Client -from eth_account import Account - -# Set up your payment account -account = Account.from_key("0xYourPrivateKey") -client = X402Client(account) - -# Select a service from discovery -selected_service = affordable_services[0] - -# Select the payment method of your choice -selected_payment_requirements = selected_service.accepts[0] -input_schema = selected_payment_requirements.output_schema.input - -# Make the request -response = client.request( - method=input_schema.method, - url=input_schema.resource, - params={"location": "San Francisco"} # Based on input_schema -) - -print(f"Response data: {response}") -``` -{% endtab %} -{% endtabs %} - -### Quickstart for Sellers - -#### Automatic Listing with Bazaar Extension - -If your API uses the CDP facilitator for x402 payments, it's **automatically listed in the bazaar when you enable the bazaar extension with `discoverable: true`**. - -#### Adding Metadata - -To enhance your listing with descriptions and schemas, include them when setting up your x402 middleware. **You should include descriptions for each parameter to make it clear for agents to call your endpoints**: - -{% tabs %} -{% tab title="TypeScript" %} -```typescript -import { paymentMiddleware } from "@x402/express"; -import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; -import { registerExactEvmScheme } from "@x402/evm/exact/server"; -import { bazaarResourceServerExtension } from "@x402/extensions"; - -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://x402.org/facilitator" -}); -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); - -const routes = { - "GET /weather": { - price: "$0.001", - network: "eip155:8453", - resource: "0xYourAddress", - description: "Get current weather data for any location", - extensions: { - bazaar: { - discoverable: true, - inputSchema: { - queryParams: { - location: { - type: "string", - description: "City name or coordinates", - required: true - } - } - }, - outputSchema: { - type: "object", - properties: { - temperature: { type: "number" }, - conditions: { type: "string" }, - humidity: { type: "number" } - } - } - } - } - } -}; - -app.use(paymentMiddleware(routes, server)); -``` -{% endtab %} - -{% tab title="Python" %} -```python -from x402.middleware.fastapi import payment_middleware -from x402.facilitators import cdp_facilitator - -app.middleware("http")( - payment_middleware( - routes={ - "/weather": { - "price": "$0.001", - "network": "eip155:8453", - "resource": "0xYourAddress", - "description": "Get current weather data for any location", - "extensions": { - "bazaar": { - "discoverable": True, - "inputSchema": { - "queryParams": { - "location": { - "type": "string", - "description": "City name or coordinates", - "required": True - } - } - }, - "outputSchema": { - "type": "object", - "properties": { - "temperature": {"type": "number"}, - "conditions": {"type": "string"}, - "humidity": {"type": "number"} - } - } - } - } - } - }, - facilitator=cdp_facilitator - ) -) -``` -{% endtab %} - -{% tab title="Go" %} -```go -package main - -import ( - x402 "github.com/coinbase/x402/go" - "github.com/coinbase/x402/go/extensions/bazaar" - "github.com/coinbase/x402/go/extensions/types" - x402http "github.com/coinbase/x402/go/http" - ginmw "github.com/coinbase/x402/go/http/gin" - evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" - "github.com/gin-gonic/gin" -) - -func main() { - r := gin.Default() - - facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ - URL: "https://x402.org/facilitator", - }) - - // Create Bazaar Discovery Extension with input/output schemas - discoveryExtension, _ := bazaar.DeclareDiscoveryExtension( - bazaar.MethodGET, - map[string]interface{}{"location": "San Francisco"}, - types.JSONSchema{ - "properties": map[string]interface{}{ - "location": map[string]interface{}{ - "type": "string", - "description": "City name or coordinates", - }, - }, - "required": []string{"location"}, - }, - "", - &types.OutputConfig{ - Schema: types.JSONSchema{ - "properties": map[string]interface{}{ - "temperature": map[string]interface{}{"type": "number"}, - "conditions": map[string]interface{}{"type": "string"}, - "humidity": map[string]interface{}{"type": "number"}, - }, - }, - }, - ) - - routes := x402http.RoutesConfig{ - "GET /weather": { - Accepts: x402http.PaymentOptions{{ - Scheme: "exact", - PayTo: "0xYourAddress", - Price: "$0.001", - Network: x402.Network("eip155:8453"), - }}, - Description: "Get current weather data for any location", - Extensions: map[string]interface{}{ - types.BAZAAR: discoveryExtension, - }, - }, - } - - r.Use(ginmw.X402Payment(ginmw.Config{ - Routes: routes, - Facilitator: facilitatorClient, - Schemes: []ginmw.SchemeConfig{{ - Network: x402.Network("eip155:8453"), - Server: evm.NewExactEvmScheme(), - }}, - })) - - r.GET("/weather", func(c *gin.Context) { - location := c.DefaultQuery("location", "San Francisco") - c.JSON(200, gin.H{ - "location": location, - "temperature": 70, - "conditions": "sunny", - "humidity": 45, - }) - }) - - r.Run(":4021") -} -``` -{% endtab %} -{% endtabs %} - -### Coming Soon - -The x402 Bazaar is rapidly evolving, and your feedback helps us prioritize features. - -### Support - -* **GitHub**: [github.com/coinbase/x402](https://github.com/coinbase/x402) -* **Discord**: [Join #x402 channel](https://discord.com/invite/cdp) - -### FAQ - -**Q: How do I get my service listed?** -A: If you're using the CDP facilitator, your service is listed once you enable the bazaar extension with `discoverable: true`. - -**Q: How can I make endpoint calls more accurate?** -A: Include descriptions clearly stating what each parameter does and how to call your endpoint, but do so as succinctly as possible. - -**Q: How does pricing work?** -A: Listing is free. Services set their own prices per API call, paid via x402. - -**Q: What networks are supported?** -A: Currently Base (`eip155:8453`) and Base Sepolia (`eip155:84532`) with USDC payments. - -**Q: Can I list non-x402 services?** -A: No, only x402-compatible endpoints can be listed. See our [Quickstart for Sellers](../getting-started/quickstart-for-sellers.md) to make your API x402-compatible. diff --git a/docs/core-concepts/bazaar-discovery-layer.mdx b/docs/core-concepts/bazaar-discovery-layer.mdx new file mode 100644 index 000000000..1f25441f9 --- /dev/null +++ b/docs/core-concepts/bazaar-discovery-layer.mdx @@ -0,0 +1,425 @@ +--- +title: "Bazaar (Discovery Layer)" +description: "The x402 Bazaar is the discovery layer for the x402 ecosystem - a machine-readable catalog that helps developers and AI agents find and integrate with x402-compatible API endpoints." +--- + +Think of it as a search index for payable APIs, enabling the autonomous discovery and consumption of services. + +The x402 Bazaar is in early development. While our vision is to build the "Google for agentic endpoints," we're currently more like "Yahoo search" - functional but evolving. Features and APIs may change as we gather feedback and expand capabilities. + +### Overview + +The Bazaar solves a critical problem in the x402 ecosystem: **discoverability**. Without it, x402-compatible endpoints are like hidden stalls in a vast market. The Bazaar provides: + +* **For Buyers (API Consumers)**: Programmatically discover available x402-enabled services, understand their capabilities, pricing, and schemas +* **For Sellers (API Providers)**: Automatic visibility for your x402-enabled services to a global audience of developers and AI agents +* **For AI Agents**: Dynamic service discovery without pre-baked integrations - query, find, pay, and use + +### How It Works + +The Bazaar currently provides a simple `/list` endpoint that returns all x402-compatible services registered with the CDP facilitator. Services are automatically opted-in when they use the CDP facilitator and enable the bazaar extension, making discovery frictionless for sellers. + +**Note:** While a discovery layer is live today for the CDP Facilitator, the spec for the marketplace items is open and part of the x402 scheme, meaning any facilitator can create their own discovery layer. + +#### Basic Flow + +1. **Discovery**: Clients query the `/list` endpoint to find available services +2. **Selection**: Choose a service based on price, capabilities, and requirements +3. **Execution**: Use x402 to pay for and access the selected service +4. **No Manual Setup**: No API keys, no account creation, just discover and pay + +### API Reference + +#### List Endpoint + +Retrieve all available x402-compatible endpoints: + +```bash +GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources +``` + +**Note**: The recommended way to use this endpoint is to use the `useFacilitator` hook as described below. + +**Response Schema** + +Each endpoint in the list contains the following fields: + +```json +{ + "accepts": [ + { + "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", + "description": "", + "extra": { + "name": "USD Coin", + "version": "2" + }, + "maxAmountRequired": "200", + "maxTimeoutSeconds": 60, + "mimeType": "", + "network": "eip155:8453", + "outputSchema": { + "input": { + "method": "GET", + "type": "http" + }, + "output": null + }, + "payTo": "0xa2477E16dCB42E2AD80f03FE97D7F1a1646cd1c0", + "resource": "https://api.example.com/x402/weather", + "scheme": "exact" + } + ], + "lastUpdated": "2025-08-09T01:07:04.005Z", + "metadata": {}, + "resource": "https://api.example.com/x402/weather", + "type": "http", + "x402Version": 2 +} +``` + +### Quickstart for Buyers + +See the full example here for [Python](https://github.com/coinbase/x402/tree/main/examples/python/legacy/discovery). + +#### Step 1: Discover Available Services + +Fetch the list of available x402 services using the facilitator client: + + + + ```typescript + import { HTTPFacilitatorClient } from "@x402/core/http"; + import { withBazaar } from "@x402/extensions"; + + // Create facilitator client with Bazaar discovery extension + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://x402.org/facilitator" + }); + const client = withBazaar(facilitatorClient); + + // Fetch all available services + const response = await client.extensions.discovery.listResources({ type: "http" }); + + // NOTE: in an MCP context, you can see the full list then decide which service to use + + // Find services under $0.10 + const usdcAsset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; + const maxPrice = 100000; // $0.10 in USDC atomic units (6 decimals) + + const affordableServices = response.items.filter(item => + item.accepts.find(paymentRequirements => + paymentRequirements.asset === usdcAsset && + Number(paymentRequirements.maxAmountRequired) < maxPrice + ) + ); + ``` + + + ```python + from x402.facilitator import FacilitatorClient + + # Set up facilitator client (defaults to https://x402.org/facilitator) + facilitator = FacilitatorClient() + + # Fetch all available services + response = await facilitator.list() + + # NOTE: in an MCP context, you can see the full list then decide which service to use + + # Find services under $0.10 + usdc_asset = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" + max_price = 100000 # $0.10 in USDC atomic units (6 decimals) + + affordable_services = [ + item + for item in response.items + if any( + payment_req.asset == usdc_asset + and int(payment_req.max_amount_required) < max_price + for payment_req in item.accepts + ) + ] + ``` + + + +#### Step 2: Call a Discovered Service + +Once you've found a suitable service, use an x402 client to call it: + + + + ```typescript + import { wrapAxiosWithPayment, x402Client } from "@x402/axios"; + import { registerExactEvmScheme } from "@x402/evm/exact/client"; + import axios from "axios"; + import { privateKeyToAccount } from "viem/accounts"; + + // Set up your payment account + const account = privateKeyToAccount("0xYourPrivateKey"); + const client = new x402Client(); + registerExactEvmScheme(client, { signer: account }); + + // Select a service from discovery + const selectedService = affordableServices[0]; + + // Create a payment-enabled client for that service + const api = wrapAxiosWithPayment( + axios.create({ baseURL: selectedService.resource }), + client + ); + + // Select the payment method of your choice + const selectedPaymentRequirements = selectedService.accepts[0]; + const inputSchema = selectedPaymentRequirements.outputSchema.input; + + // Build the request using the service's schema + const response = await api.request({ + method: inputSchema.method, + url: inputSchema.resource, + params: { location: "San Francisco" } // Based on inputSchema + }); + + console.log("Response data:", response.data); + ``` + + + ```python + from x402.client import X402Client + from eth_account import Account + + # Set up your payment account + account = Account.from_key("0xYourPrivateKey") + client = X402Client(account) + + # Select a service from discovery + selected_service = affordable_services[0] + + # Select the payment method of your choice + selected_payment_requirements = selected_service.accepts[0] + input_schema = selected_payment_requirements.output_schema.input + + # Make the request + response = client.request( + method=input_schema.method, + url=input_schema.resource, + params={"location": "San Francisco"} # Based on input_schema + ) + + print(f"Response data: {response}") + ``` + + + +### Quickstart for Sellers + +#### Automatic Listing with Bazaar Extension + +If your API uses the CDP facilitator for x402 payments, it's **automatically listed in the bazaar when you enable the bazaar extension with `discoverable: true`**. + +#### Adding Metadata + +To enhance your listing with descriptions and schemas, include them when setting up your x402 middleware. **You should include descriptions for each parameter to make it clear for agents to call your endpoints**: + + + + ```typescript + import { paymentMiddleware } from "@x402/express"; + import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + import { bazaarResourceServerExtension } from "@x402/extensions"; + + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://x402.org/facilitator" + }); + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); + + const routes = { + "GET /weather": { + price: "$0.001", + network: "eip155:8453", + resource: "0xYourAddress", + description: "Get current weather data for any location", + extensions: { + bazaar: { + discoverable: true, + inputSchema: { + queryParams: { + location: { + type: "string", + description: "City name or coordinates", + required: true + } + } + }, + outputSchema: { + type: "object", + properties: { + temperature: { type: "number" }, + conditions: { type: "string" }, + humidity: { type: "number" } + } + } + } + } + } + }; + + app.use(paymentMiddleware(routes, server)); + ``` + + + ```python + from x402.middleware.fastapi import payment_middleware + from x402.facilitators import cdp_facilitator + + app.middleware("http")( + payment_middleware( + routes={ + "/weather": { + "price": "$0.001", + "network": "eip155:8453", + "resource": "0xYourAddress", + "description": "Get current weather data for any location", + "extensions": { + "bazaar": { + "discoverable": True, + "inputSchema": { + "queryParams": { + "location": { + "type": "string", + "description": "City name or coordinates", + "required": True + } + } + }, + "outputSchema": { + "type": "object", + "properties": { + "temperature": {"type": "number"}, + "conditions": {"type": "string"}, + "humidity": {"type": "number"} + } + } + } + } + } + }, + facilitator=cdp_facilitator + ) + ) + ``` + + + ```go + package main + + import ( + x402 "github.com/coinbase/x402/go" + "github.com/coinbase/x402/go/extensions/bazaar" + "github.com/coinbase/x402/go/extensions/types" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + "github.com/gin-gonic/gin" + ) + + func main() { + r := gin.Default() + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://x402.org/facilitator", + }) + + // Create Bazaar Discovery Extension with input/output schemas + discoveryExtension, _ := bazaar.DeclareDiscoveryExtension( + bazaar.MethodGET, + map[string]interface{}{"location": "San Francisco"}, + types.JSONSchema{ + "properties": map[string]interface{}{ + "location": map[string]interface{}{ + "type": "string", + "description": "City name or coordinates", + }, + }, + "required": []string{"location"}, + }, + "", + &types.OutputConfig{ + Schema: types.JSONSchema{ + "properties": map[string]interface{}{ + "temperature": map[string]interface{}{"type": "number"}, + "conditions": map[string]interface{}{"type": "string"}, + "humidity": map[string]interface{}{"type": "number"}, + }, + }, + }, + ) + + routes := x402http.RoutesConfig{ + "GET /weather": { + Accepts: x402http.PaymentOptions{{ + Scheme: "exact", + PayTo: "0xYourAddress", + Price: "$0.001", + Network: x402.Network("eip155:8453"), + }}, + Description: "Get current weather data for any location", + Extensions: map[string]interface{}{ + types.BAZAAR: discoveryExtension, + }, + }, + } + + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: routes, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{{ + Network: x402.Network("eip155:8453"), + Server: evm.NewExactEvmScheme(), + }}, + })) + + r.GET("/weather", func(c *gin.Context) { + location := c.DefaultQuery("location", "San Francisco") + c.JSON(200, gin.H{ + "location": location, + "temperature": 70, + "conditions": "sunny", + "humidity": 45, + }) + }) + + r.Run(":4021") + } + ``` + + + +### Coming Soon + +The x402 Bazaar is rapidly evolving, and your feedback helps us prioritize features. + +### Support + +* **GitHub**: [github.com/coinbase/x402](https://github.com/coinbase/x402) +* **Discord**: [Join #x402 channel](https://discord.com/invite/cdp) + +### FAQ + +**Q: How do I get my service listed?** +A: If you're using the CDP facilitator, your service is listed once you enable the bazaar extension with `discoverable: true`. + +**Q: How can I make endpoint calls more accurate?** +A: Include descriptions clearly stating what each parameter does and how to call your endpoint, but do so as succinctly as possible. + +**Q: How does pricing work?** +A: Listing is free. Services set their own prices per API call, paid via x402. + +**Q: What networks are supported?** +A: Currently Base (`eip155:8453`) and Base Sepolia (`eip155:84532`) with USDC payments. + +**Q: Can I list non-x402 services?** +A: No, only x402-compatible endpoints can be listed. See our [Quickstart for Sellers](/getting-started/quickstart-for-sellers) to make your API x402-compatible. diff --git a/docs/core-concepts/client-server.md b/docs/core-concepts/client-server.md index 5dcd8a83d..739a98b34 100644 --- a/docs/core-concepts/client-server.md +++ b/docs/core-concepts/client-server.md @@ -1,6 +1,7 @@ -# Client / Server - -This page explains the roles and responsibilities of the **client** and **server** in the x402 protocol. +--- +title: "Client / Server" +description: "This page explains the roles and responsibilities of the **client** and **server** in the x402 protocol." +--- Understanding these roles is essential to designing, building, or integrating services that use x402 for programmatic payments. @@ -69,5 +70,5 @@ This interaction is stateless, HTTP-native, and compatible with both human appli Next, explore: -* [Facilitator](facilitator.md) — how servers verify and settle payments -* [HTTP 402](http-402.md) — how servers communicate payment requirements to clients +* [Facilitator](/core-concepts/facilitator) — how servers verify and settle payments +* [HTTP 402](/core-concepts/http-402) — how servers communicate payment requirements to clients diff --git a/docs/core-concepts/facilitator.md b/docs/core-concepts/facilitator.md index 316c94304..89de34586 100644 --- a/docs/core-concepts/facilitator.md +++ b/docs/core-concepts/facilitator.md @@ -1,6 +1,7 @@ -# Facilitator - -This page explains the role of the **facilitator** in the x402 protocol. +--- +title: "Facilitator" +description: "This page explains the role of the **facilitator** in the x402 protocol." +--- The facilitator is an optional but recommended service that simplifies the process of verifying and settling payments between clients (buyers) and servers (sellers). @@ -61,5 +62,5 @@ The facilitator acts as an independent verification and settlement layer within Next, explore: -* [Client / Server ](client-server.md)— understand the roles and responsibilities of clients and servers -* [HTTP 402](http-402.md) — understand how payment requirements are communicated to clients +* [Client / Server](/core-concepts/client-server) — understand the roles and responsibilities of clients and servers +* [HTTP 402](/core-concepts/http-402) — understand how payment requirements are communicated to clients diff --git a/docs/core-concepts/http-402.md b/docs/core-concepts/http-402.md index 51c246f72..97f26d17b 100644 --- a/docs/core-concepts/http-402.md +++ b/docs/core-concepts/http-402.md @@ -1,6 +1,7 @@ -# HTTP 402 - -For decades, HTTP 402 Payment Required has been reserved for future use. x402 unlocks it, and [absolves the internet of its original sin](https://economyofbits.substack.com/p/marc-andreessens-original-sin). +--- +title: "HTTP 402" +description: "For decades, HTTP 402 Payment Required has been reserved for future use. x402 unlocks it, and [absolves the internet of its original sin](https://economyofbits.substack.com/p/marc-andreessens-original-sin)." +--- ### What is HTTP 402? diff --git a/docs/core-concepts/network-and-token-support.md b/docs/core-concepts/network-and-token-support.mdx similarity index 80% rename from docs/core-concepts/network-and-token-support.md rename to docs/core-concepts/network-and-token-support.mdx index dd65108ef..afa06c2ce 100644 --- a/docs/core-concepts/network-and-token-support.md +++ b/docs/core-concepts/network-and-token-support.mdx @@ -1,6 +1,7 @@ -# Network & Token Support - -This page explains which blockchain networks and tokens are supported by x402, and how to extend support to additional networks. +--- +title: "Networks & Token Support" +description: "This page explains which blockchain networks and tokens are supported by x402, and how to extend support to additional networks." +--- ## V2 Network Identifiers (CAIP-2) @@ -132,11 +133,11 @@ The EIP-3009 standard is essential for x402 because it enables: | Facilitator | Networks Supported (CAIP-2) | Production Ready | Requirements | | --------------- | --------------------------------------- | ---------------- | --------------- | -| x402.org | `eip155:84532`, `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | ❌ Testnet only | None | -| CDP Facilitator | `eip155:8453`, `eip155:84532`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`, `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | ✅ | CDP API keys | -| x402.rs | `eip155:84532`, `eip155:8453`, xdc | ✅ | None | -| PayAI Facilitator | solana, solana-devnet, base, base-sepolia, polygon, polygon-amoy, avalanche, avalanche-fuji, sei, sei-testnet, peaq, iotex | ✅ | None | -| Self-hosted | Any EVM network (CAIP-2 format) | ✅ | Technical setup | +| x402.org | `eip155:84532`, `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | Testnet only | None | +| CDP Facilitator | `eip155:8453`, `eip155:84532`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`, `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | Yes | CDP API keys | +| x402.rs | `eip155:84532`, `eip155:8453`, xdc | Yes | None | +| PayAI Facilitator | solana, solana-devnet, base, base-sepolia, polygon, polygon-amoy, avalanche, avalanche-fuji, sei, sei-testnet, peaq, iotex | Yes | None | +| Self-hosted | Any EVM network (CAIP-2 format) | Yes | Technical setup | **Note**: On EVM networks, facilitators support any EIP-3009 compatible token; on Solana, facilitators support any SPL/Token-2022 token. @@ -148,51 +149,50 @@ x402 V2 uses dynamic network registration - you can support any EVM network with In V2, networks are supported through the registration pattern using CAIP-2 identifiers. No source code changes are required: -{% tabs %} -{% tab title="TypeScript" %} -```typescript -import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; -import { registerExactEvmScheme } from "@x402/evm/exact/server"; - -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://your-facilitator.com" // Facilitator that supports your network -}); - -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); // Registers wildcard support for all EVM chains - -// Now use any CAIP-2 network identifier in your routes: -const routes = { - "GET /api/data": { - accepts: [{ - scheme: "exact", - price: "$0.001", - network: "eip155:43114", // Avalanche mainnet - payTo: "0xYourAddress", - }], - }, -}; -``` -{% endtab %} - -{% tab title="Go" %} -```go -import ( - x402http "github.com/coinbase/x402/go/http" - evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" -) - -facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ - URL: "https://your-facilitator.com", -}) - -// Register EVM scheme - supports any CAIP-2 EVM network -schemes := []ginmw.SchemeConfig{ - {Network: x402.Network("eip155:43114"), Server: evm.NewExactEvmScheme()}, // Avalanche -} -``` -{% endtab %} -{% endtabs %} + + + ```typescript + import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://your-facilitator.com" // Facilitator that supports your network + }); + + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); // Registers wildcard support for all EVM chains + + // Now use any CAIP-2 network identifier in your routes: + const routes = { + "GET /api/data": { + accepts: [{ + scheme: "exact", + price: "$0.001", + network: "eip155:43114", // Avalanche mainnet + payTo: "0xYourAddress", + }], + }, + }; + ``` + + + ```go + import ( + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + ) + + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://your-facilitator.com", + }) + + // Register EVM scheme - supports any CAIP-2 EVM network + schemes := []ginmw.SchemeConfig{ + {Network: x402.Network("eip155:43114"), Server: evm.NewExactEvmScheme()}, // Avalanche + } + ``` + + **Key Points:** - Use CAIP-2 format: `eip155:` for any EVM network @@ -241,7 +241,7 @@ Key takeaways: Next, explore: -* Quickstart for Sellers — Start accepting payments on supported networks -* Core Concepts — Learn how x402 works under the hood -* Facilitator — Understand the role of facilitators -* MCP Server — Set up AI agents to use x402 payments +* [Quickstart for Sellers](/getting-started/quickstart-for-sellers) — Start accepting payments on supported networks +* [Core Concepts](/core-concepts/http-402) — Learn how x402 works under the hood +* [Facilitator](/core-concepts/facilitator) — Understand the role of facilitators +* [MCP Server](/guides/mcp-server-with-x402) — Set up AI agents to use x402 payments diff --git a/docs/core-concepts/wallet.md b/docs/core-concepts/wallet.md index 90995bd94..971559977 100644 --- a/docs/core-concepts/wallet.md +++ b/docs/core-concepts/wallet.md @@ -1,6 +1,7 @@ -# Wallet - -This page explains the role of the **wallet** in the x402 protocol. +--- +title: "Wallet" +description: "This page explains the role of the **wallet** in the x402 protocol." +--- In x402, a wallet is both a payment mechanism and a form of unique identity for buyers and sellers. Wallet addresses are used to send, receive, and verify payments, while also serving as identifiers within the protocol. diff --git a/docs/docs.json b/docs/docs.json new file mode 100644 index 000000000..670a7b316 --- /dev/null +++ b/docs/docs.json @@ -0,0 +1,80 @@ +{ + "$schema": "https://mintlify.com/docs.json", + "theme": "maple", + "name": "x402", + "colors": { + "primary": "#0052FF", + "light": "#4D7CFF", + "dark": "#0039B3" + }, + + "seo": { + "metatags": { + "canonical": "https://docs.x402.org" + } + }, + "navigation": { + "global": { + "anchors": [ + { + "anchor": "x402.org", + "icon": "globe", + "href": "https://x402.org" + }, + { + "anchor": "GitHub", + "icon": "github", + "href": "https://github.com/coinbase/x402" + }, + { + "anchor": "Discord", + "icon": "discord", + "href": "https://discord.gg/cdp" + }, + { + "anchor": "Vercel Starter", + "icon": "triangle", + "href": "https://vercel.com/templates/ai/x402-ai-starter" + } + ] + }, + "groups": [ + { + "group": "Welcome", + "pages": ["introduction", "faq"] + }, + { + "group": "Getting Started", + "pages": [ + "getting-started/quickstart-for-buyers", + "getting-started/quickstart-for-sellers" + ] + }, + { + "group": "Core Concepts", + "pages": [ + "core-concepts/http-402", + "core-concepts/client-server", + "core-concepts/facilitator", + "core-concepts/wallet", + "core-concepts/network-and-token-support", + "core-concepts/bazaar-discovery-layer" + ] + }, + { + "group": "Guides", + "pages": [ + "guides/mcp-server-with-x402", + "guides/migration-v1-to-v2" + ] + } + ] + }, + "feedback": { + "thumbsRating": true, + "suggestEdit": true + }, + "search": { + "prompt": "Search x402 docs..." + } +} diff --git a/docs/faq.md b/docs/faq.md index ce9fc3095..0f3167ee3 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,4 +1,6 @@ -# FAQ +--- +title: "FAQ" +--- ### General diff --git a/docs/getting-started/quickstart-for-buyers.md b/docs/getting-started/quickstart-for-buyers.md deleted file mode 100644 index bc4bf8cbd..000000000 --- a/docs/getting-started/quickstart-for-buyers.md +++ /dev/null @@ -1,373 +0,0 @@ -# Quickstart for Buyers - -This guide walks you through how to use **x402** to interact with services that require payment. By the end of this guide, you will be able to programmatically discover payment requirements, complete a payment, and access a paid resource. - -### Prerequisites - -Before you begin, ensure you have: - -* A crypto wallet with USDC (any EVM-compatible wallet) -* [Node.js](https://nodejs.org/en) and npm, [Go](https://go.dev/), or Python and pip -* A service that requires payment via x402 - -**Note**\ -We have pre-configured [examples available in our repo](https://github.com/coinbase/x402/tree/main/examples), including examples for fetch, Axios, Go, and MCP. - -### 1. Install Dependencies - -{% tabs %} -{% tab title="Node.js" %} -Install the x402 client packages: - -```bash -# For fetch-based clients -npm install @x402/fetch @x402/evm - -# For axios-based clients -npm install @x402/axios @x402/evm - -# For Solana support, also add: -npm install @x402/svm -``` -{% endtab %} - -{% tab title="Go" %} -Add the x402 Go module to your project: - -```bash -go get github.com/coinbase/x402/go -``` -{% endtab %} - -{% tab title="Python" %} -Install the [x402 package](https://pypi.org/project/x402/) - -```bash -pip install x402 -``` - -**Note:** Python SDK currently uses v1 patterns. For v2 support, use TypeScript or Go. -{% endtab %} -{% endtabs %} - -### 2. Create a Wallet Signer - -{% tabs %} -{% tab title="Node.js (viem)" %} -Install the required package: - -```bash -npm install viem -``` - -Then instantiate the wallet signer: - -```typescript -import { privateKeyToAccount } from "viem/accounts"; - -// Create a signer from private key (use environment variable) -const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); -``` -{% endtab %} - -{% tab title="Go" %} -```go -import ( - evmsigners "github.com/coinbase/x402/go/signers/evm" -) - -// Load private key from environment -evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) -if err != nil { - log.Fatal(err) -} -``` -{% endtab %} - -{% tab title="Python (eth-account)" %} -Install the required package: - -```bash -pip install eth_account -``` - -Then instantiate the wallet account: - -```python -from eth_account import Account - -account = Account.from_key(os.getenv("PRIVATE_KEY")) -``` -{% endtab %} -{% endtabs %} - -#### Solana (SVM) - -Use [SolanaKit](https://www.solanakit.com/) to instantiate a signer: - -```typescript -import { createKeyPairSignerFromBytes } from "@solana/kit"; -import { base58 } from "@scure/base"; - -// 64-byte base58 secret key (private + public) -const svmSigner = await createKeyPairSignerFromBytes( - base58.decode(process.env.SOLANA_PRIVATE_KEY!) -); -``` - -### 3. Make Paid Requests Automatically - -{% tabs %} -{% tab title="Fetch" %} -**@x402/fetch** extends the native `fetch` API to handle 402 responses and payment headers for you. [Full example here](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/fetch) - -```typescript -import { wrapFetchWithPayment } from "@x402/fetch"; -import { x402Client, x402HTTPClient } from "@x402/core/client"; -import { registerExactEvmScheme } from "@x402/evm/exact/client"; -import { privateKeyToAccount } from "viem/accounts"; - -// Create signer -const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); - -// Create x402 client and register EVM scheme -const client = new x402Client(); -registerExactEvmScheme(client, { signer }); - -// Wrap fetch with payment handling -const fetchWithPayment = wrapFetchWithPayment(fetch, client); - -// Make request - payment is handled automatically -const response = await fetchWithPayment("https://api.example.com/paid-endpoint", { - method: "GET", -}); - -const data = await response.json(); -console.log("Response:", data); - -// Get payment receipt from response headers -if (response.ok) { - const httpClient = new x402HTTPClient(client); - const paymentResponse = httpClient.getPaymentSettleResponse( - (name) => response.headers.get(name) - ); - console.log("Payment settled:", paymentResponse); -} -``` -{% endtab %} - -{% tab title="Axios" %} -**@x402/axios** adds a payment interceptor to Axios, so your requests are retried with payment headers automatically. [Full example here](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/axios) - -```typescript -import { x402Client, wrapAxiosWithPayment, x402HTTPClient } from "@x402/axios"; -import { registerExactEvmScheme } from "@x402/evm/exact/client"; -import { privateKeyToAccount } from "viem/accounts"; -import axios from "axios"; - -// Create signer -const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); - -// Create x402 client and register EVM scheme -const client = new x402Client(); -registerExactEvmScheme(client, { signer }); - -// Create an Axios instance with payment handling -const api = wrapAxiosWithPayment( - axios.create({ baseURL: "https://api.example.com" }), - client, -); - -// Make request - payment is handled automatically -const response = await api.get("/paid-endpoint"); -console.log("Response:", response.data); - -// Get payment receipt -const httpClient = new x402HTTPClient(client); -const paymentResponse = httpClient.getPaymentSettleResponse( - (name) => response.headers[name.toLowerCase()] -); -console.log("Payment settled:", paymentResponse); -``` -{% endtab %} - -{% tab title="Go" %} -[Full example here](https://github.com/coinbase/x402/tree/main/examples/go/clients/http) - -```go -package main - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "os" - "time" - - x402 "github.com/coinbase/x402/go" - x402http "github.com/coinbase/x402/go/http" - evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" - evmsigners "github.com/coinbase/x402/go/signers/evm" -) - -func main() { - url := "http://localhost:4021/weather" - - // Create EVM signer - evmSigner, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) - - // Create x402 client and register EVM scheme - x402Client := x402.Newx402Client(). - Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) - - // Wrap HTTP client with payment handling - httpClient := x402http.WrapHTTPClientWithPayment( - http.DefaultClient, - x402http.Newx402HTTPClient(x402Client), - ) - - // Make request - payment is handled automatically - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) - resp, err := httpClient.Do(req) - if err != nil { - fmt.Printf("Request failed: %v\n", err) - return - } - defer resp.Body.Close() - - // Read response - var data map[string]interface{} - json.NewDecoder(resp.Body).Decode(&data) - fmt.Printf("Response: %+v\n", data) - - // Check payment response header - paymentHeader := resp.Header.Get("PAYMENT-RESPONSE") - if paymentHeader != "" { - fmt.Println("Payment settled successfully!") - } -} -``` -{% endtab %} - -{% tab title="Python" %} -**Note:** Python SDK currently uses v1 patterns. - -You can use either `httpx` or `Requests` to automatically handle 402 Payment Required responses. - -[Full HTTPX example](https://github.com/coinbase/x402/tree/main/examples/python/clients/httpx) | [Full Requests example](https://github.com/coinbase/x402/tree/main/examples/python/clients/requests) - -```python -from x402.clients.httpx import x402HttpxClient -from eth_account import Account - -# Create wallet account -account = Account.from_key(os.getenv("PRIVATE_KEY")) - -# Create client and make request -async with x402HttpxClient(account=account, base_url="https://api.example.com") as client: - response = await client.get("/protected-endpoint") - print(await response.aread()) -``` -{% endtab %} -{% endtabs %} - -### Multi-Network Client Setup - -You can register multiple payment schemes to handle different networks: - -```typescript -import { wrapFetchWithPayment } from "@x402/fetch"; -import { x402Client } from "@x402/core/client"; -import { registerExactEvmScheme } from "@x402/evm/exact/client"; -import { registerExactSvmScheme } from "@x402/svm/exact/client"; -import { privateKeyToAccount } from "viem/accounts"; -import { createKeyPairSignerFromBytes } from "@solana/kit"; -import { base58 } from "@scure/base"; - -// Create signers -const evmSigner = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); -const svmSigner = await createKeyPairSignerFromBytes( - base58.decode(process.env.SOLANA_PRIVATE_KEY!) -); - -// Create client with multiple schemes -const client = new x402Client(); -registerExactEvmScheme(client, { signer: evmSigner }); -registerExactSvmScheme(client, { signer: svmSigner }); - -const fetchWithPayment = wrapFetchWithPayment(fetch, client); - -// Now handles both EVM and Solana networks automatically! -``` - -### 4. Discover Available Services (Optional) - -Instead of hardcoding endpoints, you can use the x402 Bazaar to dynamically discover available services. This is especially powerful for building autonomous agents. - -```typescript -// Fetch available services from the Bazaar API -const response = await fetch( - "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources" -); -const services = await response.json(); - -// Filter services by criteria -const affordableServices = services.items.filter((item) => - item.accepts.some((req) => Number(req.amount) < 100000) // Under $0.10 -); - -console.log("Available services:", affordableServices); -``` - -Learn more about service discovery in the [Bazaar documentation](../core-concepts/bazaar-discovery-layer.md). - -### 5. Error Handling - -Clients will throw errors if: - -* No scheme is registered for the required network -* The request configuration is missing -* A payment has already been attempted for the request -* There is an error creating the payment header - -Common error handling: - -```typescript -try { - const response = await fetchWithPayment(url, { method: "GET" }); - // Handle success -} catch (error) { - if (error.message.includes("No scheme registered")) { - console.error("Network not supported - register the appropriate scheme"); - } else if (error.message.includes("Payment already attempted")) { - console.error("Payment failed on retry"); - } else { - console.error("Request failed:", error); - } -} -``` - -### Summary - -* Install x402 client packages (`@x402/fetch` or `@x402/axios`) and mechanism packages (`@x402/evm`, `@x402/svm`) -* Create a wallet signer -* Create an `x402Client` and register payment schemes -* Use the provided wrapper/interceptor to make paid API requests -* (Optional) Use the x402 Bazaar to discover services dynamically -* Payment flows are handled automatically for you - -*** - -**References:** - -* [@x402/fetch on npm](https://www.npmjs.com/package/@x402/fetch) -* [@x402/axios on npm](https://www.npmjs.com/package/@x402/axios) -* [@x402/evm on npm](https://www.npmjs.com/package/@x402/evm) -* [x402 Go module](https://github.com/coinbase/x402/tree/main/go) -* [x402 Bazaar documentation](../core-concepts/bazaar-discovery-layer.md) - Discover available services - -For questions or support, join our [Discord](https://discord.gg/invite/cdp). diff --git a/docs/getting-started/quickstart-for-buyers.mdx b/docs/getting-started/quickstart-for-buyers.mdx new file mode 100644 index 000000000..9a50d5552 --- /dev/null +++ b/docs/getting-started/quickstart-for-buyers.mdx @@ -0,0 +1,367 @@ +--- +title: "Quickstart for Buyers" +description: "This guide walks you through how to use **x402** to interact with services that require payment. By the end of this guide, you will be able to programmatically discover payment requirements, complete a payment, and access a paid resource." +--- + +### Prerequisites + +Before you begin, ensure you have: + +* A crypto wallet with USDC (any EVM-compatible wallet) +* [Node.js](https://nodejs.org/en) and npm, [Go](https://go.dev/), or Python and pip +* A service that requires payment via x402 + +**Note**\ +We have pre-configured [examples available in our repo](https://github.com/coinbase/x402/tree/main/examples), including examples for fetch, Axios, Go, and MCP. + +### 1. Install Dependencies + + + + Install the x402 client packages: + + ```bash + # For fetch-based clients + npm install @x402/fetch @x402/evm + + # For axios-based clients + npm install @x402/axios @x402/evm + + # For Solana support, also add: + npm install @x402/svm + ``` + + + Add the x402 Go module to your project: + + ```bash + go get github.com/coinbase/x402/go + ``` + + + Install the [x402 package](https://pypi.org/project/x402/) + + ```bash + pip install x402 + ``` + + **Note:** Python SDK currently uses v1 patterns. For v2 support, use TypeScript or Go. + + + +### 2. Create a Wallet Signer + + + + Install the required package: + + ```bash + npm install viem + ``` + + Then instantiate the wallet signer: + + ```typescript + import { privateKeyToAccount } from "viem/accounts"; + + // Create a signer from private key (use environment variable) + const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); + ``` + + + ```go + import ( + evmsigners "github.com/coinbase/x402/go/signers/evm" + ) + + // Load private key from environment + evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) + if err != nil { + log.Fatal(err) + } + ``` + + + Install the required package: + + ```bash + pip install eth_account + ``` + + Then instantiate the wallet account: + + ```python + from eth_account import Account + + account = Account.from_key(os.getenv("PRIVATE_KEY")) + ``` + + + +#### Solana (SVM) + +Use [SolanaKit](https://www.solanakit.com/) to instantiate a signer: + +```typescript +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +// 64-byte base58 secret key (private + public) +const svmSigner = await createKeyPairSignerFromBytes( + base58.decode(process.env.SOLANA_PRIVATE_KEY!) +); +``` + +### 3. Make Paid Requests Automatically + + + + **@x402/fetch** extends the native `fetch` API to handle 402 responses and payment headers for you. [Full example here](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/fetch) + + ```typescript + import { wrapFetchWithPayment } from "@x402/fetch"; + import { x402Client, x402HTTPClient } from "@x402/core/client"; + import { registerExactEvmScheme } from "@x402/evm/exact/client"; + import { privateKeyToAccount } from "viem/accounts"; + + // Create signer + const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); + + // Create x402 client and register EVM scheme + const client = new x402Client(); + registerExactEvmScheme(client, { signer }); + + // Wrap fetch with payment handling + const fetchWithPayment = wrapFetchWithPayment(fetch, client); + + // Make request - payment is handled automatically + const response = await fetchWithPayment("https://api.example.com/paid-endpoint", { + method: "GET", + }); + + const data = await response.json(); + console.log("Response:", data); + + // Get payment receipt from response headers + if (response.ok) { + const httpClient = new x402HTTPClient(client); + const paymentResponse = httpClient.getPaymentSettleResponse( + (name) => response.headers.get(name) + ); + console.log("Payment settled:", paymentResponse); + } + ``` + + + **@x402/axios** adds a payment interceptor to Axios, so your requests are retried with payment headers automatically. [Full example here](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/axios) + + ```typescript + import { x402Client, wrapAxiosWithPayment, x402HTTPClient } from "@x402/axios"; + import { registerExactEvmScheme } from "@x402/evm/exact/client"; + import { privateKeyToAccount } from "viem/accounts"; + import axios from "axios"; + + // Create signer + const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); + + // Create x402 client and register EVM scheme + const client = new x402Client(); + registerExactEvmScheme(client, { signer }); + + // Create an Axios instance with payment handling + const api = wrapAxiosWithPayment( + axios.create({ baseURL: "https://api.example.com" }), + client, + ); + + // Make request - payment is handled automatically + const response = await api.get("/paid-endpoint"); + console.log("Response:", response.data); + + // Get payment receipt + const httpClient = new x402HTTPClient(client); + const paymentResponse = httpClient.getPaymentSettleResponse( + (name) => response.headers[name.toLowerCase()] + ); + console.log("Payment settled:", paymentResponse); + ``` + + + [Full example here](https://github.com/coinbase/x402/tree/main/examples/go/clients/http) + + ```go + package main + + import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/client" + evmsigners "github.com/coinbase/x402/go/signers/evm" + ) + + func main() { + url := "http://localhost:4021/weather" + + // Create EVM signer + evmSigner, _ := evmsigners.NewClientSignerFromPrivateKey(os.Getenv("EVM_PRIVATE_KEY")) + + // Create x402 client and register EVM scheme + x402Client := x402.Newx402Client(). + Register("eip155:*", evm.NewExactEvmScheme(evmSigner)) + + // Wrap HTTP client with payment handling + httpClient := x402http.WrapHTTPClientWithPayment( + http.DefaultClient, + x402http.Newx402HTTPClient(x402Client), + ) + + // Make request - payment is handled automatically + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) + resp, err := httpClient.Do(req) + if err != nil { + fmt.Printf("Request failed: %v\n", err) + return + } + defer resp.Body.Close() + + // Read response + var data map[string]interface{} + json.NewDecoder(resp.Body).Decode(&data) + fmt.Printf("Response: %+v\n", data) + + // Check payment response header + paymentHeader := resp.Header.Get("PAYMENT-RESPONSE") + if paymentHeader != "" { + fmt.Println("Payment settled successfully!") + } + } + ``` + + + **Note:** Python SDK currently uses v1 patterns. + + You can use either `httpx` or `Requests` to automatically handle 402 Payment Required responses. + + [Full HTTPX example](https://github.com/coinbase/x402/tree/main/examples/python/clients/httpx) | [Full Requests example](https://github.com/coinbase/x402/tree/main/examples/python/clients/requests) + + ```python + from x402.clients.httpx import x402HttpxClient + from eth_account import Account + + # Create wallet account + account = Account.from_key(os.getenv("PRIVATE_KEY")) + + # Create client and make request + async with x402HttpxClient(account=account, base_url="https://api.example.com") as client: + response = await client.get("/protected-endpoint") + print(await response.aread()) + ``` + + + +### Multi-Network Client Setup + +You can register multiple payment schemes to handle different networks: + +```typescript +import { wrapFetchWithPayment } from "@x402/fetch"; +import { x402Client } from "@x402/core/client"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { registerExactSvmScheme } from "@x402/svm/exact/client"; +import { privateKeyToAccount } from "viem/accounts"; +import { createKeyPairSignerFromBytes } from "@solana/kit"; +import { base58 } from "@scure/base"; + +// Create signers +const evmSigner = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`); +const svmSigner = await createKeyPairSignerFromBytes( + base58.decode(process.env.SOLANA_PRIVATE_KEY!) +); + +// Create client with multiple schemes +const client = new x402Client(); +registerExactEvmScheme(client, { signer: evmSigner }); +registerExactSvmScheme(client, { signer: svmSigner }); + +const fetchWithPayment = wrapFetchWithPayment(fetch, client); + +// Now handles both EVM and Solana networks automatically! +``` + +### 4. Discover Available Services (Optional) + +Instead of hardcoding endpoints, you can use the x402 Bazaar to dynamically discover available services. This is especially powerful for building autonomous agents. + +```typescript +// Fetch available services from the Bazaar API +const response = await fetch( + "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources" +); +const services = await response.json(); + +// Filter services by criteria +const affordableServices = services.items.filter((item) => + item.accepts.some((req) => Number(req.amount) < 100000) // Under $0.10 +); + +console.log("Available services:", affordableServices); +``` + +Learn more about service discovery in the [Bazaar documentation](/core-concepts/bazaar-discovery-layer). + +### 5. Error Handling + +Clients will throw errors if: + +* No scheme is registered for the required network +* The request configuration is missing +* A payment has already been attempted for the request +* There is an error creating the payment header + +Common error handling: + +```typescript +try { + const response = await fetchWithPayment(url, { method: "GET" }); + // Handle success +} catch (error) { + if (error.message.includes("No scheme registered")) { + console.error("Network not supported - register the appropriate scheme"); + } else if (error.message.includes("Payment already attempted")) { + console.error("Payment failed on retry"); + } else { + console.error("Request failed:", error); + } +} +``` + +### Summary + +* Install x402 client packages (`@x402/fetch` or `@x402/axios`) and mechanism packages (`@x402/evm`, `@x402/svm`) +* Create a wallet signer +* Create an `x402Client` and register payment schemes +* Use the provided wrapper/interceptor to make paid API requests +* (Optional) Use the x402 Bazaar to discover services dynamically +* Payment flows are handled automatically for you + +*** + +**References:** + +* [@x402/fetch on npm](https://www.npmjs.com/package/@x402/fetch) +* [@x402/axios on npm](https://www.npmjs.com/package/@x402/axios) +* [@x402/evm on npm](https://www.npmjs.com/package/@x402/evm) +* [x402 Go module](https://github.com/coinbase/x402/tree/main/go) +* [x402 Bazaar documentation](/core-concepts/bazaar-discovery-layer) - Discover available services + +For questions or support, join our [Discord](https://discord.gg/cdp). diff --git a/docs/getting-started/quickstart-for-sellers.md b/docs/getting-started/quickstart-for-sellers.md deleted file mode 100644 index 86ec1295f..000000000 --- a/docs/getting-started/quickstart-for-sellers.md +++ /dev/null @@ -1,578 +0,0 @@ -# Quickstart for Sellers - -This guide walks you through integrating with **x402** to enable payments for your API or service. By the end, your API will be able to charge buyers and AI agents for access. - -**Note:** This quickstart begins with testnet configuration for safe testing. When you're ready for production, see [Running on Mainnet](#running-on-mainnet) for the simple changes needed to accept real payments on Base (EVM) and Solana networks. - -### Prerequisites - -Before you begin, ensure you have: - -* A crypto wallet to receive funds (any EVM-compatible wallet) -* [Node.js](https://nodejs.org/en) and npm, [Go](https://go.dev/), or Python and pip installed -* An existing API or server - -**Note:** The Python SDK is currently under development for x402 v2. For immediate v2 support, use TypeScript or Go. - -**Note**\ -We have pre-configured examples available in our repo for both [Node.js](https://github.com/coinbase/x402/tree/main/examples/typescript/servers) and [Go](https://github.com/coinbase/x402/tree/main/examples/go/servers). We also have an [advanced example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/advanced) that shows how to use the x402 SDKs to build a more complex payment flow. - -### 1. Install Dependencies - -{% tabs %} -{% tab title="Express" %} -Install the [x402 Express middleware package](https://www.npmjs.com/package/@x402/express). - -```bash -npm install @x402/express @x402/core @x402/evm -``` -{% endtab %} - -{% tab title="Next.js" %} -Install the [x402 Next.js middleware package](https://www.npmjs.com/package/@x402/next). - -```bash -npm install @x402/next @x402/core @x402/evm -``` -{% endtab %} - -{% tab title="Hono" %} -Install the [x402 Hono middleware package](https://www.npmjs.com/package/@x402/hono). - -```bash -npm install @x402/hono @x402/core @x402/evm -``` -{% endtab %} - -{% tab title="Go" %} -Add the x402 Go module to your project: - -```bash -go get github.com/coinbase/x402/go -``` -{% endtab %} - -{% tab title="FastAPI" %} -[Install the x402 Python package](https://pypi.org/project/x402/) - -```bash -pip install x402 -``` - -**Note:** Python SDK currently uses v1 patterns. -{% endtab %} - -{% tab title="Flask" %} -[Install the x402 Python package](https://pypi.org/project/x402/) - -```bash -pip install x402 -``` - -**Note:** Python SDK currently uses v1 patterns. -{% endtab %} -{% endtabs %} - -### 2. Add Payment Middleware - -Integrate the payment middleware into your application. You will need to provide: - -* The Facilitator URL or facilitator client. For testing, use `https://x402.org/facilitator` which works on Base Sepolia and Solana devnet. - * For mainnet setup, see [Running on Mainnet](#running-on-mainnet) -* The routes you want to protect. -* Your receiving wallet address. - -{% tabs %} -{% tab title="Express" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/express). - -```typescript -import express from "express"; -import { paymentMiddleware } from "@x402/express"; -import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; -import { registerExactEvmScheme } from "@x402/evm/exact/server"; - -const app = express(); - -// Your receiving wallet address -const payTo = "0xYourAddress"; - -// Create facilitator client (testnet) -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://x402.org/facilitator" -}); - -// Create resource server and register EVM scheme -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); - -app.use( - paymentMiddleware( - { - "GET /weather": { - accepts: [ - { - scheme: "exact", - price: "$0.001", // USDC amount in dollars - network: "eip155:84532", // Base Sepolia (CAIP-2 format) - payTo, - }, - ], - description: "Get current weather data for any location", - mimeType: "application/json", - }, - }, - server, - ), -); - -// Implement your route -app.get("/weather", (req, res) => { - res.send({ - report: { - weather: "sunny", - temperature: 70, - }, - }); -}); - -app.listen(4021, () => { - console.log(`Server listening at http://localhost:4021`); -}); -``` -{% endtab %} - -{% tab title="Next.js" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/fullstack/next). - -```typescript -// middleware.ts -import { paymentProxy } from "@x402/next"; -import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; -import { registerExactEvmScheme } from "@x402/evm/exact/server"; - -const payTo = "0xYourAddress"; - -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://x402.org/facilitator" -}); - -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); - -export const middleware = paymentProxy( - { - "/api/protected": { - accepts: [ - { - scheme: "exact", - price: "$0.01", - network: "eip155:84532", - payTo, - }, - ], - description: "Access to protected content", - mimeType: "application/json", - }, - }, - server, -); - -export const config = { - matcher: ["/api/protected/:path*"], -}; -``` -{% endtab %} - -{% tab title="Hono" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/hono). - -```typescript -import { Hono } from "hono"; -import { serve } from "@hono/node-server"; -import { paymentMiddleware } from "@x402/hono"; -import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; -import { registerExactEvmScheme } from "@x402/evm/exact/server"; - -const app = new Hono(); -const payTo = "0xYourAddress"; - -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://x402.org/facilitator" -}); - -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); - -app.use( - paymentMiddleware( - { - "/protected-route": { - accepts: [ - { - scheme: "exact", - price: "$0.10", - network: "eip155:84532", - payTo, - }, - ], - description: "Access to premium content", - mimeType: "application/json", - }, - }, - server, - ), -); - -app.get("/protected-route", (c) => { - return c.json({ message: "This content is behind a paywall" }); -}); - -serve({ fetch: app.fetch, port: 3000 }); -``` -{% endtab %} - -{% tab title="Go (Gin)" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/go/servers/gin). - -```go -package main - -import ( - "net/http" - "time" - - x402 "github.com/coinbase/x402/go" - x402http "github.com/coinbase/x402/go/http" - ginmw "github.com/coinbase/x402/go/http/gin" - evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" - "github.com/gin-gonic/gin" -) - -func main() { - payTo := "0xYourAddress" - network := x402.Network("eip155:84532") // Base Sepolia (CAIP-2 format) - - r := gin.Default() - - // Create facilitator client - facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ - URL: "https://x402.org/facilitator", - }) - - // Apply x402 payment middleware - r.Use(ginmw.X402Payment(ginmw.Config{ - Routes: x402http.RoutesConfig{ - "GET /weather": { - Accepts: x402http.PaymentOptions{ - { - Scheme: "exact", - PayTo: payTo, - Price: "$0.001", - Network: network, - }, - }, - Description: "Get weather data for a city", - MimeType: "application/json", - }, - }, - Facilitator: facilitatorClient, - Schemes: []ginmw.SchemeConfig{ - {Network: network, Server: evm.NewExactEvmScheme()}, - }, - SyncFacilitatorOnStart: true, - Timeout: 30 * time.Second, - })) - - // Protected endpoint - r.GET("/weather", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "weather": "sunny", - "temperature": 70, - }) - }) - - r.Run(":4021") -} -``` -{% endtab %} - -{% tab title="FastAPI" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/python/legacy). - -**Note:** Python SDK currently uses v1 patterns with string network identifiers. - -```python -from typing import Any, Dict -from fastapi import FastAPI -from x402.fastapi.middleware import require_payment - -app = FastAPI() - -# Apply payment middleware to specific routes -app.middleware("http")( - require_payment( - path="/weather", - price="$0.001", - pay_to_address="0xYourAddress", - network="base-sepolia", # v1 string identifier - ) -) - -@app.get("/weather") -async def get_weather() -> Dict[str, Any]: - return { - "report": { - "weather": "sunny", - "temperature": 70, - } - } -``` -{% endtab %} - -{% tab title="Flask" %} -Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/python/legacy). - -**Note:** Python SDK currently uses v1 patterns with string network identifiers. - -```python -from flask import Flask -from x402.flask.middleware import PaymentMiddleware - -app = Flask(__name__) - -# Initialize payment middleware -payment_middleware = PaymentMiddleware(app) - -# Apply payment middleware to specific routes -payment_middleware.add( - path="/weather", - price="$0.001", - pay_to_address="0xYourAddress", - network="base-sepolia", # v1 string identifier -) -``` -{% endtab %} -{% endtabs %} - -**Route Configuration Interface:** - -```typescript -interface RouteConfig { - accepts: Array<{ - scheme: string; // Payment scheme (e.g., "exact") - price: string; // Price in dollars (e.g., "$0.01") - network: string; // Network in CAIP-2 format (e.g., "eip155:84532") - payTo: string; // Your wallet address - }>; - description?: string; // Description of the resource - mimeType?: string; // MIME type of the response - extensions?: object; // Optional extensions (e.g., Bazaar) -} -``` - -When a request is made to these routes without payment, your server will respond with the HTTP 402 Payment Required code and payment instructions. - -### 3. Test Your Integration - -To verify: - -1. Make a request to your endpoint (e.g., `curl http://localhost:4021/weather`). -2. The server responds with a 402 Payment Required, including payment instructions in the `PAYMENT-REQUIRED` header. -3. Complete the payment using a compatible client, wallet, or automated agent. This typically involves signing a payment payload, which is handled by the client SDK detailed in the [Quickstart for Buyers](quickstart-for-buyers.md). -4. Retry the request, this time including the `PAYMENT-SIGNATURE` header containing the cryptographic proof of payment. -5. The server verifies the payment via the facilitator and, if valid, returns your actual API response (e.g., `{ "data": "Your paid API response." }`). - -### 4. Enhance Discovery with Metadata (Recommended) - -When using the CDP facilitator, your endpoints can be listed in the [x402 Bazaar](../core-concepts/bazaar-discovery-layer.md), our discovery layer that helps buyers and AI agents find services. To enable discovery: - -```typescript -{ - "GET /weather": { - accepts: [ - { - scheme: "exact", - price: "$0.001", - network: "eip155:8453", - payTo: "0xYourAddress", - }, - ], - description: "Get real-time weather data including temperature, conditions, and humidity", - mimeType: "application/json", - extensions: { - bazaar: { - discoverable: true, - category: "weather", - tags: ["forecast", "real-time"], - }, - }, - }, -} -``` - -Learn more about the discovery layer in the [Bazaar documentation](../core-concepts/bazaar-discovery-layer.md). - -### 5. Error Handling - -* If you run into trouble, check out the examples in the [repo](https://github.com/coinbase/x402/tree/main/examples) for more context and full code. -* Run `npm install` or `go mod tidy` to install dependencies - ---- - -## Running on Mainnet - -Once you've tested your integration on testnet, you're ready to accept real payments on mainnet. - -### 1. Update the Facilitator URL - -For mainnet, use the CDP facilitator: - -{% tabs %} -{% tab title="Node.js" %} -```typescript -const facilitatorClient = new HTTPFacilitatorClient({ - url: "https://api.cdp.coinbase.com/platform/v2/x402" -}); -``` -{% endtab %} - -{% tab title="Go" %} -```go -facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ - URL: "https://api.cdp.coinbase.com/platform/v2/x402", -}) -``` -{% endtab %} -{% endtabs %} - -### 2. Update Your Network Identifier - -Change from testnet to mainnet network identifiers: - -{% tabs %} -{% tab title="Base Mainnet" %} -```typescript -// Testnet → Mainnet -network: "eip155:8453", // Base mainnet (was eip155:84532) -``` -{% endtab %} - -{% tab title="Solana Mainnet" %} -```typescript -// Testnet → Mainnet -network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet - -// For Solana, use a Solana wallet address (base58 format) -payTo: "YourSolanaWalletAddress", -``` -{% endtab %} - -{% tab title="Multi-Network" %} -```typescript -// Support multiple networks on the same endpoint -{ - "GET /weather": { - accepts: [ - { - scheme: "exact", - price: "$0.001", - network: "eip155:8453", // Base mainnet - payTo: "0xYourEvmAddress", - }, - { - scheme: "exact", - price: "$0.001", - network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet - payTo: "YourSolanaAddress", - }, - ], - description: "Weather data", - }, -} -``` -{% endtab %} -{% endtabs %} - -### 3. Register Multiple Schemes (Multi-Network) - -For multi-network support, register both EVM and SVM schemes: - -{% tabs %} -{% tab title="Node.js" %} -```typescript -import { registerExactEvmScheme } from "@x402/evm/exact/server"; -import { registerExactSvmScheme } from "@x402/svm/exact/server"; - -const server = new x402ResourceServer(facilitatorClient); -registerExactEvmScheme(server); -registerExactSvmScheme(server); -``` -{% endtab %} - -{% tab title="Go" %} -```go -import ( - evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" - svm "github.com/coinbase/x402/go/mechanisms/svm/exact/server" -) - -r.Use(ginmw.X402Payment(ginmw.Config{ - // ... - Schemes: []ginmw.SchemeConfig{ - {Network: x402.Network("eip155:8453"), Server: evm.NewExactEvmScheme()}, - {Network: x402.Network("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"), Server: svm.NewExactSvmScheme()}, - }, -})) -``` -{% endtab %} -{% endtabs %} - -### 4. Update Your Wallet - -Make sure your receiving wallet address is a real mainnet address where you want to receive USDC payments. - -### 5. Test with Real Payments - -Before going live: -1. Test with small amounts first -2. Verify payments are arriving in your wallet -3. Monitor the facilitator for any issues - -**Warning:** Mainnet transactions involve real money. Always test thoroughly on testnet first and start with small amounts on mainnet. - ---- - -## Network Identifiers (CAIP-2) - -x402 v2 uses [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format for network identifiers: - -| Network | CAIP-2 Identifier | -|---------|-------------------| -| Base Mainnet | `eip155:8453` | -| Base Sepolia | `eip155:84532` | -| Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | -| Solana Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | - -See [Network Support](../core-concepts/network-and-token-support.md) for the full list. - ---- - -### Next Steps - -* Looking for something more advanced? Check out the [Advanced Example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/advanced) -* Get started as a [buyer](quickstart-for-buyers.md) -* Learn about the [Bazaar discovery layer](../core-concepts/bazaar-discovery-layer.md) - -For questions or support, join our [Discord](https://discord.gg/invite/cdp). - -### Summary - -This quickstart covered: - -* Installing the x402 SDK and relevant middleware -* Adding payment middleware to your API and configuring it -* Testing your integration -* Deploying to mainnet with CAIP-2 network identifiers - -Your API is now ready to accept crypto payments through x402. diff --git a/docs/getting-started/quickstart-for-sellers.mdx b/docs/getting-started/quickstart-for-sellers.mdx new file mode 100644 index 000000000..393b0a6b8 --- /dev/null +++ b/docs/getting-started/quickstart-for-sellers.mdx @@ -0,0 +1,565 @@ +--- +title: "Quickstart for Sellers" +description: "This guide walks you through integrating with **x402** to enable payments for your API or service. By the end, your API will be able to charge buyers and AI agents for access." +--- + +**Note:** This quickstart begins with testnet configuration for safe testing. When you're ready for production, see [Running on Mainnet](#running-on-mainnet) for the simple changes needed to accept real payments on Base (EVM) and Solana networks. + +### Prerequisites + +Before you begin, ensure you have: + +* A crypto wallet to receive funds (any EVM-compatible wallet) +* [Node.js](https://nodejs.org/en) and npm, [Go](https://go.dev/), or Python and pip installed +* An existing API or server + +**Note:** The Python SDK is currently under development for x402 v2. For immediate v2 support, use TypeScript or Go. + +**Note**\ +We have pre-configured examples available in our repo for both [Node.js](https://github.com/coinbase/x402/tree/main/examples/typescript/servers) and [Go](https://github.com/coinbase/x402/tree/main/examples/go/servers). We also have an [advanced example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/advanced) that shows how to use the x402 SDKs to build a more complex payment flow. + +### 1. Install Dependencies + + + + Install the [x402 Express middleware package](https://www.npmjs.com/package/@x402/express). + + ```bash + npm install @x402/express @x402/core @x402/evm + ``` + + + Install the [x402 Next.js middleware package](https://www.npmjs.com/package/@x402/next). + + ```bash + npm install @x402/next @x402/core @x402/evm + ``` + + + Install the [x402 Hono middleware package](https://www.npmjs.com/package/@x402/hono). + + ```bash + npm install @x402/hono @x402/core @x402/evm + ``` + + + Add the x402 Go module to your project: + + ```bash + go get github.com/coinbase/x402/go + ``` + + + [Install the x402 Python package](https://pypi.org/project/x402/) + + ```bash + pip install x402 + ``` + + **Note:** Python SDK currently uses v1 patterns. + + + [Install the x402 Python package](https://pypi.org/project/x402/) + + ```bash + pip install x402 + ``` + + **Note:** Python SDK currently uses v1 patterns. + + + +### 2. Add Payment Middleware + +Integrate the payment middleware into your application. You will need to provide: + +* The Facilitator URL or facilitator client. For testing, use `https://x402.org/facilitator` which works on Base Sepolia and Solana devnet. + * For mainnet setup, see [Running on Mainnet](#running-on-mainnet) +* The routes you want to protect. +* Your receiving wallet address. + + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/express). + + ```typescript + import express from "express"; + import { paymentMiddleware } from "@x402/express"; + import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + + const app = express(); + + // Your receiving wallet address + const payTo = "0xYourAddress"; + + // Create facilitator client (testnet) + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://x402.org/facilitator" + }); + + // Create resource server and register EVM scheme + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); + + app.use( + paymentMiddleware( + { + "GET /weather": { + accepts: [ + { + scheme: "exact", + price: "$0.001", // USDC amount in dollars + network: "eip155:84532", // Base Sepolia (CAIP-2 format) + payTo, + }, + ], + description: "Get current weather data for any location", + mimeType: "application/json", + }, + }, + server, + ), + ); + + // Implement your route + app.get("/weather", (req, res) => { + res.send({ + report: { + weather: "sunny", + temperature: 70, + }, + }); + }); + + app.listen(4021, () => { + console.log(`Server listening at http://localhost:4021`); + }); + ``` + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/fullstack/next). + + ```typescript + // middleware.ts + import { paymentProxy } from "@x402/next"; + import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + + const payTo = "0xYourAddress"; + + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://x402.org/facilitator" + }); + + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); + + export const middleware = paymentProxy( + { + "/api/protected": { + accepts: [ + { + scheme: "exact", + price: "$0.01", + network: "eip155:84532", + payTo, + }, + ], + description: "Access to protected content", + mimeType: "application/json", + }, + }, + server, + ); + + export const config = { + matcher: ["/api/protected/:path*"], + }; + ``` + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/hono). + + ```typescript + import { Hono } from "hono"; + import { serve } from "@hono/node-server"; + import { paymentMiddleware } from "@x402/hono"; + import { x402ResourceServer, HTTPFacilitatorClient } from "@x402/core/server"; + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + + const app = new Hono(); + const payTo = "0xYourAddress"; + + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://x402.org/facilitator" + }); + + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); + + app.use( + paymentMiddleware( + { + "/protected-route": { + accepts: [ + { + scheme: "exact", + price: "$0.10", + network: "eip155:84532", + payTo, + }, + ], + description: "Access to premium content", + mimeType: "application/json", + }, + }, + server, + ), + ); + + app.get("/protected-route", (c) => { + return c.json({ message: "This content is behind a paywall" }); + }); + + serve({ fetch: app.fetch, port: 3000 }); + ``` + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/go/servers/gin). + + ```go + package main + + import ( + "net/http" + "time" + + x402 "github.com/coinbase/x402/go" + x402http "github.com/coinbase/x402/go/http" + ginmw "github.com/coinbase/x402/go/http/gin" + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + "github.com/gin-gonic/gin" + ) + + func main() { + payTo := "0xYourAddress" + network := x402.Network("eip155:84532") // Base Sepolia (CAIP-2 format) + + r := gin.Default() + + // Create facilitator client + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://x402.org/facilitator", + }) + + // Apply x402 payment middleware + r.Use(ginmw.X402Payment(ginmw.Config{ + Routes: x402http.RoutesConfig{ + "GET /weather": { + Accepts: x402http.PaymentOptions{ + { + Scheme: "exact", + PayTo: payTo, + Price: "$0.001", + Network: network, + }, + }, + Description: "Get weather data for a city", + MimeType: "application/json", + }, + }, + Facilitator: facilitatorClient, + Schemes: []ginmw.SchemeConfig{ + {Network: network, Server: evm.NewExactEvmScheme()}, + }, + SyncFacilitatorOnStart: true, + Timeout: 30 * time.Second, + })) + + // Protected endpoint + r.GET("/weather", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{ + "weather": "sunny", + "temperature": 70, + }) + }) + + r.Run(":4021") + } + ``` + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/python/legacy). + + **Note:** Python SDK currently uses v1 patterns with string network identifiers. + + ```python + from typing import Any, Dict + from fastapi import FastAPI + from x402.fastapi.middleware import require_payment + + app = FastAPI() + + # Apply payment middleware to specific routes + app.middleware("http")( + require_payment( + path="/weather", + price="$0.001", + pay_to_address="0xYourAddress", + network="base-sepolia", # v1 string identifier + ) + ) + + @app.get("/weather") + async def get_weather() -> Dict[str, Any]: + return { + "report": { + "weather": "sunny", + "temperature": 70, + } + } + ``` + + + Full example in the repo [here](https://github.com/coinbase/x402/tree/main/examples/python/legacy). + + **Note:** Python SDK currently uses v1 patterns with string network identifiers. + + ```python + from flask import Flask + from x402.flask.middleware import PaymentMiddleware + + app = Flask(__name__) + + # Initialize payment middleware + payment_middleware = PaymentMiddleware(app) + + # Apply payment middleware to specific routes + payment_middleware.add( + path="/weather", + price="$0.001", + pay_to_address="0xYourAddress", + network="base-sepolia", # v1 string identifier + ) + ``` + + + +**Route Configuration Interface:** + +```typescript +interface RouteConfig { + accepts: Array<{ + scheme: string; // Payment scheme (e.g., "exact") + price: string; // Price in dollars (e.g., "$0.01") + network: string; // Network in CAIP-2 format (e.g., "eip155:84532") + payTo: string; // Your wallet address + }>; + description?: string; // Description of the resource + mimeType?: string; // MIME type of the response + extensions?: object; // Optional extensions (e.g., Bazaar) +} +``` + +When a request is made to these routes without payment, your server will respond with the HTTP 402 Payment Required code and payment instructions. + +### 3. Test Your Integration + +To verify: + +1. Make a request to your endpoint (e.g., `curl http://localhost:4021/weather`). +2. The server responds with a 402 Payment Required, including payment instructions in the `PAYMENT-REQUIRED` header. +3. Complete the payment using a compatible client, wallet, or automated agent. This typically involves signing a payment payload, which is handled by the client SDK detailed in the [Quickstart for Buyers](/getting-started/quickstart-for-buyers). +4. Retry the request, this time including the `PAYMENT-SIGNATURE` header containing the cryptographic proof of payment. +5. The server verifies the payment via the facilitator and, if valid, returns your actual API response (e.g., `{ "data": "Your paid API response." }`). + +### 4. Enhance Discovery with Metadata (Recommended) + +When using the CDP facilitator, your endpoints can be listed in the [x402 Bazaar](/core-concepts/bazaar-discovery-layer), our discovery layer that helps buyers and AI agents find services. To enable discovery: + +```typescript +{ + "GET /weather": { + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:8453", + payTo: "0xYourAddress", + }, + ], + description: "Get real-time weather data including temperature, conditions, and humidity", + mimeType: "application/json", + extensions: { + bazaar: { + discoverable: true, + category: "weather", + tags: ["forecast", "real-time"], + }, + }, + }, +} +``` + +Learn more about the discovery layer in the [Bazaar documentation](/core-concepts/bazaar-discovery-layer). + +### 5. Error Handling + +* If you run into trouble, check out the examples in the [repo](https://github.com/coinbase/x402/tree/main/examples) for more context and full code. +* Run `npm install` or `go mod tidy` to install dependencies + +--- + +## Running on Mainnet + +Once you've tested your integration on testnet, you're ready to accept real payments on mainnet. + +### 1. Update the Facilitator URL + +For mainnet, use the CDP facilitator: + + + + ```typescript + const facilitatorClient = new HTTPFacilitatorClient({ + url: "https://api.cdp.coinbase.com/platform/v2/x402" + }); + ``` + + + ```go + facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{ + URL: "https://api.cdp.coinbase.com/platform/v2/x402", + }) + ``` + + + +### 2. Update Your Network Identifier + +Change from testnet to mainnet network identifiers: + + + + ```typescript + // Testnet → Mainnet + network: "eip155:8453", // Base mainnet (was eip155:84532) + ``` + + + ```typescript + // Testnet → Mainnet + network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet + + // For Solana, use a Solana wallet address (base58 format) + payTo: "YourSolanaWalletAddress", + ``` + + + ```typescript + // Support multiple networks on the same endpoint + { + "GET /weather": { + accepts: [ + { + scheme: "exact", + price: "$0.001", + network: "eip155:8453", // Base mainnet + payTo: "0xYourEvmAddress", + }, + { + scheme: "exact", + price: "$0.001", + network: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", // Solana mainnet + payTo: "YourSolanaAddress", + }, + ], + description: "Weather data", + }, + } + ``` + + + +### 3. Register Multiple Schemes (Multi-Network) + +For multi-network support, register both EVM and SVM schemes: + + + + ```typescript + import { registerExactEvmScheme } from "@x402/evm/exact/server"; + import { registerExactSvmScheme } from "@x402/svm/exact/server"; + + const server = new x402ResourceServer(facilitatorClient); + registerExactEvmScheme(server); + registerExactSvmScheme(server); + ``` + + + ```go + import ( + evm "github.com/coinbase/x402/go/mechanisms/evm/exact/server" + svm "github.com/coinbase/x402/go/mechanisms/svm/exact/server" + ) + + r.Use(ginmw.X402Payment(ginmw.Config{ + // ... + Schemes: []ginmw.SchemeConfig{ + {Network: x402.Network("eip155:8453"), Server: evm.NewExactEvmScheme()}, + {Network: x402.Network("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"), Server: svm.NewExactSvmScheme()}, + }, + })) + ``` + + + +### 4. Update Your Wallet + +Make sure your receiving wallet address is a real mainnet address where you want to receive USDC payments. + +### 5. Test with Real Payments + +Before going live: +1. Test with small amounts first +2. Verify payments are arriving in your wallet +3. Monitor the facilitator for any issues + +**Warning:** Mainnet transactions involve real money. Always test thoroughly on testnet first and start with small amounts on mainnet. + +--- + +## Network Identifiers (CAIP-2) + +x402 v2 uses [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-2.md) format for network identifiers: + +| Network | CAIP-2 Identifier | +|---------|-------------------| +| Base Mainnet | `eip155:8453` | +| Base Sepolia | `eip155:84532` | +| Solana Mainnet | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` | +| Solana Devnet | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` | + +See [Network Support](/core-concepts/network-and-token-support) for the full list. + +--- + +### Next Steps + +* Looking for something more advanced? Check out the [Advanced Example](https://github.com/coinbase/x402/tree/main/examples/typescript/servers/advanced) +* Get started as a [buyer](/getting-started/quickstart-for-buyers) +* Learn about the [Bazaar discovery layer](/core-concepts/bazaar-discovery-layer) + +For questions or support, join our [Discord](https://discord.gg/cdp). + +### Summary + +This quickstart covered: + +* Installing the x402 SDK and relevant middleware +* Adding payment middleware to your API and configuring it +* Testing your integration +* Deploying to mainnet with CAIP-2 network identifiers + +Your API is now ready to accept crypto payments through x402. diff --git a/docs/guides/mcp-server-with-x402.md b/docs/guides/mcp-server-with-x402.md index 7e428ef05..bc41b00a4 100644 --- a/docs/guides/mcp-server-with-x402.md +++ b/docs/guides/mcp-server-with-x402.md @@ -1,6 +1,7 @@ -# MCP Server with x402 - -[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is a protocol for passing context between LLMs and other AI agents. This page shows how to use the x402 payment protocol with MCP to make paid API requests through an MCP server, and how to connect it to Claude Desktop. +--- +title: "MCP Server with x402" +description: "[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is a protocol for passing context between LLMs and other AI agents. This page shows how to use the x402 payment protocol with MCP to make paid API requests through an MCP server, and how to connect it to Claude Desktop." +--- ### What is this integration? @@ -308,4 +309,4 @@ The example uses these x402 v2 packages: * [See the full example in the repo](https://github.com/coinbase/x402/tree/main/examples/typescript/clients/mcp) * Try integrating with your own x402-compatible APIs * Extend the MCP server with more tools or custom logic as needed -* [Learn about building x402 servers](../getting-started/quickstart-for-sellers.md) +* [Learn about building x402 servers](/getting-started/quickstart-for-sellers) diff --git a/docs/guides/migration-v1-to-v2.md b/docs/guides/migration-v1-to-v2.md index 21323c492..4b72607f1 100644 --- a/docs/guides/migration-v1-to-v2.md +++ b/docs/guides/migration-v1-to-v2.md @@ -1,6 +1,7 @@ -# Migration Guide: V1 to V2 - -This guide helps you migrate from x402 V1 to V2. The V2 protocol introduces standardized identifiers, improved type safety, and a more modular architecture. +--- +title: "Migration Guide: V1 to V2" +description: "This guide helps you migrate from x402 V1 to V2. The V2 protocol introduces standardized identifiers, improved type safety, and a more modular architecture." +--- ## Overview @@ -208,6 +209,6 @@ The facilitator supports both V1 and V2 protocols. During migration, your V2 ser ## Next Steps -- [Quickstart for Buyers](../getting-started/quickstart-for-buyers.md) -- [Quickstart for Sellers](../getting-started/quickstart-for-sellers.md) -- [Network and Token Support](../core-concepts/network-and-token-support.md) +- [Quickstart for Buyers](/getting-started/quickstart-for-buyers) +- [Quickstart for Sellers](/getting-started/quickstart-for-sellers) +- [Network and Token Support](/core-concepts/network-and-token-support) diff --git a/docs/README.md b/docs/introduction.md similarity index 89% rename from docs/README.md rename to docs/introduction.md index b9684cef5..821406bbc 100644 --- a/docs/README.md +++ b/docs/introduction.md @@ -1,11 +1,10 @@ --- +title: "Welcome to x402" description: >- This guide will help you understand x402, the open payment standard, and help you get started building or integrating services with x402. --- -# Welcome to x402 - x402 is the open payment standard that enables services to charge for access to their APIs and content directly over HTTP. It is built around the HTTP `402 Payment Required` status code and allows clients to programmatically pay for resources without accounts, sessions, or credential management. With x402, any web service can require payment before serving a response, using crypto-native payments for speed, privacy, and efficiency. @@ -51,9 +50,9 @@ At a high level, the flow is simple: For more detail, see: -* Client / Server -* Facilitator -* HTTP 402 +* [Client / Server](/core-concepts/client-server) +* [Facilitator](/core-concepts/facilitator) +* [HTTP 402](/core-concepts/http-402) The goal is to make programmatic commerce accessible, permissionless, and developer-friendly. @@ -61,7 +60,7 @@ The goal is to make programmatic commerce accessible, permissionless, and develo Ready to build? Start here: -* [Quickstart for Sellers](getting-started/quickstart-for-sellers.md) -* [Quickstart for Buyers](getting-started/quickstart-for-buyers.md) -* [Explore Core Concepts](core-concepts/http-402.md) +* [Quickstart for Sellers](/getting-started/quickstart-for-sellers) +* [Quickstart for Buyers](/getting-started/quickstart-for-buyers) +* [Explore Core Concepts](/core-concepts/http-402) * [Join our community on Discord](https://discord.gg/invite/cdp)