Worlds / Finance ops
Xero API
A local Xero organisation with bank feeds, statement lines, bills, invoices, contacts and a chart of accounts. Test the agent that reconciles the bank feed and codes transactions to the right accounts.
- Base path
/api.xro/2.0- Auth
- OAuth bearer token plus xero-tenant-id header, the world key
- Endpoints
- 16
- Status
- Active today
This reference previews the surface the Xero world serves in the closed beta. Paths mirror the public Xero API; the exact subset is confirmed when your workflow is scoped.
Connect
The run gives your agent these bindings. Keep your SDK; change only where it sends requests.
| binding | meaning |
|---|---|
WORLDS_XERO_URL | This world's origin followed by /api.xro/2.0 |
WORLDS_API_KEY | The world key, accepted wherever Xero expects a credential |
WORLDS_WORLD_ID | The isolated world's identity |
import { XeroClient } from "xero-node";
const xero = new XeroClient({
clientId: "client",
clientSecret: "secret",
redirectUris: ["http://localhost/cb"],
scopes: ["accounting.transactions"],
});
await xero.setTokenSet({ access_token: process.env.WORLDS_API_KEY });
xero.apiClient.basePath = process.env.WORLDS_XERO_URL;
const { body } = await xero.accountingApi.getInvoices("tenant-1");API reference
Invoices
Sales invoices and supplier bills.
- GET
/api.xro/2.0/InvoicesList invoices - PUT
/api.xro/2.0/InvoicesCreate invoices - POST
/api.xro/2.0/Invoices/{InvoiceID}Update an invoice - GET
/api.xro/2.0/Invoices/{InvoiceID}Get an invoice
Fields · 6
InvoiceID | string | Invoice id |
Type | string | ACCREC or ACCPAY |
Status | string | DRAFT, AUTHORISED, PAID or VOIDED |
Total | number | Total |
AmountDue | number | Amount due |
Contact | object | Contact reference |
Contacts
Customers and suppliers.
- GET
/api.xro/2.0/ContactsList contacts - PUT
/api.xro/2.0/ContactsCreate contacts - POST
/api.xro/2.0/Contacts/{ContactID}Update a contact
Fields · 4
ContactID | string | Contact id |
Name | string | Name |
EmailAddress | string | |
IsCustomer | boolean | Has sales invoices |
Payments
Payments applied to invoices.
- PUT
/api.xro/2.0/PaymentsCreate a payment - GET
/api.xro/2.0/PaymentsList payments - GET
/api.xro/2.0/Payments/{PaymentID}Get a payment
Fields · 5
PaymentID | string | Payment id |
Invoice | object | Invoice paid |
Account | object | Bank account |
Amount | number | Amount |
Date | date | Payment date |
Bank transactions
Spend and receive money items.
- GET
/api.xro/2.0/BankTransactionsList bank transactions - PUT
/api.xro/2.0/BankTransactionsCreate bank transactions - POST
/api.xro/2.0/BankTransactions/{BankTransactionID}Update a bank transaction
Fields · 4
BankTransactionID | string | Transaction id |
Type | string | SPEND or RECEIVE |
BankAccount | object | Bank account |
Total | number | Total |
Accounts
Chart of accounts.
- GET
/api.xro/2.0/AccountsList accounts - PUT
/api.xro/2.0/AccountsCreate an account - GET
/api.xro/2.0/Accounts/{AccountID}Get an account
Fields · 4
AccountID | string | Account id |
Code | string | Account code |
Name | string | Name |
Type | string | BANK, REVENUE, EXPENSE and more |
Test workflow
- Prepare. Select the Xero setup for your workflow and review its starting records, including invoices, contacts, payments.
- Connect. Configure your agent with this world's URL and key using the SDK example. Check that it reaches the intended API before running a test.
- Define. Describe the task, expected final changes and records that must stay untouched. Keep expected outcomes separate from the agent's instructions.
- Run and inspect. Use the dashboard or your workflow's generated CLI setup. Review final records and changes, then rerun from the same starting setup with the relevant failure conditions. Use Deployment and CI to automate the same workflow.
What to verify
- Oct 20 PIONEER SUPPLY matched to INV-778
- Oct 22 PIONEER SUPPLY not matched to the already paid INV-778
- AWS line coded to 429 Software with the right tax rate
- Stripe payout and transfer still unreconciled
- No transaction dated before the Sep 30 lock date
Test file
A task file names the jobs, the policy your agent is given and what the grader reads back from the world's final state. The agent never sees the expected outcomes.
# worlds/tasks.yaml · Xero
version: 2
connector: xero
seed: xero-starter
mode: isolated
policy: >
Reconcile last week's Business Cheque lines. Match supplier payments to
their bills and code card spend to the right accounts. Leave the Stripe
payout and the transfer for review.
tasks:
- id: reconcile-statement-lines-to-bills-and-invoices
prompt: Reconcile statement lines to bills and invoices
- id: code-a-bank-transaction-to-the-right-account-and-tax-rate
prompt: Code a bank transaction to the right account and tax rate
- id: approve-draft-bills-from-suppliers
prompt: Approve draft bills from suppliers
expected:
- Oct 20 PIONEER SUPPLY matched to INV-778
- Oct 22 PIONEER SUPPLY not matched to the already paid INV-778
- AWS line coded to 429 Software with the right tax rate
- Stripe payout and transfer still unreconciled
- No transaction dated before the Sep 30 lock date
scenarios:
- rate-limited
- validation
- token-expiredSee Tasks and outcomes for every field, and Deployment and CI to run the file on every pull request.
Failure conditions
Each one fires before the handler, at the same step on every run.
| condition | what the agent sees |
|---|---|
rate-limited | API returns 429 with X-Rate-Limit-Problem minute |
validation | A bill with a missing account code returns ValidationException |
token-expired | The access token expires after 30 minutes |
lock-date | Saving a transaction before the lock date is rejected |
Starting data
Start each run from the same records and relationships. The overview below describes the Xero starter; use the setup supplied for your workflow when preparing your own snapshot.
| Records | Starting setup |
|---|---|
| bank accounts | Business Cheque and Savings with live feeds |
| statement lines | 140, 26 unreconciled |
| invoices | ACCREC and ACCPAY across DRAFT, AUTHORISED and PAID |
| contacts | 90 customers and suppliers |
| lock date | Set to Sep 30 |
The record shapes below reuse this world's API field definitions. They show illustrative values and placeholders, not an importable seed. API responses and seed input can differ; include all required records and references in the accepted import format for your workflow.
Invoices records
Invoices
Sales invoices and supplier bills.
| Field | Type | Meaning / relationship |
|---|---|---|
InvoiceID | string | Invoice id |
Type | string | ACCREC or ACCPAY |
Status | string | DRAFT, AUTHORISED, PAID or VOIDED |
Total | number | Total |
AmountDue | number | Amount due |
Contact | object | Contact reference |
{
"InvoiceID": "<Invoice id>",
"Type": "<ACCREC or ACCPAY>",
"Status": "<DRAFT, AUTHORISED, PAID or VOIDED>",
"Total": 1,
"AmountDue": 1,
"Contact": {}
}Contacts records
Contacts
Customers and suppliers.
| Field | Type | Meaning / relationship |
|---|---|---|
ContactID | string | Contact id |
Name | string | Name |
EmailAddress | string | |
IsCustomer | boolean | Has sales invoices |
{
"ContactID": "<Contact id>",
"Name": "<Name>",
"EmailAddress": "person@example.test",
"IsCustomer": false
}Payments records
Payments
Payments applied to invoices.
| Field | Type | Meaning / relationship |
|---|---|---|
PaymentID | string | Payment id |
Invoice | object | Invoice paid |
Account | object | Bank account |
Amount | number | Amount |
Date | date | Payment date |
{
"PaymentID": "<Payment id>",
"Invoice": {},
"Account": {},
"Amount": 1,
"Date": "<Payment date>"
}Bank transactions records
Bank transactions
Spend and receive money items.
| Field | Type | Meaning / relationship |
|---|---|---|
BankTransactionID | string | Transaction id |
Type | string | SPEND or RECEIVE |
BankAccount | object | Bank account |
Total | number | Total |
{
"BankTransactionID": "<Transaction id>",
"Type": "<SPEND or RECEIVE>",
"BankAccount": {},
"Total": 1
}Accounts records
Accounts
Chart of accounts.
| Field | Type | Meaning / relationship |
|---|---|---|
AccountID | string | Account id |
Code | string | Account code |
Name | string | Name |
Type | string | BANK, REVENUE, EXPENSE and more |
{
"AccountID": "<Account id>",
"Code": "<Account code>",
"Name": "<Name>",
"Type": "<BANK, REVENUE, EXPENSE and more>"
}