---
title: "Hand the agent the company account"
standfirst: "My bank could not let an agent pay for me without my tap. A business account in Singapore can. Here is what that lets a small company do, and the one place a person still says yes."
author: "Jan Cervinka"
author_url: "https://hello-purple.com/authors/jan-cervinka/"
date_published: "2026-09-24T10:23:21.165Z"
canonical: "https://hello-purple.com/reports/hand-the-agent-the-company-account/"
track: "The Map"
layout: "essay"
publisher: "Hello Purple"
publisher_note: "Hello Purple is a technology publisher from Purple Technology. Its Reports describe what was built and how; they are not financial advice and do not offer or invite the use of any financial service."
llms_txt: "https://hello-purple.com/llms.txt"
interactive: "https://hello-purple.com/reports/hand-the-agent-the-company-account/interactive/"
---

# Hand the agent the company account

> My bank could not let an agent pay for me without my tap. A business account in Singapore can. Here is what that lets a small company do, and the one place a person still says yes.

*Interactive edition: Five payments an agent can make from a business account, the one that waits for a customer, and what a mistake could cost with and without rules. https://hello-purple.com/reports/hand-the-agent-the-company-account/interactive/*

## TL;DR

- Walletory's API is for business accounts. A company's agent can pay from one by itself, where my own bank needs my tap on every payment.
- One key lets an agent see the balances, pay a supplier in Tokyo or Berlin overnight, and tie every payment back to the bank statement, with nobody awake.
- Ask a customer for money and the picture flips: the agent asks, the customer says yes on their own phone, and only that yes moves the money.
- The version 1 key opens everything until Walletory switches it off. Version 2 will scope access per integration; until then the agent brings its own rules.
- Verdict: for businesses the door is open today. What is still missing is a key that can say how much, to whom, and until when.

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.

## For agents

### 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/v1` on `my.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 `Errors` array with `ErrorCode` (four-character Open Banking code such as U001), `Message` and `Path`.
- Read endpoints (specification and documentation): `GET /accounts`; `GET /accounts/{AccountId}/balances` (balance type ITAV, interim available); `GET /accounts/{AccountId}/transactions` with `fromBookingDateTime` and `toBookingDateTime` in UTC, maximum window 90 days per call, paginated with `Links` and `Meta.TotalPages`. Transaction status values: BOOK, PDNG, RJCT. A transaction carries `TransactionInformation` (free text), `Amount`, `CreditorAccount`, `DebtorAccount` and, on cross-currency entries, `CurrencyExchange` with `SourceCurrency`, `ExchangeRate` and optionally `TargetCurrency`. 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) and `GET /domestic-payments/{DomesticPaymentId}`; `POST /international-payments` and `GET /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 an `x-idempotency-key` header 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. `CurrencyOfTransfer` must equal the debtor wallet's currency; no foreign exchange.
- Identification schemes: `SG.Walletory.WalletId`, `SG.Walletory.Email`, `UK.OBIE.IBAN`, `UK.OBIE.BBAN` for accounts; `UK.OBIE.BICFI` and `SG.Walletory.JapanBank` for banks.
- SEPA requires an IBAN (`UK.OBIE.IBAN`), the creditor's street, town and country, and a remittance reference. SWIFT requires `ChargeBearer` (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 `CreditorAgent` with scheme `SG.Walletory.JapanBank`, the bank code and the bank name in Katakana, plus `SupplementaryData.Creditor` with `BankBranchName` (Katakana), `BankBranchCode`, `BankAccountType` (フツウ or トウザ) and, per the requirements table of 2026-08-27, `NameKana`. The January specification's `SupplementaryData.Creditor` object does not include `NameKana` and 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 by `SG.Walletory.Email`, creditor wallet must belong to the caller), `GET /payment-requests/{PaymentRequestId}`, `GET /payment-requests` with `status` and `page` filters, `DELETE /payment-requests/{PaymentRequestId}` (only while PDNG). Statuses PDNG, ACTC (debtor approved, payment being created), ACSP (paid; `DomesticPaymentId` populated), RJCT with `StatusReason` Declined, 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: `AccountCategory` Business or Personal; `AccountTypeCode` CACC (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.

1. The agent sends every request over HTTPS with the bearer header and `Accept: application/json`, from the registered address.
2. It lists wallets, picks the wallet whose currency matches the payment, and reads its interim available balance before initiating.
3. 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.
4. 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.
5. 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`.
6. 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.
