Agent flow
An agent can transfer a file with no account, no wallet and no key. Add the MCP server and the transfer tools work immediately — a key only raises the limits. This page covers both paths and the three details that cause almost every failed integration.
Without a key
Install and go. Uploads run under guest limits: 100 MB per file and a 24-hour link.
npx -y @payaion/mcp # or: pip install payaion-mcp && payaion-mcpStraight HTTP works the same way — one request, whole file, link back:
curl -X POST https://payaion-api.fly.dev/v1/aion/upload \
-F "file=@report.csv"
# {"uploadId":"up_…","downloadUrl":"https://payaion.com/d/…","status":"PENDING_UPLOAD"}Browsing the marketplace needs no key either. Uploading, checking status and fetching a download URL all work anonymously; listing a file for sale and buying one do not.
Getting a key without a browser
An agent mints its own key by signing a message with a wallet it holds locally. No MetaMask, no dashboard, three requests.
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(generatePrivateKey()); // a dedicated agent wallet
// 1. nonce
const { nonce } = await (await fetch("https://payaion.com/api/auth/nonce")).json();
// 2. sign locally
const message = [
"payaion.com wants you to sign in with your Ethereum account:",
account.address,
"",
"Create a Payaion API key",
"",
"URI: https://payaion.com",
"Version: 1",
"Chain ID: 8453",
`Nonce: ${nonce}`,
`Issued At: ${new Date().toISOString()}`,
].join("\n");
const signature = await account.signMessage({ message });
// 3. mint
const { apiKey } = await (await fetch("https://payaion.com/api/aion-keys/siwe", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message, signature }),
})).json(); // av_…Three things that will reject your signature
- The domain must be exactly
payaion.com. The first line of the message is checked against this site's host. A message built forlocalhostor a preview URL is rejected here. - The statement must read
Create a Payaion API key. It sits on its own line, wrapped in blank lines, exactly as shown. A message signed to log in is deliberately not accepted for minting, and vice versa — one signature must not authorise two different things. - Chain ID must be 8453 (Base). Other chains are refused even though the signature would verify on them.
The nonce is single-use and the message expires five minutes after Issued At. Fetch a fresh nonce per mint.
What a minted key can and cannot do
Keys minted this way carry upload scopes only — upload:create, upload:status, upload:download. They cannot list a file for sale. Pricing is a human action taken in the dashboard, because the wallet an agent generated for itself lives in an environment file on a server, and money should not follow it.
Where the money goes
Earnings are paid to the payout address on your account, set in the dashboard under Earnings. It is deliberately independent of whichever wallet signed an upload, and no API key can read or change it. Use a cold address.
Until you set one, payouts fall back to the wallet you first signed in with — which is correct for a human account and wrong for an agent that minted its own key. Set it before you price anything.
Selling without an account
A caller with no key has no account to hold a payout address, so it names one per upload instead: payoutAddress on POST /v1/upload/init, or the X-Payout-Address header on the one-shot endpoints. The MCP transfer tool takes the same value as payoutAddress. This is what lets an agent sell with no signup at all.
It applies to keyless callers only. When a key is present the field is ignored and the account's dashboard setting wins — otherwise a stolen key could redirect an account's earnings.
- Must be a
0x-prefixed 40-character EVM address, or the call fails withinvalid_payout_address. - Payments are final. A mistyped address cannot be recovered by us or anyone else.
- An exchange deposit address usually will not credit a Base transfer arriving from a contract. Use a wallet you control.
- A priced upload cannot also ask for a 12- or 24-hour link (
retention_conflicts_with_price) — buyers are guaranteed 30 days and a short link cannot honour that.
What a keyless caller can and cannot do
A keyless caller is counted by a hash of its network address, and that is all the hash does: it anchors rate limits and daily byte budgets so one guest cannot exhaust the service for everyone. It is not proof of ownership, and it never grants access to anything. Changing network does not hand over — or take away — any file.
What a key does buy is authority over uploads after the fact:
get_download_urlneeds a key. Keep thedownloadUrlfrom the upload response instead — it is public and belongs to the file, not to the caller, so a keyless agent loses nothing by never calling it.- Deleting an upload needs a key. Keyless uploads expire on their own.
- Listing on the marketplace needs a key with
marketplace:list. Pricing a file does not — see above. Idempotency-Keyworks for API keys only. A keyless retry creates a second upload, so check the first attempt's status rather than resending.