Your First Agent Account
End-to-end walkthrough: provision an account, set policy, fund it, issue an agent key, and make your first programmatic payment.
What you'll build
By the end of this guide you will have:
- A provisioned agent account on Solana with an associated USDC token account
- A spending policy with sensible limits
- An agent-scoped API key that can transfer USDC but cannot modify policy
- A funded account ready to make direct transfers or pay MPP-enabled services via HTTP 402
Step 1 — Provision the account
Name your account after the agent's function. This name appears in the dashboard and in audit logs — make it meaningful.
import { MPPPal } from "@mpppal/sdk";
const client = new MPPPal({ apiKey: process.env.MPPPAL_OPERATOR_KEY });
const account = await client.accounts.create({
name: "invoice-payment-agent-prod",
metadata: {
environment: "production",
team: "payments",
service: "billing-automation",
},
});
console.log("Account ID:", account.account_id);
console.log("Fund this address with USDC:", account.usdc_token_account);
Step 2 — Set spending policy before funding
Set policy before you fund the account. An unfunded account with no policy is harmless. A funded account with no policy has no limits.
await client.policy.update(account.account_id, {
max_single_transfer: 500, // No single payment over $500
max_daily_spend: 2000, // $2,000/day cap
categories: ["inference", "data"], // Only approved spend categories
require_memo: true, // Every transfer needs a reference
paused: false,
});
console.log("Policy set. Account is ready to fund.");
Step 3 — Fund the account
Send USDC to the usdc_token_account address. This is a Solana SPL token account — fund it with USDC only. Do not send SOL.
Verify funding:
const { balance_usdc } = await client.accounts.getBalance(account.account_id);
console.log(`Balance: $${balance_usdc} USDC`);
// Balance: $500.000000 USDC
Step 4 — Issue an agent API key
Generate an agent-scoped key for this account. The agent will use this key — not your operator key — when making transfers or paying MPP services.
const { api_key } = await client.apiKeys.create({
account_id: account.account_id,
name: "invoice-payment-agent-prod-key",
});
// Store this key in your secrets manager — it will not be shown again
console.log("Agent key:", api_key);
// mpppal_agent_01j9m5p2q8rstu3vw...
Step 5 — Use the key in your agent
For direct transfers between agents:
// Your agent uses the agent-scoped key, not the operator key
const agentClient = new MPPPal({
apiKey: process.env.MPPPAL_AGENT_KEY,
});
const transfer = await agentClient.transfers.create({
from: process.env.MPPPAL_ACCOUNT_ID,
to: "vendor-usdc-token-account-address",
amount: "120.00",
memo: "Invoice #1042 — Acme Corp",
idempotency_key: `invoice-1042-${Date.now()}`,
});
console.log("Settled:", transfer.tx_signature);
For agents paying MPP-enabled services via HTTP 402:
const agent = new MPPPal.Agent({
wallet: process.env.MPPPAL_ACCOUNT_ID,
apiKey: process.env.MPPPAL_AGENT_KEY,
intent: "session",
sessionCap: "5.00",
});
const http = agent.createHttpClient();
// HTTP 402 payment challenges resolved automatically
const result = await http.post("https://api.someservice.xyz/inference", {
body: JSON.stringify({ text: content }),
});
Checklist
- Account provisioned and name is meaningful
- Spending policy set before funding
- Account funded with USDC (SPL token address, not SOL address)
- Agent API key issued and stored in secrets manager
- Agent uses agent-scoped key, not operator key
- Webhook configured for
transfer.rejectedevents so policy violations surface in your alerting