Your system runs the agents, and each one holds its own key. The person whose money moves signs once, in their own wallet. Remesso provides the contracts on Celo, a request inbox, an indexer and signed webhooks.
No sign-up
No API key
Receiving needs no gas
Money never passes through Remesso
Fig. 1
Who runs what
Two agents on your side, Remesso in the middle, Celo underneath. The numbers follow one payment from request to delivery.
Swipe sideways to see the whole figure.
The receiving agent asks to be paid. It names the wallet that will pay, an exact amount and one token.
The paying agent reads that wallet's inbox and finds the request.
It pays on Celo, from its own wallet or from the person's, inside the limit they signed.
Remesso's indexer sees the payment and matches it to the request.
Remesso posts signed webhooks to the receiving side: payment.received, then payment.finalized.
The receiving agent checks the payment on Celo itself, with no key, and then delivers.
Signed once. The person's wallet approves a spending limit or a mandate. The contracts refuse anything outside it, and the person can revoke it alone.
Mandates. Remesso's executor agent sends each payment of a mandate when it's due. It can't change the receiver, the amount or the dates.
Transaction on Celo, signed by its sender
Call to Remesso or a webhook, free
Reads the chain, no key
Your system
Remesso
Celo mainnet
Your user's wallet
Fig. 2
One payment, step by step
A spending-limit payment of 1,500 wARS. The person signs once. After that the agent pays on its own, and the contract refuses anything outside the limit.
Swipe sideways to see the whole figure.
Transaction on Celo, signed by its sender
Call to Remesso or a webhook, free
Reads the chain, no key
Fig. 3
Choosing how to pay
Three ways to fund a payment. The receiving side works the same way for all three.
Swipe sideways to see the whole figure.
A
Spending limit
Who signs
The person, once: an approval and a policy naming the agent. Then the agent pays alone.
Each payment
One transaction from the agent, about 90k gas.
Remesso's fee
None.
Per payment
What the policy allows: caps per payment and per day, an expiry, and optionally a recipient list.
B
The agent's own wallet
Who signs
The agent, each time. In Fig. 2, step 1 drops out and step 4 becomes three transactions: a one-payment schedule, an approval and the run.
Each payment
About 370k gas across the three.
Remesso's fee
0.25%, added on top, so the receiver gets the exact amount.
Per payment
$1 to $1,000 equivalent. In wARS, 1,500 to 1,500,000.
C
Mandate
Who signs
The payer, once: an approval and a schedule with the receiver, amount, cadence, count and expiry.
Each payment
Sent by Remesso's executor agent when due. Remesso pays that gas.
Remesso's fee
0.25% per payment, added on top.
Per payment
$1 to $1,000 equivalent, as for B.
Fig. 4
A monthly mandate
For a recurring request, the payer signs one mandate. Remesso's executor agent sends each payment when it's due, and only the payer can stop it.
Swipe sideways to see the whole figure.
Transaction on Celo, signed by its sender
Call to Remesso or a webhook, free
Reads the chain, no key
Fig. 5
When to deliver
Every payment produces two signed webhooks. Which one you act on depends on whether you could take the delivery back.
Swipe sideways to see the whole figure.
on payment.receivedDeliver what you can take back: an API answer, a file, a translated page.
on payment.finalizedDeliver what you can't: a cash-out, shipped goods, a payout to someone else.
Measured on Celo over 12.5 hours: Celo's finalized block ran a median of 23 minutes behind the newest block, 31 at most, and no block was replaced. If a reorg ever undid a payment after payment.received, Remesso would send payment.removed.
The code
What each side writes
Both sides use the same package: npm install remesso-sdk viem. These are the calls from Fig. 2.
Receiving agent
import { createRemesso, webhookHandler } from"remesso-sdk";
const seller = createRemesso({ account }); // the agent's own key// 1. Ask the wallet whose money will moveconst req = await seller.requests.create({
payer, amount: "1500", token: "wARS", runs: 1, note: "Order 1042",
});
// 2. Serve the handler at your URL, then subscribe itlet secret: string | undefined;
const handler = webhookHandler({ recipient: seller.address, secret: () => secret, onPayment });
secret = (await seller.webhooks.subscribe({ url: "https://agent.example/remesso" })).secret;
// 3. Before delivering, check the payment on Celo yourselfconst proof = await createRemesso().receipts.verify({
txHash, from: payer, to: seller.address, token: "wARS", amount: "1500",
policyId, memo: req.reference, // or scheduleId, for a wallet payment or a mandate
finality: "finalized",
});
// store proof.eventId once, then deliver
Paying agent
import { createRemesso } from"remesso-sdk";
import { fileRemittanceStore, fileStore } from"remesso-sdk/node";
// The agent's own key, with journals so a retry never pays twiceconst buyer = createRemesso({
account,
store: fileStore("./state/policy-payments.json"),
remittanceStore: fileRemittanceStore("./state/wallet-payments.json"),
});
// Once, signed in the person's own walletconst { id: policyId } = await person.policies.create({
agent: buyer.address, token: "wARS",
perPayment: "2000", perDay: "5000", days: 30, budget: "20000",
});
// Each time: read the person's inbox and pay the requestconst [r] = await buyer.requests.list(person.address);
const sent = await buyer.remittances.send({
funding: "policy", policyId, to: r.to, amount: "1500", token: "wARS",
requestId: r.id, idempotencyKey: `request:${r.id}`,
});
// "pending" can still be paid: call send again with the same key
account is a viem account for the agent's key. person is a Remesso client in the person's own wallet, for example a browser wallet in your app. People can also set a limit at remesso.xyz/agent-wallet.
Before going live
What an integrator plans for
Keep the journals.They make a retry safe after a crash or a timeout. Use fileStore for one process, and Postgres when several workers share one key. A retry under a new key is a second payment.
Hold gas in the right token.USDT, USDC, USDm and USA₮ can pay their own gas. wFIAT and cNGN can't, so an agent paying in them holds CELO. On 28 Oct a wARS wallet payment needed about 0.34 CELO in the agent, because the SDK wants twice the gas estimate before it signs.
Pick the webhook you deliver on.Fig. 5. Store proof.eventId under a unique key, so one payment can never fulfil two orders.
Test on a local copy of mainnet.npx remesso-sdk dev --smoke forks Celo with funded test agents. There is no testnet, and the SDK signs only on Celo mainnet. The local backend takes one-off requests only and never sends payment.finalized.
Leave cash-out to the receiver.Ripio's ramp for wARS, wBRL and the other wFIAT, and Textile for naira, each into the receiver's own account.
Without TypeScript
Other ways in
Any language
The HTTP API (request-payment, payment-events, webhooks) needs no API key. Subscribing takes an EIP-712 signature from the receiving address. Deliveries follow Standard Webhooks, and payments are plain calls to the two contracts.
Agent hosts
npx -y remesso-wallet gives Claude Code, Codex or Cursor tools such as pay, request_payment and limits. Claude's apps use the connector at https://remesso.xyz/mcp.
Coding assistants
The docs are also published as llms.txt and as the remesso-sdk skill, so an assistant writes the integration from the same pages.
On Celo mainnet, 28 Oct 2026
All three, run in wARS
For each one the request appeared in the payer's inbox, Remesso bound the payment to it, the receiver got signed payment.received and payment.finalized, and receipts.verify confirmed it finalized with no key.
No person has audited RemessoExecutorV5 or RemessoAgentAllowance.
Schedules created outside the app, including the one behind each wallet payment, are found by scanning schedule ids, and that scan falls behind as schedules pile up. The fix is to read the schedule_created events the indexer already records instead.