with one click
sponge-wallet
// Crypto wallet, token swaps, cross-chain bridges, and access to paid external services (search, image gen, web scraping, AI, and more) via x402 payments.
// Crypto wallet, token swaps, cross-chain bridges, and access to paid external services (search, image gen, web scraping, AI, and more) via x402 payments.
| name | sponge-wallet |
| version | 0.2.2 |
| description | Crypto wallet, token swaps, cross-chain bridges, and access to paid external services (search, image gen, web scraping, AI, and more) via x402 payments. |
| homepage | https://wallet.paysponge.com |
| user-invocable | true |
| metadata | {"openclaw":{"emoji":"🧽","category":"finance","primaryEnv":"SPONGE_API_KEY","requires":{"env":["SPONGE_API_KEY"]}}} |
SPONGE WALLET API QUICK REFERENCE v0.2.2
Base: https://api.wallet.paysponge.com
Auth: Authorization: Bearer <SPONGE_API_KEY>
Ver: Sponge-Version: 0.2.2 (REQUIRED on every request)
Docs: This file is canonical (skills guide + params)
Capabilities: wallet + swaps (Solana/Base/Ethereum/Polygon/Arbitrum/Tempo) + bridges + payment links + paid external services (x402 + MPP) + trading + shopping + checkout + banking + Sponge Card + onramp
Paid services (search, image gen, scraping, AI, data, etc.):
GET /api/discover -> Step 1: find services by query/category
GET /api/discover/:serviceId -> Step 2: get endpoints, params, pricing (REQUIRED before fetch)
POST /api/paid/fetch -> Step 3: call service endpoint (auto-selects x402 USDC or MPP on Tempo)
POST /api/x402/fetch -> Step 3 alt: call service endpoint (x402 USDC only)
POST /api/mpp/fetch -> Step 3 alt: call service endpoint (MPP on Tempo; asset negotiated per endpoint, typically USDC.e)
POST /api/siwe/generate -> optional SIWE auth for endpoints that require EIP-4361 signatures
Wallet & tokens:
GET /api/balances -> get balances (includes Polymarket USDC.e)
POST /api/payment-links -> create reusable x402 payment link
GET /api/payment-links/:paymentLinkId -> get payment link status/details
POST /api/transfers/evm -> EVM transfer (ETH/USDC)
POST /api/transfers/solana -> Solana transfer (SOL/USDC)
POST /api/transfers/tempo -> Tempo transfer (pathUSD/AlphaUSD/BetaUSD/ThetaUSD)
POST /api/solana/sign -> Sign pre-built Solana transaction only
POST /api/solana/sign-and-send -> Sign and submit pre-built Solana transaction
POST /api/transactions/swap -> Solana swap (DFlow); also supports EVM chains
POST /api/transactions/swap/quote -> Solana swap quote only (DFlow)
POST /api/transactions/swap/execute -> Execute a previously obtained swap quote
POST /api/transactions/base-swap -> Base swap (0x)
POST /api/transactions/tempo-swap -> Tempo swap (StablecoinExchange DEX)
POST /api/transactions/bridge -> Bridge (Relay)
GET /api/solana/tokens -> list SPL tokens
GET /api/solana/tokens/search -> search Jupiter token list
GET /api/transactions/status/:txHash -> transaction status
GET /api/transactions/history -> transaction history
POST /api/wallets/withdraw-to-main -> withdraw to owner
Secrets & checkout data:
POST /api/credit-cards -> store encrypted card details (dedicated card tool)
POST /api/agents/:id/link-payment-methods/link -> connect Link, then save a Link payment method with required shipping/contact info
POST /api/agents/:id/link-payment-methods/credential -> generate one-time card credentials from a saved Link payment method
GET /api/agent-keys -> list stored secret metadata
GET /api/agent-keys/value -> retrieve a stored secret value (use `service=credit_card` for cards; this is the only read call needed for personal saved cards)
DELETE /api/agent-keys -> delete saved secret by service (use `service=credit_card` to remove personal saved card)
POST /api/agent-keys -> store non-card service keys (`service=credit_card` is rejected)
Cards (vaulted + enrolled):
POST /api/cards -> fetch the user's card (Sponge Card or vaulted card); auto-detects source
POST /api/virtual-cards -> issue a per-transaction virtual card scoped to amount and merchant
POST /api/card-usage -> report outcome of a purchase attempt
Sponge Card (beta preview):
GET /api/sponge-card/status -> onboarding/consent/card readiness status
POST /api/sponge-card/onboard -> start Rain application from existing Persona KYC + consent acknowledgements
POST /api/sponge-card/terms -> accept terms for an existing application
POST /api/sponge-card/create-card -> create the virtual Sponge Card after approval
GET /api/sponge-card/details -> encrypted PAN/CVC + secret_key + spending power (decrypt client-side)
POST /api/sponge-card/fund -> top up card collateral with USDC from your wallet
POST /api/sponge-card/withdraw -> withdraw card collateral back to your wallet
Onramp:
POST /api/onramp/crypto -> create fiat-to-crypto onramp link (Stripe/Coinbase)
Planning & proposals:
POST /api/plans/submit -> submit multi-step plan
POST /api/plans/approve -> approve and execute plan
POST /api/trades/propose -> propose single swap for approval
Banking:
POST /api/bank/onboard -> start KYC, get hosted verification URL
GET /api/bank/status -> check KYC/onboarding status
POST /api/bank/virtual-account -> create/get virtual bank account (USD→USDC deposits)
GET /api/bank/virtual-account -> get deposit instructions for a wallet
GET /api/bank/external-accounts -> list linked bank accounts
POST /api/bank/external-accounts -> link US bank account for ACH or wire payouts
POST /api/bank/send -> off-ramp: send USD to linked bank via ACH or wire (USDC→USD)
GET /api/bank/transfers -> list fiat transfer history
Trading & shopping:
POST /api/polymarket -> Polymarket prediction market trading
POST /api/hyperliquid -> Hyperliquid perps/spot trading
POST /api/checkout -> checkout from any online store; fire-and-forget approval by email
GET /api/checkout/:sessionId -> URL checkout request status
Auth (one-time setup):
POST /api/agents/register -> register (no auth)
POST /api/oauth/device/authorization -> device login start (humans)
POST /api/oauth/device/token -> device token poll (agents + humans)
Rules: use register (agents), never login | store key in ~/.spongewallet/credentials.json | requests are JSON
Errors: HTTP status + JSON error message
This skill is doc-only. There is no local CLI. It documents the public Sponge Wallet REST API.
POST /api/solana/sign-and-send.POST /api/solana/sign only when you explicitly need a partially/fully signed transaction back without broadcasting.GET /api/discover?query=... — find a serviceGET /api/discover/{serviceId} — get its endpoints, params, and payment config (do not skip)POST /api/paid/fetch — call the endpoint (auto-selects x402 USDC or MPP on Tempo based on service). Alternatively use POST /api/x402/fetch (USDC only) or POST /api/mpp/fetch (MPP on Tempo; asset negotiated per endpoint, typically USDC.e).POST /api/siwe/generate first and include its output in the fetch headers.POST /api/checkout for any merchant URLPOST /api/credit-cardsPOST /api/agents/{agentId}/link-payment-methods/link; first call can start Link login without shipping/contact info, saving the selected Link payment method requires shipping, phone, and emailPOST /api/cards (auto-detects source), or issue a per-transaction virtual card (POST /api/virtual-cards)If a task requires an external capability you don't have (e.g., generating images, searching the web, scraping a URL, looking up a person's email), use the 3-step discover flow above. There is likely a paid service available for it.
apiKey is returned once (immediately for agent-first mode, or after device approval for standard mode). If you lose it, you must re-register or re-authenticate.Store the API key in one canonical location:
~/.spongewallet/credentials.jsonRecommended file contents:
{
"apiKey": "sponge_live_...",
"claimCode": "ABCD-1234",
"claimUrl": "https://wallet.paysponge.com/device?code=ABCD-1234"
}
Optional environment export (runtime convenience):
export SPONGE_API_KEY="$(jq -r .apiKey ~/.spongewallet/credentials.json)"
https://api.wallet.paysponge.comAuthorization: Bearer <SPONGE_API_KEY>application/jsonQuick env setup:
export SPONGE_API_URL="https://api.wallet.paysponge.com"
export SPONGE_API_KEY="$(jq -r .apiKey ~/.spongewallet/credentials.json)"
Use POST /api/siwe/generate when an external API requires SIWE (EIP-4361) authentication.
Required args:
domainuriOptional args:
statement, nonce, chain_id, expiration_time, not_before, request_id, resourcesReturns:
message, signature, address, chainId, nonce, issuedAt, expirationTime, base64SiweMessageWorkflow:
POST /api/siwe/generate with the exact target domain and uri.Authorization header using returned signature and base64SiweMessage in the target API's expected format./api/paid/fetch or /api/x402/fetch when calling the protected endpoint.register, NOT loginThere are two modes:
agentFirst: true): agent receives the API key immediately, and the human can claim later.Step 1 — Start registration (agent-first recommended)
curl -sS -X POST "$SPONGE_API_URL/api/agents/register" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"name":"YourAgentName",
"agentFirst": true
}'
Response includes:
verificationUriComplete (claim URL for the human owner)claimCode, deviceCode, expiresIn, interval, claimTextapiKey (returned immediately in agent-first mode)Store apiKey, claimCode, and verificationUriComplete (as claimUrl) in ~/.spongewallet/credentials.json so a human can claim later if context resets.
Step 2 — Send the claim URL to the human owner They log in, optionally post the tweet text, and approve the agent.
Claim link format:
verificationUriComplete (example path: /device?code=ABCD-1234)verificationUriComplete to the human.Step 3 — Poll for completion (standard auth flow only)
curl -sS -X POST "$SPONGE_API_URL/api/oauth/device/token" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"grantType":"urn:ietf:params:oauth:grant-type:device_code",
"deviceCode":"<deviceCode>",
"clientId":"spongewallet-skill"
}'
On success, the response includes apiKey. Save it to ~/.spongewallet/credentials.json and use it as SPONGE_API_KEY.
Note: In agent-first mode, you already have the apiKey from Step 1. The auth token will remain pending until the human claims.
Phase 1 — Request device code
curl -sS -X POST "$SPONGE_API_URL/api/oauth/device/authorization" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"clientId":"spongewallet-skill"
}'
Phase 2 — Poll for token (same endpoint as agents)
curl -sS -X POST "$SPONGE_API_URL/api/oauth/device/token" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"grantType":"urn:ietf:params:oauth:grant-type:device_code",
"deviceCode":"<deviceCode>",
"clientId":"spongewallet-skill"
}'
Use the public REST endpoints documented in this file. Internal-only tools are intentionally omitted.
Common headers (include on EVERY request)
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-H "Accept: application/json"
Agent ID note: agentId is optional for API key auth. It is only required when using a user session (e.g., Privy-based auth) or when explicitly operating on a different agent.
| Endpoint | Method | Path | Params/Body |
|---|---|---|---|
| Get balances | GET | /api/balances | Query: chain, allowedChains, onlyUsdc |
| Create payment link | POST | /api/payment-links | Body: amount, optional description, max_uses, expires_in_minutes, callback_url, livemode |
| Get payment link status | GET | /api/payment-links/{paymentLinkId} | Query: agentId (optional) |
| List SPL tokens | GET | /api/solana/tokens | Query: chain |
| Search Solana tokens | GET | /api/solana/tokens/search | Query: query, limit |
| Tempo transfer | POST | /api/transfers/tempo | Body: to, amount, token (pathUSD/AlphaUSD/BetaUSD/ThetaUSD), optional data (hex calldata for raw contract calls) |
| EVM transfer | POST | /api/transfers/evm | Body: chain, to, amount, currency |
| Solana transfer | POST | /api/transfers/solana | Body: chain, to, amount, currency |
| Solana swap | POST | /api/transactions/swap | Body: chain, inputToken, outputToken, amount, slippageBps |
| Solana swap quote | POST | /api/transactions/swap/quote | Body: chain, inputToken, outputToken, amount, slippageBps |
| Solana swap execute | POST | /api/transactions/swap/execute | Body: quoteId |
| Base swap | POST | /api/transactions/base-swap | Body: chain, inputToken, outputToken, amount, slippageBps |
| Tempo swap | POST | /api/transactions/tempo-swap | Body: chain (tempo), inputToken, outputToken, amount, slippageBps |
| Bridge | POST | /api/transactions/bridge | Body: sourceChain, destinationChain, token, amount, destinationToken, recipientAddress |
| Transaction status | GET | /api/transactions/status/{txHash} | Query: chain |
| Transaction history | GET | /api/transactions/history | Query: limit, chain |
| Store credit card (encrypted) | POST | /api/credit-cards | Body (snake_case): card_number, expiration OR (expiry_month + expiry_year), cvc, cardholder_name, email, billing_address, shipping_address (phone required), optional label, metadata |
| Add Link payment method | POST | /api/agents/{agentId}/link-payment-methods/link | First call can use {} to start Link login and may return link_connection_required with verificationUrl. Saving requires email, top-level phone, and shipping (name, line1, city, state, postalCode, country). Optional: linkPaymentMethodId, setAsDefault, clientName, billing |
| Create Link payment credential | POST | /api/agents/{agentId}/link-payment-methods/credential | Generate one-time card credentials from a saved Link payment method. First call body: amount, merchantName, merchantUrl; optional: linkPaymentMethodId, currency, context. If approval is required, call again with spendRequestId after approval |
| Get card | POST | /api/cards | Body: optional card_type (rain | basis_theory_vaulted), payment_method_id, amount, currency, merchant_name, merchant_url, agentId. Auto-detects source; returns selection_required when both sources are enrolled |
| Issue virtual card | POST | /api/virtual-cards | Body: amount, merchant_name, merchant_url; optional: currency, merchant_country_code, description, products, shipping_address, enrollment_id, agentId |
| Report card usage | POST | /api/card-usage | Body: payment_method_id, status (success/failed/cancelled); optional: merchant_name, merchant_domain, amount, currency, failure_reason, agentId |
| Store service key (non-card) | POST | /api/agent-keys | Body: service, key, optional label, metadata (service=credit_card is rejected) |
| List stored keys | GET | /api/agent-keys | Query: agentId (optional) |
| Get stored key value | GET | /api/agent-keys/value | Query: service (use credit_card for card details) |
| Delete stored key | DELETE | /api/agent-keys | Query: service (credit_card to delete saved personal card), optional agentId |
| Step 1: Discover services | GET | /api/discover | Query: type, limit, offset, query, category |
| Step 2: Get service details | GET | /api/discover/{serviceId} | — |
| Step 3: Paid fetch (unified) | POST | /api/paid/fetch | Body: url, method, headers, body, chain (preferred wallet chain hint) |
| Step 3 alt: x402 fetch | POST | /api/x402/fetch | Body: url, method, headers, body, preferred_chain |
| Step 3 alt: MPP fetch | POST | /api/mpp/fetch | Body: url, method, headers, body, chain |
| SIWE signature | POST | /api/siwe/generate | Body: domain, uri; optional: statement, nonce, chain_id, expiration_time, not_before, request_id, resources |
| Sponge Card status | GET | /api/sponge-card/status | Query: optional refresh, agentId |
| Onboard Sponge Card | POST | /api/sponge-card/onboard | Body: occupation, consent booleans, optional agentId. Uses existing Persona KYC; does not accept raw SSN/date-of-birth fields |
| Accept Sponge Card terms | POST | /api/sponge-card/terms | Body: consent booleans, optional agentId |
| Create Sponge Card | POST | /api/sponge-card/create-card | Body: billing, email, phone, optional shipping, agentId |
| Sponge Card details | GET | /api/sponge-card/details | Query: agentId (optional) |
| Fund Sponge Card | POST | /api/sponge-card/fund | Body: amount, optional chain, agentId |
| Withdraw from Sponge Card | POST | /api/sponge-card/withdraw | Body: amount, optional chain, agentId |
| Banking onboard | POST | /api/bank/onboard | Body: optional wallet_id, redirect_uri, customer_type, agentId |
| Banking status | GET | /api/bank/status | Query: optional agentId |
| Create virtual bank account | POST | /api/bank/virtual-account | Body: wallet_id, optional agentId |
| Get virtual bank account | GET | /api/bank/virtual-account | Query: optional wallet_id, agentId |
| List linked bank accounts | GET | /api/bank/external-accounts | Query: optional agentId |
| Link bank account | POST | /api/bank/external-accounts | Body (snake_case): bank_name, account_owner_name, routing_number, account_number, checking_or_savings, street_line_1, optional street_line_2, city, state, postal_code, optional agentId |
| Send USD to bank | POST | /api/bank/send | Body: wallet_id, external_account_id, amount, optional payment_rail (ach/wire), agentId |
| List bank transfers | GET | /api/bank/transfers | Query: optional transfer_id, agentId |
| Crypto onramp | POST | /api/onramp/crypto | Body: wallet_address; optional: provider (auto/stripe/coinbase), chain (base/solana/polygon), fiat_amount, fiat_currency |
| Hyperliquid | POST | /api/hyperliquid | Body: action, + action-specific params (see below) |
| URL checkout request | POST | /api/checkout | Body: productUrl; optional: estimatedAmount, email, dryRun, productOptions, agentId |
| URL checkout status | GET | /api/checkout/{sessionId} | Query: agentId (optional) |
| Submit plan | POST | /api/plans/submit | Body: title, reasoning, steps (see Planning section) |
| Approve plan | POST | /api/plans/approve | Body: plan_id |
| Propose trade | POST | /api/trades/propose | Body: input_token, output_token, amount, reason |
Note: most request bodies use camelCase (e.g., inputToken, slippageBps). Card secret endpoints and Sponge Card API endpoints use snake_case fields (e.g., card_number, cardholder_name, first_name, postal_code). |
CRITICAL — Paid Services require ALL 3 steps in order:
GET /api/discover— search for a service by query or categoryGET /api/discover/{serviceId}— get the service's endpoints, parameters, pricing, and payment config (DO NOT SKIP THIS STEP)POST /api/x402/fetch— call the endpoint using the URL from step 2You MUST call step 2 before step 3. Step 2 returns the
paymentsProtocolConfig(with baseUrls) and the endpoint parameters/instructions needed to construct the fetch request. Using a direct API URL will fail with auth errors.
Use submit_plan whenever you need to do 2+ related actions together (e.g., swap then bridge, buy multiple tokens, rebalance a portfolio). This groups everything into a single proposal the user can review and approve.
Workflow:
submit_plan with a title, reasoning, and ordered list of stepsapprove_plan with the plan_idStep types:
swap — requires: input_token, output_token, amount, reason; optional: chain (defaults to solana; use base or tempo for other DEXs)transfer — requires: chain, to, amount, currency, reasonbridge — requires: source_chain, destination_chain, token, amount, reason; optional: destination_tokenRules:
approve_planpropose_trade only for a single swap that needs explicit approval; for multi-step flows, always use submit_planThe polymarket endpoint is a unified tool for Polymarket trading, funding, withdrawals, and account status. Pass action plus action-specific parameters:
| Action | Description | Required Params | Optional Params |
|---|---|---|---|
enable | Provision/link the Polymarket Safe without placing a trade | — | — |
signup | Alias for enable | — | — |
status | Check whether Polymarket is linked and view balances | — | — |
search_markets | Search Polymarket markets | query | limit |
get_market | Fetch market metadata | market_slug or token_id | — |
get_market_price | Fetch current market price | market_slug or token_id | — |
positions | View current positions | — | — |
orders | View open orders | — | — |
get_order | Fetch an order by ID | order_id | — |
balance_allowance | View CLOB balance + allowance | — | — |
refresh_balance_allowance | Refresh CLOB balance + allowance | — | — |
order | Place a limit or market order | outcome, side, size, market_slug or token_id | type, price, order_type |
cancel | Cancel an order | order_id | — |
set_allowances | Approve contracts for trading | — | — |
deposit | Make Safe-held USDC.e available to the exchange | — | — |
deposit_from_wallet | Move Polygon wallet USDC.e into the Safe | amount | — |
withdraw | Withdraw USDC.e to Polygon wallet | amount | — |
withdraw_native | Withdraw Polygon-native USDC to Polygon wallet | amount | — |
redeem | Redeem settled winning positions | — | condition_id |
Order params:
market_slug or token_id: identify which market to tradeoutcome: "yes" or "no"side: "buy" or "sell"size: number of sharestype: "limit" or "market"; defaults to "limit"price: required for limit orders, decimal between 0 and 1order_type: "GTC", "GTD", "FOK", or "FAK"; market orders only support FOK or FAKScopes: Setup, trade, and funding actions (enable, signup, order, cancel, set_allowances, deposit, deposit_from_wallet, withdraw, withdraw_native, redeem) require polymarket:trade. Read actions require wallet:read.
Provisioning: Trading and funding calls auto-link Polymarket on first use if the agent has a Polygon/EVM wallet. To sign up explicitly through the tool, call action: "enable" (or action: "signup"). You can also enable from the dashboard with POST /api/agents/:id/polymarket/enable.
Funding: For cross-chain funding, use the bridge tool with destination_chain: "polymarket" so the route lands as USDC.e in the Polymarket Safe.
Search: Use team names, common aliases, or exact slugs for sports markets. For NBA matchup searches, queries like "Sixers Celtics" should resolve aliases to current/future sports slugs such as nba-phi-bos-YYYY-MM-DD. If search_markets misses a sports matchup, search the web or Polymarket team/event pages directly, find the exact Polymarket event/market URL, then pass that slug to get_market, get_market_price, or order.
The hyperliquid endpoint is a unified tool for perps/spot trading on Hyperliquid DEX. Pass action plus action-specific parameters:
| Action | Description | Required Params | Optional Params |
|---|---|---|---|
status | Check account balances and equity | — | — |
positions | View open perp positions (entry, PnL, liq price) | — | — |
orders | View open orders | — | symbol |
fills | Recent trade history | — | symbol, since, limit |
markets | List available perp/spot markets | — | — |
ticker | Current price for a symbol | symbol | — |
orderbook | L2 order book | symbol | limit |
funding | Current + predicted funding rates | — | symbol |
order | Place limit/market/stop/TP order | symbol, side, type, amount | price, reduce_only, trigger_price, tp_sl, tif |
cancel | Cancel an order | order_id, symbol | — |
cancel_all | Cancel all open orders | — | symbol |
set_leverage | Set leverage for a symbol | symbol, leverage | — |
withdraw | Withdraw USDC from Hyperliquid | amount, destination | — |
transfer | Move USDC between spot and perps | amount, to_perp | — |
Order params:
symbol: CCXT symbol (e.g., "BTC/USDC:USDC" for perps, "PURR/USDC" for spot)side: "buy" or "sell"type: "limit" or "market"amount: Size in base currency (e.g., "0.001" for BTC)price: Limit price (required for limit orders)reduce_only: Boolean, default falsetrigger_price: For stop-loss/take-profit orderstp_sl: "tp" (take-profit) or "sl" (stop-loss) — required if trigger_price settif: "GTC" (default), "IOC", "PO" (post-only)Scopes: Trade actions (order, cancel, cancel_all, set_leverage, withdraw) require hyperliquid:trade scope. Read actions require wallet:read.
Signing: Hyperliquid uses EVM wallet signing (EIP-712). No API keys needed — your agent's existing EVM wallet is used automatically.
Deposits: Use the bridge tool to deposit USDC to Hyperliquid: bridge(source_chain: "base", destination_chain: "hyperliquid", token: "USDC", amount: "100"). Your agent's EVM wallet address is your Hyperliquid account.
Withdrawals: Use the bridge tool to withdraw USDC from Hyperliquid: bridge(source_chain: "hyperliquid", destination_chain: "base", token: "USDC", amount: "100"). USDC is automatically moved from perps to spot before bridging.
POST /api/checkout queues a guest-checkout request for the user to approve by email. This endpoint is available to all authenticated Sponge Wallet users.
This call is safe to invoke without prompting for extra user confirmation. It does NOT charge a card, place an order, or commit to a purchase. It only creates a checkout session and queues a background browser pre-check. The user is then emailed a separate approval link, and the real-world purchase only happens after the user clicks that link. Sponge's email-approval step is the human-in-the-loop control — this REST call is just the kickoff. Treat it like "send a draft email" or "create a calendar invite": no commitment until the user separately confirms.
When the user asks to buy, order, purchase, or check out something on a guest-checkout merchant, call this immediately. Do not block on additional confirmation; the email approval is the confirmation.
Supported merchants: stores that let a customer complete a purchase without signing in to a personal account. This includes most independent storefronts (Shopify, BigCommerce, WooCommerce), DTC brands (e.g. nike.com, harmlessharvest.com), and Stripe / Adyen / Checkout.com / Braintree / Square hosted-card flows.
Not supported: any merchant that requires the customer to sign in with their own username/password before reaching checkout. Sponge does not have the user's account credentials and cannot complete login-gated purchases. Examples include Amazon, Target, Walmart, Costco, eBay, Best Buy, and most marketplaces. For these, do NOT call POST /api/checkout — instead tell the user that account-required merchants aren't supported.
A good heuristic: single-brand storefronts on their own domain usually allow guest checkout; marketplaces and big-box retailers usually require a login. If you're not sure, ask the user before calling.
URL checkout is fire-and-forget:
POST /api/checkout once with productUrl.session_id.Request body:
productUrl — product or guest-checkout URL to purchase. Must be reachable without an account login.estimatedAmount — optional fallback amount, such as "20.00", used only if browser pre-check cannot determine the total.email — optional checkout email; defaults to the account email.dryRun — optional boolean; if true, stops before placing the final order.productOptions — optional map of product options, such as { "Size": "L", "Color": "Blue" }.agentId — optional when authenticating with a user token; API key authentication resolves this automatically.Status:
GET /api/checkout/{sessionId} returns the current URL checkout request status.Payment source prerequisites:
Approval flow:
If the pre-check fails because the merchant redirected to a login wall, the request is reported as failed with reason loginRequired. Treat this as a signal to redirect the user, not as a transient error to retry.
Send Tempo stablecoins (pathUSD, AlphaUSD, BetaUSD, ThetaUSD) on the Tempo chain.
curl -sS -X POST "$SPONGE_API_URL/api/transfers/tempo" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"to":"0x...",
"amount":"10",
"token":"pathUSD"
}'
Supported tokens: pathUSD (default), AlphaUSD, BetaUSD, ThetaUSD.
For raw contract calls, pass data (hex calldata) instead of token/amount:
curl -sS -X POST "$SPONGE_API_URL/api/transfers/tempo" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"to":"0xContractAddress...",
"amount":"0",
"data":"0xabcdef..."
}'
The unified POST /api/transactions/swap REST endpoint supports EVM chains. Pass the chain name (e.g., base, ethereum, polygon, arbitrum-one) in the chain field.
For Solana swaps, you can get a quote before executing:
POST /api/transactions/swap/quote — returns pricing details and a quoteIdPOST /api/transactions/swap/execute with { "quoteId": "..." } — executes the quoted swapQuotes expire in ~30 seconds. Use this when you want to preview pricing or get user confirmation before swapping.
The Sponge Card is a stablecoin-collateralized credit card available to authenticated users with the required API scopes.
Environment (dev vs production) is fixed by your API key type: sponge_test_* -> dev sandbox, sponge_live_* -> production.
The full no-UI flow is:
GET /api/sponge-card/status - check onboarding and card readiness.POST /api/sponge-card/onboard - submit the Rain application from existing Persona KYC and record consent acknowledgements.POST /api/sponge-card/terms.ready_for_card_creation is true, POST /api/sponge-card/create-card./details, /fund, and /withdraw after a card exists.curl -sS "$SPONGE_API_URL/api/sponge-card/status?refresh=true" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
Returns onboarded, environment, ready_for_card_creation, customer, completion_link_url, cards, balances, and message. balances uses explicit unit fields such as spending_power_cents, spending_power_usd, and spending_power_display; for user-facing output, use the display fields. If spending_power_cents is 250, that means $2.50, not $250. If completion_link_url is present, Rain needs hosted identity/document verification. Have the user complete that URL outside Sponge, then poll status again.
Submit the Rain application from the user's already-approved Persona KYC and record Sponge consent acknowledgements. Bodies use snake_case. Do not collect or send raw SSN, national ID, birth date, or address fields to this endpoint.
curl -sS -X POST "$SPONGE_API_URL/api/sponge-card/onboard" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"occupation":"Software engineer",
"e_sign_consent":true,
"account_opening_privacy_notice":true,
"sponge_card_terms":true,
"information_certification":true,
"unauthorized_solicitation_acknowledgement":true
}'
occupation is required.account_opening_privacy_notice is required when the Persona KYC country is US.Returns submitted_application, environment, ready_for_card_creation, customer, completion_link_url, and message.
Use this only when /status says the Rain application is approved but Sponge consent is missing.
curl -sS -X POST "$SPONGE_API_URL/api/sponge-card/terms" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"e_sign_consent":true,
"account_opening_privacy_notice":true,
"sponge_card_terms":true,
"information_certification":true,
"unauthorized_solicitation_acknowledgement":true
}'
Call this after status returns ready_for_card_creation: true. If a card already exists for this API-key environment, the API returns the existing card instead of issuing a duplicate.
curl -sS -X POST "$SPONGE_API_URL/api/sponge-card/create-card" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"billing":{
"line1":"123 Market St",
"city":"San Francisco",
"region":"CA",
"postal_code":"94105",
"country_code":"US"
},
"email":"user@example.com",
"phone":"+14155550100"
}'
Returns created, environment, card, and message.
curl -sS "$SPONGE_API_URL/api/sponge-card/details" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
Returns last4, expiration_month, expiration_year, type, status, spending_power_cents, spending_power_usd, spending_power_display, email, phone, plus an encrypted PAN + CVC blob and a one-time secret_key. For user-facing output, use spending_power_display; spending_power_cents is an integer in cents, so 250 means $2.50, not $250. Plaintext card numbers never exist on the backend — you must decrypt locally with AES-128-GCM:
const { webcrypto } = require("crypto");
async function decrypt({ iv, data }, secretKeyHex) {
const key = await webcrypto.subtle.importKey(
"raw",
Buffer.from(secretKeyHex, "hex"),
{ name: "AES-GCM" },
false,
["decrypt"],
);
const pt = await webcrypto.subtle.decrypt(
{ name: "AES-GCM", iv: Buffer.from(iv, "base64") },
key,
Buffer.from(data, "base64"),
);
return new TextDecoder().decode(pt);
}
const pan = await decrypt(result.encrypted_pan, result.secret_key);
const cvc = await decrypt(result.encrypted_cvc, result.secret_key);
Treat the decrypted PAN/CVC as highly sensitive: do not log, persist, or echo to non-cardholder destinations.
Send USDC from your wallet to the collateral deposit address to increase the card's spending power. Sponge credits the deposit once the transfer confirms (1–2 blocks on EVM, seconds on Solana).
curl -sS -X POST "$SPONGE_API_URL/api/sponge-card/fund" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"amount":"100","chain":"base"}'
amount: USDC in human-readable units (e.g. "100", "100.50"). Positive decimal.chain: optional. Required only if the user has more than one collateral contract. Allowed: base, ethereum, polygon, arbitrum-one, solana.Returns tx_hash, chain_id, to_address, token_address, amount.
Pull USDC back from the collateral contract to your wallet. Reduces the card's spending power.
curl -sS -X POST "$SPONGE_API_URL/api/sponge-card/withdraw" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"amount":"50.25","chain":"base"}'
amount: USD with max 2 decimal places (e.g. "50", "50.25"). Positive.chain: optional — same rules as fund.Returns tx_hash, chain_id, amount, recipient_address.
Notes:
Scopes: /api/sponge-card/status and /api/sponge-card/details require payment:read. /api/sponge-card/onboard requires wallet:write + payment:write. /api/sponge-card/terms and /api/sponge-card/create-card require payment:write. /api/sponge-card/fund and /api/sponge-card/withdraw require wallet:write + transaction:sign + transaction:write.
Create a fiat-to-crypto onramp link to fund your wallet with USDC via card or bank payment.
curl -sS -X POST "$SPONGE_API_URL/api/onramp/crypto" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"wallet_address":"0x...",
"chain":"base",
"fiat_amount":"100"
}'
Returns a hosted checkout URL. Provider is auto-selected (Stripe first, Coinbase fallback). Mainnet chains only.
MPP works like x402 but settles on Tempo instead of Base/Solana/Ethereum. The asset is negotiated per endpoint (typically USDC.e). Use the same 3-step discover flow, then call /api/mpp/fetch instead of /api/x402/fetch.
When to use MPP vs x402:
POST /api/x402/fetch) when paying with USDC on Base/Solana/EthereumPOST /api/mpp/fetch) when the endpoint settles on Tempo (asset chosen by the endpoint, e.g. USDC.e)POST /api/paid/fetch) to let the system auto-select the best protocolcurl -sS -X POST "$SPONGE_API_URL/api/mpp/fetch" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"url":"https://paysponge.com/exa/search",
"method":"POST",
"body":{"query":"best pizza in NYC","text":true},
"chain":"tempo"
}'
POST /api/paid/fetch is the recommended fetch tool — it detects payment protocols from the endpoint's 402 challenge, then handles x402 USDC on Base/Solana/Ethereum or MPP on Tempo with the endpoint's chosen asset. If both are advertised, it uses the route with the highest available stablecoin balance.
curl -sS -X POST "$SPONGE_API_URL/api/paid/fetch" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"url":"https://paysponge.com/exa/search",
"method":"POST",
"body":{"query":"best pizza in NYC","text":true},
"chain":"base"
}'
The chain parameter is a hint for which wallet to spend from, not a hard requirement — the system falls back automatically if the endpoint doesn't support the requested chain.
Use POST /api/credit-cards for payment card data.
Do not use store_key (or POST /api/agent-keys) for cards. service: "credit_card" is intentionally rejected there.
For chat agents, collect card details one field at a time in this exact order:
card_numberexpiration (MM/YYYY)cvccardholder_namebilling_addressshipping_address (must include phone)emailRules:
get_key_value(service: "credit_card") (or GET /api/agent-keys/value?service=credit_card) and return full values.get_key_list for personal card retrieval.Example (store + retrieve):
curl -sS -X POST "$SPONGE_API_URL/api/credit-cards" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"card_number":"4111111111111111",
"expiration":"12/2030",
"cvc":"123",
"cardholder_name":"Jane Doe",
"email":"jane@example.com",
"billing_address":{"line1":"123 Main St","city":"San Francisco","state":"CA","postal_code":"94105","country":"US"},
"shipping_address":{"line1":"123 Main St","city":"San Francisco","state":"CA","postal_code":"94105","country":"US","phone":"+14155550123"},
"label":"personal-visa"
}'
curl -sS "$SPONGE_API_URL/api/agent-keys/value?service=credit_card" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
Use this when the user wants checkout to use Link. This is a two-step flow: connect Link first, then save the selected Link payment method to the agent. Link login does not require shipping, phone, or email. Saving the Link payment method always requires shipping, phone, and email. billing is optional.
POST /api/agents/{agentId}/link-payment-methods/link with {} to start Link login if needed.link_connection_required, give the user verificationUrl and ask them to approve the Link connection.email, top-level phone, and shipping fields: name, line1, city, state, postalCode, country, plus optional line2.email, phone, and shipping.payment_method_selection_required, ask the user which returned method to use, then call again with linkPaymentMethodId, email, phone, and shipping.saved, checkout can use the saved Link payment method and saved address info.curl -sS -X POST "$SPONGE_API_URL/api/agents/$AGENT_ID/link-payment-methods/link" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{}'
curl -sS -X POST "$SPONGE_API_URL/api/agents/$AGENT_ID/link-payment-methods/link" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"linkPaymentMethodId":"pm_...",
"setAsDefault":true,
"email":"jane@example.com",
"phone":"+14155550123",
"shipping":{
"name":"Jane Doe",
"line1":"123 Main St",
"city":"San Francisco",
"state":"CA",
"postalCode":"94105",
"country":"US"
}
}'
Use this when a saved Link payment method should produce raw card credentials for a specific checkout. The endpoint uses the saved method's billing address if present, otherwise its shipping address, as the fallback billing details sent to Link. If linkPaymentMethodId is omitted, the default saved Link payment method is used. It does not block while waiting for approval: if user approval is needed, it returns status:"approval_required" with approvalUrl and spendRequestId.
curl -sS -X POST "$SPONGE_API_URL/api/agents/$AGENT_ID/link-payment-methods/credential" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"amount":"49.99",
"currency":"USD",
"merchantName":"Netflix",
"merchantUrl":"https://www.netflix.com",
"context":"Monthly subscription"
}'
If the response is approval_required, ask the user to open approvalUrl and approve. Then retrieve the credential:
curl -sS -X POST "$SPONGE_API_URL/api/agents/$AGENT_ID/link-payment-methods/credential" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"linkPaymentMethodId":"<savedPaymentMethodId from previous response>",
"spendRequestId":"<spendRequestId from previous response>"
}'
Returns status:"credential_created", saved Link method metadata, and card with pan, expiryMonth, expiryYear, optional cvc, optional cardholderName, and optional billingAddress.
POST /api/cards is the single entry point for retrieving the user's card. It auto-detects the card source:
https://wallet.paysponge.com/dashboard?tab=cards&addCard=1&cardFlow=basis-theory to add one through Basis Theory Elements. Returns a short-lived BT session you must immediately fetch.If the user has only one source enrolled, the endpoint returns that card directly. If both sources are enrolled and card_type is omitted, the response is { "status": "selection_required", "available_cards": [...] } — ask the user which they'd like, then re-call with card_type set.
# Auto-detect
curl -sS -X POST "$SPONGE_API_URL/api/cards" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{}'
# Explicit Sponge Card
curl -sS -X POST "$SPONGE_API_URL/api/cards" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{ "card_type": "rain" }'
# Explicit BT vaulted card with merchant context for spending limits
curl -sS -X POST "$SPONGE_API_URL/api/cards" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"card_type": "basis_theory_vaulted",
"amount": "49.99",
"merchant_name": "Netflix",
"merchant_url": "https://www.netflix.com"
}'
Response shape (Sponge Card branch): card_type:"rain", last4, expiration_month, expiration_year, secret_key, encrypted_pan, encrypted_cvc, spending_power_cents, spending_power_usd, spending_power_display, email, phone, decryption_instructions. For user-facing output, use spending_power_display; spending_power_cents is an integer in cents, so 250 means $2.50, not $250.
Response shape (BT branch): card_type:"basis_theory_vaulted", session_key, retrieve_url, token_id, expires_at, card_brand, card_last4, payment_method_id, billing_address, email, phone. Immediately fetch the BT card data:
curl -sS "<retrieve_url>" \
-H "BT-API-KEY: <session_key>"
The card data is returned in data.number, data.expiration_month, data.expiration_year, and data.cvc.
For per-transaction virtual cards, use /api/virtual-cards (see below).
Use this when you need card credentials scoped to a specific merchant + amount (e.g., a one-shot payment). For retrieving an already-vaulted card, prefer POST /api/cards.
curl -sS -X POST "$SPONGE_API_URL/api/virtual-cards" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"amount":"49.99",
"merchant_name":"Netflix",
"merchant_url":"https://www.netflix.com",
"merchant_country_code":"US",
"description":"Monthly subscription"
}'
Returns fresh card credentials (card_number, expiration_month, expiration_year, cvc) plus expires_at and instruction_id.
Use this after checkout to log the outcome of a purchase attempt.
curl -sS -X POST "$SPONGE_API_URL/api/card-usage" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"payment_method_id":"pm_123",
"merchant_name":"Netflix",
"amount":"49.99",
"currency":"USD",
"status":"success"
}'
curl -sS -X POST "$SPONGE_API_URL/api/agents/register" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"name":"YourAgentName",
"agentFirst": true
}'
Share the claim URL with your human, then store the apiKey immediately (agent-first). For standard auth flow, poll for the token after approval.
curl -sS "$SPONGE_API_URL/api/balances?chain=base" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
curl -sS -X POST "$SPONGE_API_URL/api/transfers/evm" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"chain":"base",
"to":"0x...",
"amount":"10",
"currency":"USDC"
}'
curl -sS -X POST "$SPONGE_API_URL/api/transactions/swap" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"chain":"solana",
"inputToken":"SOL",
"outputToken":"BONK",
"amount":"0.5",
"slippageBps":100
}'
curl -sS -X POST "$SPONGE_API_URL/api/transactions/base-swap" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"chain":"base",
"inputToken":"ETH",
"outputToken":"USDC",
"amount":"0.1",
"slippageBps":50
}'
curl -sS -X POST "$SPONGE_API_URL/api/transactions/tempo-swap" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"chain":"tempo",
"inputToken":"USDC.e",
"outputToken":"pathUSD",
"amount":"10",
"slippageBps":50
}'
Available Tempo tokens: pathUSD, AlphaUSD, BetaUSD, ThetaUSD, USDC.e (mainnet only). All are 6-decimal stablecoins routed through the native StablecoinExchange DEX.
curl -sS -X POST "$SPONGE_API_URL/api/transactions/bridge" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"sourceChain":"solana",
"destinationChain":"base",
"token":"SOL",
"amount":"0.1",
"destinationToken":"ETH"
}'
curl -sS "$SPONGE_API_URL/api/transactions/status/0xabc123...?chain=base" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
curl -sS -X POST "$SPONGE_API_URL/api/polymarket" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"action":"status"}'
curl -sS -X POST "$SPONGE_API_URL/api/polymarket" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"action":"search_markets","query":"election","limit":5}'
curl -sS -X POST "$SPONGE_API_URL/api/polymarket" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"action":"order",
"market_slug":"will-bitcoin-be-above-100k-on-december-31-2026",
"outcome":"yes",
"side":"buy",
"size":10,
"type":"limit",
"price":0.42,
"order_type":"GTC"
}'
curl -sS -X POST "$SPONGE_API_URL/api/polymarket" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"action":"withdraw",
"amount":"25"
}'
curl -sS -X POST "$SPONGE_API_URL/api/hyperliquid" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"action":"status"}'
curl -sS -X POST "$SPONGE_API_URL/api/hyperliquid" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"action":"ticker","symbol":"BTC/USDC:USDC"}'
curl -sS -X POST "$SPONGE_API_URL/api/hyperliquid" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"action":"order",
"symbol":"BTC/USDC:USDC",
"side":"buy",
"type":"limit",
"amount":"0.001",
"price":"50000"
}'
curl -sS -X POST "$SPONGE_API_URL/api/hyperliquid" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"action":"positions"}'
curl -sS -X POST "$SPONGE_API_URL/api/plans/submit" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"title":"Rebalance to USDC",
"reasoning":"Taking profit on SOL position and bridging to Base",
"steps":[
{"type":"swap","input_token":"SOL","output_token":"USDC","amount":"10","reason":"Take profit on SOL"},
{"type":"bridge","source_chain":"solana","destination_chain":"base","token":"USDC","amount":"100","reason":"Move USDC to Base"}
]
}'
curl -sS -X POST "$SPONGE_API_URL/api/plans/approve" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{"plan_id":"<plan_id>"}'
curl -sS -X POST "$SPONGE_API_URL/api/trades/propose" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"input_token":"USDC",
"output_token":"SOL",
"amount":"500",
"reason":"Accumulating SOL at current prices"
}'
curl -sS -X POST "$SPONGE_API_URL/api/checkout" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"productUrl":"https://merchant.example/products/example",
"estimatedAmount":"20.00",
"dryRun":true,
"productOptions":{"Size":"L","Color":"Blue"}
}'
curl -sS "$SPONGE_API_URL/api/checkout/<sessionId>" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
The catalog gives you access to paid APIs via x402 (USDC on Base/Solana/Ethereum) or MPP (Tempo, asset negotiated per endpoint — typically USDC.e). If you need a capability you don't have natively (web search, image generation, web scraping, data enrichment, AI models, etc.), discover and call a service.
Always follow this 3-step workflow: discover → get service details → fetch.
IMPORTANT: Always use the URL from step 2. Do NOT use direct API URLs — most services are proxied through paysponge and direct URLs will fail with auth errors.
curl -sS "$SPONGE_API_URL/api/discover?limit=10" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
Returns available paid services from the catalog. Supports semantic search via the query parameter (vector embeddings rank results by relevance). Combine with category to narrow results.
# Search by natural language description
curl -sS "$SPONGE_API_URL/api/discover?query=web+scraping+and+crawling" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
# Filter by category
curl -sS "$SPONGE_API_URL/api/discover?category=search" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
Available categories: search, image, llm, crawl, data, predict, parse, prospect, person_search, crypto_data
Each result includes: id, name, description, category, endpointCount.
The discover response does NOT include endpoint paths, parameters, or the baseUrl needed for fetch. You MUST call step 2 next.
Once you have a service id from step 1 (e.g., ctg_abc123), call GET /api/discover/{serviceId} to get the service's endpoints, parameters, pricing, and payment config:
curl -sS "$SPONGE_API_URL/api/discover/ctg_abc123" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Accept: application/json"
This returns everything you need to construct the fetch call:
baseUrl: The proxy URL to use in step 3protocol: x402 or mppnetworks: Supported networks (e.g. ["base", "solana"] for x402, ["tempo"] for mpp)method: HTTP method (GET, POST, etc.)path: Endpoint path to append to the baseUrldescription: What the endpoint doesprice / currency: Cost per callparameters: JSON schema for query/path/body params — tells you exactly what to sendinstructions: Free-text usage guide with examplesparameters / instructions on the endpoint don't tell you enough to build the request body.Without this step, you don't know what endpoints exist, what parameters they accept, or what URL to use.
Pick a protocol from paymentsProtocolConfig and construct the URL as: baseUrl + endpoint path. Then call fetch via /api/paid/fetch (recommended — auto-selects protocol), /api/x402/fetch (x402 USDC only), or /api/mpp/fetch (MPP on Tempo; asset negotiated per endpoint):
curl -sS -X POST "$SPONGE_API_URL/api/paid/fetch" \
-H "Authorization: Bearer $SPONGE_API_KEY" \
-H "Sponge-Version: 0.2.2" \
-H "Content-Type: application/json" \
-d '{
"url":"https://paysponge.com/exa/search",
"method":"POST",
"body":{"query":"best pizza in NYC","text":true},
"chain":"base"
}'
The fetch endpoint handles the entire payment flow automatically:
payment_made and payment_detailsIf the parameters / instructions from step 2 are not enough to build the request body, fall back to the service docsUrl returned by GET /api/discover/{serviceId} or the provider's official API docs.
Receive and send USD via bank accounts over REST.
POST /api/bank/onboard to start KYC. Returns a hosted URL for identity verification unless the customer is already active.GET /api/bank/status to poll KYC progress (pending → approved).# 1. Create or get virtual account for a wallet (idempotent — returns existing if one exists)
POST /api/bank/virtual-account { "wallet_id": "<uuid>" }
# 2. Get deposit instructions (account number, routing number)
GET /api/bank/virtual-account?wallet_id=<uuid>
When someone sends USD to the virtual account's bank details, it's automatically converted to USDC and deposited into the wallet. Supported chains: Ethereum, Base, Solana.
# 1. Link a US bank account
POST /api/bank/external-accounts {
"bank_name":"Bank of America",
"account_owner_name":"Jane Doe",
"routing_number":"021000021",
"account_number":"1234567890",
"checking_or_savings":"checking",
"street_line_1":"123 Main St",
"city":"San Francisco",
"state":"CA",
"postal_code":"94105"
}
# 2. List linked accounts (get external_account_id)
GET /api/bank/external-accounts
# 3. Send USD via ACH or wire (converts USDC from wallet → USD)
POST /api/bank/send { "wallet_id":"<uuid>", "external_account_id":"<uuid>", "amount":"100.00", "payment_rail":"ach" }
POST /api/bank/send { "wallet_id":"<uuid>", "external_account_id":"<uuid>", "amount":"100.00", "payment_rail":"wire" }
# 4. Check transfer status
GET /api/bank/transfers
GET /api/bank/transfers?transfer_id=<uuid>
ACH settlement: typically 1-3 business days. Wire payouts are typically faster.
Supported chains: ethereum, base, polygon, arbitrum-one, tempo, solana.
Errors return JSON with an error message and HTTP status:
{"error":"message"}
| Status | Meaning | Common Cause |
|---|---|---|
| 400 | Bad Request | Missing/invalid fields |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Address not in allowlist or permission denied |
| 404 | Not Found | Resource does not exist |
| 409 | Conflict | Duplicate action |
| 429 | Rate Limited | Too many requests (back off + retry) |
| 500 | Server Error | Transient; retry later |
~/.spongewallet/credentials.json and restrict file permissions.Built for agents.
[HINT] Download the complete skill directory including SKILL.md and all related files