1- import { Tabs , TabsList , TabsTrigger , TabsContent , DocImage , createMetadata } from " @doc" ;
1+ import {
2+ Tabs ,
3+ TabsList ,
4+ TabsTrigger ,
5+ TabsContent ,
6+ DocImage ,
7+ createMetadata ,
8+ Stack ,
9+ GithubTemplateCard
10+ } from " @doc" ;
211import { Steps , Step } from " @doc" ;
312import PaymentFlow from " ./x402-protocol-flow.png" ;
413
514export const metadata = createMetadata ({
6- image: {
7- title: " x402 Server" ,
8- icon: " payments" ,
9- },
10- title: " x402 Server" ,
11- description: " Accept x402 payments in your APIs from any x402-compatible client." ,
15+ image: {
16+ title: " x402 Server" ,
17+ icon: " payments" ,
18+ },
19+ title: " x402 Server" ,
20+ description:
21+ " Accept x402 payments in your APIs from any x402-compatible client." ,
1222});
1323
1424# Server Side
@@ -28,53 +38,123 @@ The x402 protocol follows this flow:
28385 . ** Verify & Settle** - Server verifies and settles the payment
29396 . ** Success** - Server returns the protected content
3040
31- ## Verify vs Settle
41+ ## Exact vs Upto Payment Schemes
3242
33- You have two options for handling payments:
43+ The thirdweb x402 client/server stack supports two payment schemes: ` exact ` and ` upto ` .
3444
35- ### Option 1: Settle Payment Directly
45+ - ` exact ` - The client pays the exact amount specified in the payment requirements.
46+ - ` upto ` - The client pays any amount up to the specified maximum amount.
3647
37- Use ` settlePayment() ` to verify and settle the payment in one step. This is the simplest approach:
48+ By default, the payment scheme is ` exact ` . You can specify the payment scheme in the ` settlePayment() ` or ` verifyPayment() ` arguments.
49+
50+ ### Exact Payment Scheme
51+
52+ Use ` settlePayment() ` to verify and settle the payment in one step. This is the default and simplest approach:
3853
3954``` typescript
40- const result = await settlePayment (paymentArgs );
55+ const result = await settlePayment ({
56+ resourceUrl: " https://api.example.com/premium-content" ,
57+ method: " GET" ,
58+ paymentData ,
59+ payTo: " 0x1234567890123456789012345678901234567890" ,
60+ network: arbitrum ,
61+ price: " $0.10" ,
62+ facilitator: thirdwebFacilitator ,
63+ });
4164
4265if (result .status === 200 ) {
43- // Payment settled, do the paid work
44- return Response .json ({ data: " premium content" });
66+ // Payment settled, do the paid work
67+ return Response .json ({ data: " premium content" });
4568}
4669```
4770
48- ### Option 2: Verify First, Then Settle
71+ ### Upto Payment Scheme
72+
73+ For dynamic pricing, use ` verifyPayment() ` first, do the work, then ` settlePayment() ` :
74+
75+ - The final price can be dynamic based on the work performed
76+ - Ensures the payment is valid before doing the expensive work
4977
50- Use ` verifyPayment() ` first, do the work, then ` settlePayment() ` . This is useful when:
51- - The final price might be dynamic based on the work performed
52- - You want to ensure the payment is valid before doing expensive work
53- - You need to calculate resource usage before charging
78+ This is great for AI apis that need to charge based on the token usage for example. Check out a fully working example check out [ this x402 ai inference example] ( https://github.com/thirdweb-example/x402-ai-inference ) .
79+
80+ <Stack >
81+ <GithubTemplateCard
82+ title = " x402 AI Inference Example"
83+ description = " A fully working example of charging an for AI inference with x402"
84+ href = " https://github.com/thirdweb-example/x402-ai-inference"
85+ />
86+ </Stack >
87+
88+ Here's a high level example of how to use the ` upto ` payment scheme with a dynamic price based on the token usage. First we verify the payment is valid for the max payable amount and then settle the payment based on the actual usage.
5489
5590``` typescript
56- // First verify the payment is valid
91+ const paymentArgs = {
92+ resourceUrl: " https://api.example.com/premium-content" ,
93+ method: " GET" ,
94+ paymentData ,
95+ payTo: " 0x1234567890123456789012345678901234567890" ,
96+ network: arbitrum ,
97+ scheme: " upto" , // enables dynamic pricing
98+ price: " $0.10" , // max payable amount
99+ facilitator: thirdwebFacilitator ,
100+ };
101+
102+ // First verify the payment is valid for the max amount
57103const verifyResult = await verifyPayment (paymentArgs );
58104
59105if (verifyResult .status !== 200 ) {
60- return Response .json (verifyResult .responseBody , {
61- status: verifyResult .status ,
62- headers: verifyResult .responseHeaders ,
63- });
106+ return Response .json (verifyResult .responseBody , {
107+ status: verifyResult .status ,
108+ headers: verifyResult .responseHeaders ,
109+ });
64110}
65111
66112// Do the expensive work that requires payment
67- const result = await doExpensiveWork ();
113+ const { tokensUsed } = await callExpensiveAIModel ();
68114
69115// Now settle the payment based on actual usage
116+ const pricePerTokenUsed = 0.00001 ; // ex: $0.00001 per AI model token used
70117const settleResult = await settlePayment ({
71- ... paymentArgs ,
72- price: calculateDynamicPrice ( result ) , // adjust price based on usage
118+ ... paymentArgs ,
119+ price: tokensUsed * pricePerTokenUsed , // adjust final price based on usage
73120});
74121
75122return Response .json (result );
76123```
77124
125+ ## Price and Token Configuration
126+
127+ You can specify prices in multiple ways:
128+
129+ ### USD String
130+
131+ This will default to using USDC on the specified network.
132+
133+ ``` typescript
134+ network : polygon , // or any other EVM chain
135+ price : " $0.10" // 10 cents in USDC
136+ ```
137+
138+ ### ERC20 Token
139+
140+ You can use any ERC20 token that supports the ERC-2612 permit or ERC-3009 sign with authorization.
141+
142+ Simply pass the amount in base units and the token address.
143+
144+ ``` typescript
145+ network : arbitrum ,
146+ price : {
147+ amount : " 1000000000000000" , // Amount in base units (0.001 tokens with 18 decimals)
148+ asset : {
149+ address : " 0xf01E52B0BAC3E147f6CAf956a64586865A0aA928" , // Token address
150+ }
151+ }
152+ ```
153+
154+ ### Native Token
155+
156+ Payments in native tokens are not currently supported.
157+
78158## Dedicated Endpoint Examples
79159
80160Protect individual API endpoints with x402 payments:
@@ -117,7 +197,6 @@ Protect individual API endpoints with x402 payments:
117197 routeConfig: {
118198 description: " Access to premium API content" ,
119199 mimeType: " application/json" ,
120- maxTimeoutSeconds: 300 ,
121200 },
122201 });
123202
@@ -133,6 +212,7 @@ Protect individual API endpoints with x402 payments:
133212 }
134213 }
135214 ```
215+
136216 </TabsContent >
137217
138218 <TabsContent value = " express" >
@@ -185,6 +265,7 @@ Protect individual API endpoints with x402 payments:
185265
186266 app .listen (3000 );
187267 ```
268+
188269 </TabsContent >
189270
190271 <TabsContent value = " hono" >
@@ -237,6 +318,7 @@ Protect individual API endpoints with x402 payments:
237318
238319 export default app ;
239320 ```
321+
240322 </TabsContent >
241323</Tabs >
242324
@@ -311,6 +393,7 @@ Protect multiple endpoints with a shared middleware:
311393 matcher: [" /api/paid/:path*" ],
312394 };
313395 ```
396+
314397 </TabsContent >
315398
316399 <TabsContent value = " express" >
@@ -364,6 +447,7 @@ Protect multiple endpoints with a shared middleware:
364447 res .json ({ message: " This is premium content!" });
365448 });
366449 ```
450+
367451 </TabsContent >
368452
369453 <TabsContent value = " hono" >
@@ -418,38 +502,7 @@ Protect multiple endpoints with a shared middleware:
418502 return c .json ({ message: " This is premium content!" });
419503 });
420504 ```
505+
421506 </TabsContent >
422507</Tabs >
423508
424- ## Price and Token Configuration
425-
426- You can specify prices in multiple ways:
427-
428- ### USD String
429-
430- This will default to using USDC on the specified network.
431-
432- ``` typescript
433- network : polygon , // or any other EVM chain
434- price : " $0.10" // 10 cents in USDC
435- ```
436-
437- ### ERC20 Token
438-
439- You can use any ERC20 token that supports the ERC-2612 permit or ERC-3009 sign with authorization.
440-
441- Simply pass the amount in base units and the token address.
442-
443- ``` typescript
444- network : arbitrum ,
445- price : {
446- amount : " 1000000000000000" , // Amount in base units (0.001 tokens with 18 decimals)
447- asset : {
448- address : " 0xf01E52B0BAC3E147f6CAf956a64586865A0aA928" , // Token address
449- }
450- }
451- ```
452-
453- ### Native Token
454-
455- Payments in native tokens are not currently supported.
0 commit comments