Agentic Payments
Agent Pay gives your AI agents a guarded way to move money — within limits a human approved once. Collect takes money in; send pays money out. Contracts are AP2-aligned mandates; sends and off-session charges pause for Strong Customer Authentication. Atoa enforces every limit server-side.
Install
npm install @atoapayments/agent-pay # Node 22+
Setup
Get a sandbox API key from the Atoa dashboard and set it in your environment. Sandbox and production keys are separate.
export ATOA_API_KEY="your_sandbox_api_key"
Create a client and register your agent. Registration is idempotent. The ES256 key signs every request; here it’s generated in memory — in production, load it from your secrets manager or use a KMS signer. Both ways to supply credentials — env var vs. explicit — are covered in Authentication.
import atoa_agent_pay
private_key_pem, _ = atoa_agent_pay.generate_es256_keypair()
# api_key is read from ATOA_API_KEY; the public key is derived from private_key_pem.
atoa = atoa_agent_pay.init(environment="sandbox", private_key_pem=private_key_pem)
atoa.agent.register(name="Bookings assistant") # registers the derived public key
Receiving or sending?
- Customer present →
payment.collectreturns a pay-link/QR. No contract. → Collect - Customer not present →
payment.collectwith acontractId, under a COLLECT contract the customer approved once. → Collect - Paying out →
payment.sendunder a SEND contract the account owner approved once. → Send
Collect your first payment
Create a pay-link and wait for the result. In sandbox, open the link, pick the Atoa Test Bank, and choose the outcome yourself.
req = atoa.payment.collect(
amount={"amount": 45.00}, # decimal major units; GBP by default
order_id="booking-8812", # your own reference
)
print(req.payment_url) # open this and choose an outcome
settled = atoa.payment.await_settled(req.payment_request_id)
print(settled.status) # COMPLETED
Send your first payout
Create a SEND contract, approve it once at the authorizationUrl, then send. Every payout pauses for the business
owner’s approval (SCA) before money moves. In sandbox the recipient account decides the outcome — discover the
accounts with atoa.sandboxTestAccounts().
contract = atoa.contract.create(
type="SEND",
name="Supplier payouts",
limits={
"max_per_payment": 500.00,
"period_limits": [{"amount": 2000.00, "period": "MONTH"}],
"valid_to": "2026-12-31T23:59:59Z",
},
)
print(contract.authorization_url) # the account owner approves here
atoa.contract.await_active(contract.contract_id)
result = atoa.payment.send(
contract_id=contract.contract_id,
payments=[{
"amount": {"amount": 250.00},
"beneficiary": {"name": "ACME LTD", "sortCode": "040004", "accountNumber": "12345678"}, # sandbox: settles COMPLETED
"orderId": "payout-3001",
}],
)
print(result.next_action.approval_url) # the owner approves the payout here — in sandbox, open it yourself
atoa.payment.await_decision(result.next_action.approval_id) # APPROVED → the payment executes
print(result[0].status) # COMPLETED
Money moved in sandbox. The next_action approval step applies to every send and every off-session charge — see
Collect and Send.
Next
AI agents & tools
Hand the SDK to your model: the tool surface, the loop, and how a human approves.
Collect — money in
Pay-links, off-session charges, SCA, refunds.
Send — money out
Payouts, SCA, batches, contract limits.
Reference
Auth, methods, types, errors, sandbox, go-live.
Download the notebook · run it locally
The full flow as a runnable Jupyter notebook — pip install atoa-agent-pay, add a sandbox ATOA_API_KEY, run.