Agentic Commerce - Buy IRL Items With USDC
AI-powered shopping API for product search and crypto checkout. Use this skill when: - Searching for products from Amazon and Shopify - Building shopping assistants or product recommendation features
AI-powered shopping API for product search and crypto checkout. Use this skill when: - Searching for products from Amazon and Shopify - Building shopping assistants or product recommendation features
Real data. Real impact.
Growing
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
Base URL:
https://api.purch.xyz
60 requests/minute per IP. Headers in every response:
X-RateLimit-Limit: Max requests per windowX-RateLimit-Remaining: Requests leftX-RateLimit-Reset: Seconds until resetQuery products with filters.
curl "https://api.purch.xyz/search?q=headphones&priceMax=100"
Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | Search query |
| priceMin | number | No | Minimum price |
| priceMax | number | No | Maximum price |
| brand | string | No | Filter by brand |
| page | number | No | Page number (default: 1) |
Response:
{ "products": [ { "id": "B0CXYZ1234", "title": "Sony WH-1000XM5", "price": 348.00, "currency": "USD", "rating": 4.8, "reviewCount": 15420, "imageUrl": "https://...", "productUrl": "https://amazon.com/dp/B0CXYZ1234", "source": "amazon" } ], "totalResults": 20, "page": 1, "hasMore": true }
Natural language product search. Returns 20+ products from both Amazon and Shopify.
curl -X POST "https://api.purch.xyz/shop" \ -H "Content-Type: application/json" \ -d '{"message": "comfortable running shoes under $100"}'
Request Body:
{ "message": "comfortable running shoes under $100", "context": { "priceRange": { "min": 0, "max": 100 }, "preferences": ["comfortable", "breathable"] } }
Response:
{ "reply": "Found 22 running shoes. Top pick: Nike Revolution 6 at $65...", "products": [ { "asin": "B09XYZ123", "title": "Nike Revolution 6", "price": 65.00, "currency": "USD", "rating": 4.5, "reviewCount": 8420, "imageUrl": "https://...", "productUrl": "https://amazon.com/dp/B09XYZ123", "source": "amazon" }, { "asin": "gid://shopify/p/abc123", "title": "Allbirds Tree Runners", "price": 98.00, "source": "shopify", "productUrl": "https://allbirds.com/products/tree-runners", "vendor": "Allbirds" } ] }
Create an order and get a transaction to sign. Chain is auto-detected from wallet format:
7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU0x1234567890abcdef1234567890abcdef12345678Amazon Products (Solana):
curl -X POST "https://api.purch.xyz/buy" \ -H "Content-Type: application/json" \ -d '{ "asin": "B0CXYZ1234", "email": "buyer@example.com", "walletAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "shippingAddress": { "name": "John Doe", "line1": "123 Main St", "line2": "Apt 4B", "city": "New York", "state": "NY", "postalCode": "10001", "country": "US", "phone": "+1-555-123-4567" } }'
Amazon Products (Base):
curl -X POST "https://api.purch.xyz/buy" \ -H "Content-Type: application/json" \ -d '{ "asin": "B0CXYZ1234", "email": "buyer@example.com", "walletAddress": "0x1234567890abcdef1234567890abcdef12345678", "shippingAddress": { "name": "John Doe", "line1": "123 Main St", "city": "New York", "state": "NY", "postalCode": "10001", "country": "US" } }'
Shopify Products - Use
productUrl AND variantId:
curl -X POST "https://api.purch.xyz/buy" \ -H "Content-Type: application/json" \ -d '{ "productUrl": "https://store.com/products/item-name", "variantId": "41913945718867", "email": "buyer@example.com", "walletAddress": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "shippingAddress": { "name": "John Doe", "line1": "123 Main St", "city": "New York", "state": "NY", "postalCode": "10001", "country": "US" } }'
Response:
{ "orderId": "550e8400-e29b-41d4-a716-446655440000", "status": "awaiting-payment", "serializedTransaction": "NwbtPCP62oXk5fmSrgT...", "product": { "title": "Sony WH-1000XM5", "imageUrl": "https://...", "price": { "amount": "348.00", "currency": "usdc" } }, "totalPrice": { "amount": "348.00", "currency": "usdc" }, "checkoutUrl": "https://www.crossmint.com/checkout/550e8400..." }
This skill includes ready-to-use CLI scripts for all endpoints. Available in Python and TypeScript/Bun.
Dependencies (Solana):
# Python pip install solana solders base58TypeScript/Bun
bun add @solana/web3.js bs58
Dependencies (Base/EVM):
# TypeScript/Bun bun add viem
# Python python scripts/search.py "wireless headphones" --price-max 100 python scripts/search.py "running shoes" --brand Nike --page 2TypeScript
bun run scripts/search.ts "wireless headphones" --price-max 100
# Python python scripts/shop.py "comfortable running shoes under $100"TypeScript
bun run scripts/shop.ts "wireless headphones with good noise cancellation"
# Amazon by ASIN python scripts/buy.py --asin B0CXYZ1234 --email buyer@example.com \ --wallet 7xKXtg... --address "John Doe,123 Main St,New York,NY,10001,US"Shopify product
bun run scripts/buy.ts --url "https://store.com/products/item" --variant 41913945718867
--email buyer@example.com --wallet 7xKXtg... --address "John Doe,123 Main St,NYC,NY,10001,US"
Address format:
Name,Line1,City,State,PostalCode,Country[,Line2][,Phone]
End-to-end purchase flow - creates order and signs/submits the Solana transaction:
# Python python scripts/buy_and_sign.py --asin B0CXYZ1234 --email buyer@example.com \ --wallet 7xKXtg... --private-key 5abc123... \ --address "John Doe,123 Main St,New York,NY,10001,US"TypeScript
bun run scripts/buy_and_sign.ts --url "https://store.com/products/item" --variant 41913945718867
--email buyer@example.com --wallet 7xKXtg... --private-key 5abc123...
--address "John Doe,123 Main St,NYC,NY,10001,US"
End-to-end purchase flow using Base/EVM wallet:
bun run scripts/buy_and_sign_base.ts --asin B0CXYZ1234 --email buyer@example.com \ --wallet 0x1234567890abcdef1234567890abcdef12345678 \ --private-key 0xabc123... \ --address "John Doe,123 Main St,New York,NY,10001,US"
If you already have a
serializedTransaction from the /buy endpoint:
# Python python scripts/sign_transaction.py "<serialized_tx>" "<private_key_base58>"TypeScript
bun run scripts/sign_transaction.ts "<serialized_tx>" "<private_key_base58>"
bun run scripts/sign_transaction_base.ts "<serialized_tx_hex>" "<private_key_hex>"
Output (Solana):
✅ Transaction successful! Signature: 5UfgJ3vN... Explorer: https://solscan.io/tx/5UfgJ3vN...
Output (Base):
✅ Transaction successful! Hash: 0x1234... Explorer: https://basescan.org/tx/0x1234...
For custom integrations without using the bundled scripts:
import { Connection, Transaction, clusterApiUrl } from "@solana/web3.js"; import bs58 from "bs58";async function signAndSendTransaction( serializedTransaction: string, wallet: { signTransaction: (tx: Transaction) => Promise<Transaction> } ) { // Decode the base58 transaction const transactionBuffer = bs58.decode(serializedTransaction); const transaction = Transaction.from(transactionBuffer);
// Sign with user's wallet (e.g., Phantom, Solflare) const signedTransaction = await wallet.signTransaction(transaction);
// Send to Solana network const connection = new Connection(clusterApiUrl("mainnet-beta")); const signature = await connection.sendRawTransaction( signedTransaction.serialize() );
// Confirm transaction await connection.confirmTransaction(signature, "confirmed");
return signature; }
import { useWallet, useConnection } from "@solana/wallet-adapter-react"; import { Transaction } from "@solana/web3.js"; import bs58 from "bs58";function CheckoutButton({ serializedTransaction }: { serializedTransaction: string }) { const { signTransaction, publicKey } = useWallet(); const { connection } = useConnection();
const handlePayment = async () => { if (!signTransaction || !publicKey) { throw new Error("Wallet not connected"); }
// Decode and sign const tx = Transaction.from(bs58.decode(serializedTransaction)); const signed = await signTransaction(tx); // Send and confirm const sig = await connection.sendRawTransaction(signed.serialize()); await connection.confirmTransaction(sig, "confirmed"); console.log("Payment complete:", sig);};
return <button onClick={handlePayment}>Pay with USDC</button>; }
import base58 from solana.rpc.api import Client from solana.transaction import Transaction from solders.keypair import Keypairdef sign_and_send(serialized_tx: str, keypair: Keypair) -> str: # Decode base58 transaction tx_bytes = base58.b58decode(serialized_tx) transaction = Transaction.deserialize(tx_bytes)
# Sign transaction.sign(keypair) # Send client = Client("https://api.mainnet-beta.solana.com") result = client.send_transaction(transaction) return result.value # transaction signature
For Base chain orders, the
serializedTransaction is an EVM transaction that needs to be signed with an EVM wallet.
import { createWalletClient, http, parseTransaction } from "viem"; import { base } from "viem/chains"; import { privateKeyToAccount } from "viem/accounts";async function signAndSendBaseTransaction( serializedTransaction: string, privateKey:
) { const account = privateKeyToAccount(privateKey);0x${string}const client = createWalletClient({ account, chain: base, transport: http(), });
// Parse and send the serialized transaction const tx = parseTransaction(serializedTransaction as
); const hash = await client.sendTransaction(tx);0x${string}console.log("Transaction hash:", hash); console.log("Explorer: https://basescan.org/tx/" + hash);
return hash; }
import { useSendTransaction } from "wagmi"; import { parseTransaction } from "viem";function CheckoutButton({ serializedTransaction }: { serializedTransaction: string }) { const { sendTransaction } = useSendTransaction();
const handlePayment = async () => { const tx = parseTransaction(serializedTransaction as
); sendTransaction(tx); };0x${string}return <button onClick={handlePayment}>Pay with USDC on Base</button>; }
// 1. Search for products const searchResponse = await fetch("https://api.purch.xyz/shop", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: "wireless headphones under $100" }) }); const { products, reply } = await searchResponse.json();// 2. User selects a product, create order (Solana wallet) const orderResponse = await fetch("https://api.purch.xyz/buy", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ asin: products[0].asin, email: "buyer@example.com", walletAddress: wallet.publicKey.toBase58(), // Solana address shippingAddress: { name: "John Doe", line1: "123 Main St", city: "New York", state: "NY", postalCode: "10001", country: "US" } }) }); const { orderId, serializedTransaction, checkoutUrl } = await orderResponse.json();
// 3. Sign and send Solana transaction const tx = Transaction.from(bs58.decode(serializedTransaction)); const signed = await wallet.signTransaction(tx); const signature = await connection.sendRawTransaction(signed.serialize()); await connection.confirmTransaction(signature, "confirmed");
console.log();Order ${orderId} paid. Tx: ${signature}
import { parseTransaction } from "viem";// 1. Search for products const searchResponse = await fetch("https://api.purch.xyz/shop", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: "wireless headphones under $100" }) }); const { products } = await searchResponse.json();
// 2. User selects a product, create order (EVM wallet) const orderResponse = await fetch("https://api.purch.xyz/buy", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ asin: products[0].asin, email: "buyer@example.com", walletAddress: "0x1234...", // Base/EVM address - chain auto-detected shippingAddress: { name: "John Doe", line1: "123 Main St", city: "New York", state: "NY", postalCode: "10001", country: "US" } }) }); const { orderId, serializedTransaction } = await orderResponse.json();
// 3. Sign and send Base transaction const tx = parseTransaction(serializedTransaction as
); const hash = await walletClient.sendTransaction(tx);0x${string}console.log();Order ${orderId} paid. Tx: ${hash}
If wallet signing fails or isn't available, redirect to
checkoutUrl for browser-based payment:
if (!wallet.connected) { window.open(checkoutUrl, "_blank"); }
All endpoints return errors as:
{ "code": "VALIDATION_ERROR", "message": "Invalid email format", "details": { "field": "email" } }
Common error codes:
VALIDATION_ERROR (400) - Invalid request parametersNOT_FOUND (404) - Product not foundRATE_LIMITED (429) - Too many requestsINTERNAL_ERROR (500) - Server errorNo automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.