Buyer SDK
Prepare smart-account mandates, create agent continuations, and pay direct x402 resources.
For autonomous agent commerce, the buyer path is permission-first:
- Approve a MetaMask ERC-7715 permission for the seller payee and token.
- Check readiness for a seller/resource/payment scope.
- Create a continuation only when readiness is
ready. - Open or redirect to the seller-hosted continuation URL with the scoped continuation token appended. The seller server calls OpenPermit internally to issue the x402 ERC-7710 credential and finish checkout.
import { createOpenPermitClient } from '@openpermit/sdk/client';
const openpermit = createOpenPermitClient({
baseUrl: 'https://api.openpermit.ai',
apiKey: process.env.OPENPERMIT_API_KEY,
});
const scope = {
mandateId: 'mandate_...',
storefrontUrl: 'https://storefront.example',
sellerId: 'seller_...',
resourceId: 'storefront:checkout',
paymentChallenge: 'x402' as const,
paymentMode: 'metamaskErc7715' as const,
chain: 'eip155:11155111',
asset: 'USDC',
payTo: '0xSellerPayTo...',
tokenAddress: '0xUsdcToken...',
tokenDecimals: 6,
tokenName: 'USDC',
tokenVersion: '2',
metadata: {
merchantContinuationUrl: 'https://storefront.example/agent-payments/continue/session_123?checkoutSession=checkout_session_123',
},
};
const readiness = await openpermit.checkAgentCommerceReadiness(scope);
if (readiness.status !== 'ready') {
throw new Error(readiness.requiredActions.join('\\n'));
}
const continuation = await openpermit.createAgentCommerceContinuation(scope);The continuation response includes link-first agentInstructions; show or copy those only after readiness is ready. For browser-first checkout, append the continuation token to the seller merchantContinuationUrl and let the seller page complete checkout.
OpenPermit's dashboard requests the MetaMask ERC-7715 permission from the connected payer wallet. Viem signAuthorization and the EIP-7702 helpers below are future/advanced mode; production MetaMask extension accounts should use paymentMode: 'metamaskErc7715' instead of the 7702 helper path.
import {
registerSmartAccountX402Mandate,
revokeSmartAccountX402Mandate,
} from '@openpermit/sdk/experimental/openpermit7702';
await registerSmartAccountX402Mandate({
client: openpermit,
mandateId: 'mandate_...',
walletClient,
publicClient, // must support getCode for already-delegated browser-wallet accounts
chain: 'eip155:10143',
payeeAddress: '0xSellerPayTo...',
tokenAddress: '0xUsdcToken...',
tokenDecimals: 6,
tokenName: 'USDC',
tokenVersion: '2',
});
await revokeSmartAccountX402Mandate({
client: openpermit,
mandateId: 'mandate_...',
walletClient,
publicClient,
chain: 'eip155:10143',
});wrapFetch is still useful for developer-controlled agents that can run SDK code directly. For x402, it can also run in manual wallet-signed mode when you supply an x402.walletClient capable of signing the EIP-3009 payload. Manual x402 helpers are also available under @openpermit/sdk/x402/manual so they are not confused with autonomous generic-agent checkout.
import { wrapFetch } from '@openpermit/sdk/buyer';
import { createOpenPermitClient } from '@openpermit/sdk/client';
const openpermit = createOpenPermitClient({
baseUrl: 'https://api.openpermit.ai',
apiKey: process.env.OPENPERMIT_API_KEY,
});
const paidFetch = wrapFetch(fetch, {
client: openpermit,
mandateId: 'mandate_...',
x402: { walletClient },
idempotencyKey: (intent) => `agent-run-${intent.intentId}`,
onPaymentExecuted: (execution, intent) => {
console.log('paid', intent.intentId, execution.executionId);
},
});
const response = await paidFetch('https://seller.example/paid/data');Policy denials throw OpenPermitPolicyError. Malformed or unsupported payment challenges throw OpenPermitPaymentRequiredError.
Manual wallet-signed x402 requires a fresh real PAYMENT-SIGNATURE. Generic agents should use MetaMask ERC-7715 readiness and continuations instead of pretending they can sign from the user's wallet.