Two weeks ago I wrote about letting an AI agent pay my children's kindergarten. The agent did everything: read the invoices, checked them, prepared the payments. Then it stopped and waited for me, because my bank has no way to let software pay on my behalf without my tap on every batch.
Since then I have been reading what a business gets. Walletory, a Singapore e-money company, gives business customers an API to their account. Disclosure: Purple Technology, which publishes Hello Purple, and Walletory share some owners. I read its documentation with one question: if my agent held this key instead of my bank token, what could it do for a small company, and where would a person still be needed?
Almost everything, with nobody in the loop. The one place a person still says yes is exactly where it should be.
The API comes in two versions. Version 1 is live, and a business that shares owners with Purple Technology already uses it. Version 2 is in development, first for Linked Wallets and later for Hello Purple's own use cases, and in its first phase it serves businesses only. Personal accounts stay out of both, because for a person the law requires their own confirmation.
What it unlocks
Picture a ten-person company that buys parts in Japan and Germany, sells to customers in Singapore, and has one person doing the books on Friday afternoons. An agent holds the key to its account.
Paying suppliers while everyone sleeps. An invoice arrives from Tokyo at two in the morning. The agent reads it, checks that the wallet has enough yen, and sends the payment. Walletory takes care of the route: a payment to Japan in yen goes by the Japanese domestic system, a payment to Germany in euro goes by SEPA, a payment to the United States in dollars goes by SWIFT. The agent never picks the route, only fills in what that route needs. For Japan that includes the supplier's name and bank branch written in Katakana, the sort of detail people get wrong and software does not. By the time the office opens, the payment is on its way and the agent has read back the confirmation.
Books that close themselves. The same key reads every wallet's balance, with pending items already deducted, and every movement in and out, marked paid, pending or returned, with the counterparty and the exchange rate where one applied. The agent can match each payment it sent against what actually left, flag anything that did not arrive, and hand the Friday bookkeeper a finished statement instead of a pile of receipts.
Paying another Walletory business in an instant. A retainer to a design studio that also banks on Walletory moves wallet to wallet, and the agent reads back "paid" moments later. Paying an ordinary Singapore bank account from the business wallet is planned for version 2.
Never paying twice. In version 1 this stays the agent's job. The same request sent twice creates two payments, so the ledger my kindergarten agent keeps against double-paying carries over as it is. Version 2 requires an x-idempotency-key header on every payment, and a repeat with the same key is stopped.
Getting paid: where the customer says yes
The key can also ask for money.
The agent can ask a customer for money: an amount, a note, addressed to the email the customer uses on Walletory. The customer gets a notification, opens their own account, and approves or declines with the same two-factor step that already guards their money. The request expires on its own if nobody answers. The agent can withdraw it while the customer is still thinking, and not a second after they say yes.
Nothing in the API lets the agent skip that yes. This is the exact shape I wished my bank had offered me: a specific person, on their own device, agreeing to a specific amount, and that agreement is what moves the money. When an account becomes programmable, the human tap does not disappear. It moves to the person whose money is leaving.
How the key works
Walletory issues the business a key. The key works only from the computer addresses the business names in advance, so the agent has to live somewhere fixed, a server rather than a laptop. In version 1 it is one simple key with full access. From that address, the agent can read everything and pay or ask for anything. The key does not expire, and Walletory switches it off by hand when asked.
Version 2 is designed around scopes, so each integration can be given only the access it needs. Walletory does not convert currency, so a business that pays in yen keeps a yen wallet. It does not call the agent when a payment settles; the agent asks. And a payment request reaches only people who already hold a Walletory account.
Until scoped keys arrive, the rules about what the agent may pay have to live in the agent. The ones we built into the kindergarten agent carry over unchanged: a list of known payees, a ledger of what has been paid, a limit per payment and per day, and a refusal to retry anything whose outcome is unclear.
Two doors, one lesson
On the personal side, the permission does not exist, so my signature stands in for it. On the business side, the permission exists, and in version 1 it is a switch: the key is in or out. The payment request shows what both sides actually want, a yes with an amount and an expiry, held by the person whose money it is.
Since I know the people who build it, I will say what I would want as an engineer, which is not the same as what is planned: a key that can say how much, to whom, and until when. The building blocks are already on the page.
If you run a business, the question to ask of your own bank is the one this piece asked of Walletory. Could software hold the key without a person? What exactly would it be allowed to do? And where, if anywhere, does a human still say yes, and is it the right human? An agent pointed at the appendix below can answer all three for this account in a minute. Ask it the same about yours.
This article is information and commentary. It is not investment advice, not a personal recommendation and not investment research, it takes no account of your circumstances, and it must not be relied on as a reason to trade. Any figure shown is historical or simulated and is not an indication of future results.
Get the next piece the day it is published.
One email when a new report lands, nothing else.
Exact figures, sources, steps and terms behind this piece, written for the coding agent you point at it.
Quote freely with attribution: name the author, Hello Purple and the canonical URL, with the publication date, all of which are in the Markdown twin’s front matter. The twin is the reference text of the piece.
Read the appendix
Facts and figures
- API: Walletory Business Customer API. Two sources, which do not fully agree: the OpenAPI 3.0.0 specification file
wlt-customer-api.yaml, version 1.0.0, as circulated in January 2026; and the documentation pages in Walletory's knowledge base, last edited between 2026-03-20 and 2026-08-27. Where they differ, the difference is stated below. - Base path:
/customer-api/v1onmy.walletory.com(production),my.staging.walletory.net(staging),my.develop.walletory.net(development). - Authentication:
Authorization: Bearer <api_key>on every request, HTTPS only. Keys are generated and revoked by hand by Walletory, stored as hashes, and do not expire. Access is limited to pre-approved IP addresses; a request from another address is answered 403. - Data model: adapted from the UK Open Banking Standard v4.0. Errors return an
Errorsarray withErrorCode(four-character Open Banking code such as U001),MessageandPath. - Read endpoints (specification and documentation):
GET /accounts;GET /accounts/{AccountId}/balances(balance type ITAV, interim available);GET /accounts/{AccountId}/transactionswithfromBookingDateTimeandtoBookingDateTimein UTC, maximum window 90 days per call, paginated withLinksandMeta.TotalPages. Transaction status values: BOOK, PDNG, RJCT. A transaction carriesTransactionInformation(free text),Amount,CreditorAccount,DebtorAccountand, on cross-currency entries,CurrencyExchangewithSourceCurrency,ExchangeRateand optionallyTargetCurrency. There is no remittance-reference field on a transaction. - Push endpoints (specification and documentation):
POST /domestic-payments(Walletory wallet to Walletory wallet today; transfers to Singapore bank accounts are planned for version 2) andGET /domestic-payments/{DomesticPaymentId};POST /international-paymentsandGET /international-payments/{InternationalPaymentId}. Both return 201 with a payment identifier. Version 1 has no duplicate protection: the same request sent twice creates two payments. Version 2 requires anx-idempotency-keyheader that stops duplicates (Walletory, 2026-09-23). - Payment statuses, domestic: PDNG (debited, processing), ACSP, RJCT (returned, final). The specification glosses ACSP as "accepted for processing"; the documentation (2026-05-27) glosses it as credited to the payee and final.
- Payment statuses, international: PDNG, ACSP (accepted for further processing), ACWP (sent to the beneficiary bank, final), RJCT (returned, final). ACWP appears only in the documentation; the January specification's enum is PDNG, ACSP, RJCT.
- International rails: SWIFT (all supported currencies), SEPA (EUR), Japan local (JPY), Philippines local (PHP). The rail is chosen by Walletory from destination country and currency; a payment that qualifies for a local scheme cannot be sent by SWIFT.
CurrencyOfTransfermust equal the debtor wallet's currency; no foreign exchange. - Identification schemes:
SG.Walletory.WalletId,SG.Walletory.Email,UK.OBIE.IBAN,UK.OBIE.BBANfor accounts;UK.OBIE.BICFIandSG.Walletory.JapanBankfor banks. - SEPA requires an IBAN (
UK.OBIE.IBAN), the creditor's street, town and country, and a remittance reference. SWIFT requiresChargeBearer(BorneByDebtor, BorneByCreditor or Shared), the beneficiary bank's BIC (UK.OBIE.BICFI) and the creditor's postal address; the reference is optional. - Japan local requires
CreditorAgentwith schemeSG.Walletory.JapanBank, the bank code and the bank name in Katakana, plusSupplementaryData.CreditorwithBankBranchName(Katakana),BankBranchCode,BankAccountType(フツウ or トウザ) and, per the requirements table of 2026-08-27,NameKana. The January specification'sSupplementaryData.Creditorobject does not includeNameKanaand refuses unknown properties; the two sources conflict on this field. - Pull endpoints (documentation only, page last edited 2026-06-19; not present in the January specification file):
POST /payment-requests(debtor identified bySG.Walletory.Email, creditor wallet must belong to the caller),GET /payment-requests/{PaymentRequestId},GET /payment-requestswithstatusandpagefilters,DELETE /payment-requests/{PaymentRequestId}(only while PDNG). Statuses PDNG, ACTC (debtor approved, payment being created), ACSP (paid;DomesticPaymentIdpopulated), RJCT withStatusReasonDeclined, Canceled, Expired or Failed. Requests carry an expiration timestamp. The number of pending requests to one debtor from one caller is limited; excess returns 429. - Debtor approval happens in Walletory's own interface through the existing accept flow with 2FA. The API cannot bypass it.
- Wallet types:
AccountCategoryBusiness or Personal;AccountTypeCodeCACC (regular wallet) or OTHR (protected wallet with restricted transfers, used for Walletory Bridge).
Steps to reproduce
How an agent works against this API, as the documents describe it. Every step presumes a key already issued to a business and an agent running at the address registered with it.
- The agent sends every request over HTTPS with the bearer header and
Accept: application/json, from the registered address. - It lists wallets, picks the wallet whose currency matches the payment, and reads its interim available balance before initiating.
- For an international payment it chooses the rail from the requirements table by destination country and currency, fills that rail's required fields under
Data.Initiation, and posts once. A post whose response was lost is not retried; the agent reads the wallet's transactions for the window and matches on amount, counterparty and booking time, since no reference field is specified on a transaction. - It polls the payment's GET endpoint until a final status: ACSP or RJCT for a wallet-to-wallet payment; ACWP or RJCT for an international payment per the documentation, ACSP or RJCT per the January specification.
- For a pull payment it posts a payment request to the customer's Walletory email and polls its GET endpoint. ACTC means the customer has approved and the request can no longer be cancelled; RJCT carries
StatusReason. - It reconciles by reading transactions in windows of at most 90 days, in UTC, and matching on amount, counterparty and booking time.
Limits
- Version 1: one key grants every endpoint. No scopes, no read-only keys, no per-wallet keys, no amount ceilings, no expiry. Revocation is manual. Version 2, in development, is designed with scoped access.
- Access only from pre-approved IP addresses.
- No foreign exchange: the transfer currency must equal the wallet currency.
- Domestic payments are Walletory wallet to Walletory wallet; transfers to Singapore bank accounts are planned for version 2.
- No webhooks or callbacks; all status is read by polling.
- Transaction queries cover at most 90 days per call, in UTC, and carry no remittance-reference field.
- Payment requests reach only holders of a Walletory account, identified by email.
- Rate limits apply; the documentation does not publish the numbers.
Sources and links
- Walletory Business Customer API specification, OpenAPI 3.0.0, version 1.0.0, file
wlt-customer-api.yaml, as circulated inside Purple Group in January 2026. Not publicly linkable. - Walletory Business Customer API documentation (overview, account and transaction endpoints, payment endpoints, payment request endpoints, international payment requirements by payment method), Walletory knowledge base, last edited 2026-08-27. Internal to Purple Group; not publicly linkable.
- Walletory product team review of this piece, 2026-09-23: version 1 is live and version 2 is in development; duplicate protection and scoped access in version 2. Not publicly linkable.
- UK Open Banking Standard, the data model this API adapts: https://standards.openbanking.org.uk/
- Open Banking error code sets referenced by the API: https://github.com/OpenBankingUK/External_Internal_CodeSets
- The personal-side piece this follows: https://hello-purple.com/reports/the-agent-was-ready-the-bank-wasnt/
Terms
- Bearer key: a secret string sent in the Authorization header; whoever holds it and calls from an allowed address is the business.
- IP allowlist: the set of network addresses from which a key may be used; any other address is refused.
- Interim available balance (ITAV): the balance after pending items, the figure to check before a payment.
- Push payment: the caller sends money from its own wallet (domestic or international payment).
- Pull payment (payment request): the caller asks a Walletory customer for money; the customer approves in their own Walletory account.
- PDNG, ACSP, ACWP, RJCT, BOOK: Open Banking status codes for pending, accepted, sent to the beneficiary bank, rejected, and booked. ACTC is Walletory's mapping for a payment request the debtor has accepted.
About this piece
Written by Jan Cervinka, CTO of Purple Group, for Hello Purple, the map track. It describes the business API of Walletory, a Singapore e-money company, as read from its specification and documentation. Disclosure: Purple Technology, which publishes Hello Purple, and Walletory share some owners. The piece describes engineering; it is not financial advice and does not offer or invite the use of any payment service.
CEO of Purple Technology and CTO of Purple Group. Purple Technology is the 250-person engineering and operations company behind the group's regulated brokerage, prop-trading, e-money and payments businesses; the CTO seat covers architecture, engineering culture and AI adoption across five regulated entities. Has built Purple's technology since 2011, from a small development team to serverless infrastructure on AWS. Holds an MSc in Economics and Management from Brno International Business School and a bachelor's degree in Management and Psychology from NEWTON College. Writes here about what agents can actually do with money.
