Manage your seller
tools402 has no web dashboard, no login, no admin UI. Every seller operation is an HTTP call signed by your wallet (EIP-712 SellerAction). The four operations below cover the full lifecycle after onboarding.
#Pre-requisite
You have your .tools402-seller.pk file (the same key that registered
your slug). All the snippets below assume :
import { existsSync, readFileSync } from "node:fs";
import { privateKeyToAccount } from "viem/accounts";
import { keccak256, toBytes } from "viem";
const pk = readFileSync(".tools402-seller.pk", "utf-8").trim() as `0x${string}`;
const account = privateKeyToAccount(pk);
const WALLET = account.address;
const API = "https://api.tools402.dev";
const DOMAIN = { name: "tools402", version: "1", chainId: 8453 } as const;
const TYPES = { SellerAction: [
{ name: "wallet", type: "address" }, { name: "action", type: "string" },
{ name: "payloadHash", type: "bytes32" }, { name: "timestamp", type: "uint256" },
]} as const;#Update an endpoint (price, upstream, desc)
There is no UPDATE primitive — instead, delete then re-add. The sequence keeps your slug, only the endpoint id changes.
#Delete an endpoint
const id = 42; // your endpoint id from /v1/_meta
const ts = Math.floor(Date.now() / 1000);
const sig = await account.signTypedData({
domain: DOMAIN, types: TYPES, primaryType: "SellerAction",
message: { wallet: WALLET, action: "delete_endpoint", payloadHash: keccak256(toBytes(String(id))), timestamp: BigInt(ts) },
});
await fetch(`${API}/v1/_seller/${WALLET}/endpoints/${id}`, {
method: "DELETE",
headers: { "X-Signature": sig, "X-Timestamp": String(ts) },
});
// → 200 OK { ok: true }The endpoint is soft-deleted (enabled = 0). Buyer calls on this path
return 410 Gone immediately. Pending settlements still ship at the
next 00:00 UTC cron.
#Resume after suspension
If your endpoint returned 5xx for > 50 % of probes over 10 minutes, the
marketplace flipped it to degraded. Sustained outage > 1 hour →
suspended (status returned in /v1/_meta).
To resume :
const ts = Math.floor(Date.now() / 1000);
const sig = await account.signTypedData({
domain: DOMAIN, types: TYPES, primaryType: "SellerAction",
message: { wallet: WALLET, action: "resume", payloadHash: keccak256(toBytes("")), timestamp: BigInt(ts) },
});
await fetch(`${API}/v1/_seller/${WALLET}/resume`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ wallet: WALLET, signature: sig, timestamp: ts }),
});
// → 200 OK { ok: true, status: "active" }The marketplace runs another 3-region probe immediately. If it passes,
your endpoint flips back to active in /v1/_meta and starts serving
again. If it fails, the suspension stays.
#Read your stats
The stats endpoint returns your current activity (calls, revenue, top endpoints, next settlement). It's read-only but still signed (to prevent stalking of arbitrary wallets) :
const ts = Math.floor(Date.now() / 1000);
const sig = await account.signTypedData({
domain: DOMAIN, types: TYPES, primaryType: "SellerAction",
message: { wallet: WALLET, action: "stats", payloadHash: keccak256(toBytes("")), timestamp: BigInt(ts) },
});
const r = await fetch(`${API}/v1/_seller/${WALLET}/stats?sig=${sig}&ts=${ts}`);
const stats = await r.json();
// → {
// "wallet": "0x…", "slug": "your-slug",
// "revenue_24h_usdc": "0.46", "revenue_total_usdc": "12.83",
// "calls_24h": 47, "calls_total": 1287,
// "take_rate": "3%",
// "top_endpoints": [...],
// "perf": { p50_ms, p95_ms, p99_ms },
// "next_settlement": { "in": "8h 12m", "net_usdc": "0.44", "gas_absorbed": true }
// }#Lose your .tools402-seller.pk file
There is no recovery. Your slug is locked to the wallet that registered it; without the private key, you can't add endpoints, delete endpoints, resume, or move the slug elsewhere. Daily settlement keeps pushing USDC to the wallet's address but you cannot spend it.
Back up .tools402-seller.pk to a password manager the moment you
generate it. The onboarding script writes it with mode 0o600; you can
also copy the hex content into 1Password, Bitwarden, or any secrets
vault.
If your wallet is compromised (private key leaked), you cannot rotate it.
You can delete_endpoint everything and start over with a new slug + new
wallet. The marketplace does not have any concept of "account ownership"
above the wallet.