Worlds / Payments and billing
Recurly API
A local Recurly with accounts, subscriptions, invoices, coupons and a dunning campaign for failed renewals. Test the agent that works past-due accounts without double charging or expiring good customers.
- Base path
/- Auth
- Basic auth with API key as username, the world key
- Endpoints
- 18
- Status
- Active today
This reference previews the surface the Recurly world serves in the closed beta. Paths mirror the public Recurly 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_RECURLY_URL | This world's origin followed by / |
WORLDS_API_KEY | The world key, accepted wherever Recurly expects a credential |
WORLDS_WORLD_ID | The isolated world's identity |
import recurly from "recurly";
const client = new recurly.Client(process.env.WORLDS_API_KEY, {
baseUrl: process.env.WORLDS_RECURLY_URL,
});
const sub = await client.getSubscription("uuid-123");
await client.cancelSubscription(sub.id);API reference
Accounts
Customer accounts that own subscriptions and invoices.
- POST
/accountsCreate an account - GET
/accounts/{account_id}Fetch an account - PUT
/accounts/{account_id}Update an account - DELETE
/accounts/{account_id}Deactivate an account - GET
/accountsList accounts
Fields · 4
id | string | Account id |
code | string | Your account code |
email | string | Billing email |
state | string | active or inactive |
Subscriptions
Plans billed on a schedule.
- POST
/subscriptionsCreate a subscription - GET
/subscriptions/{subscription_id}Fetch a subscription - PUT
/subscriptions/{subscription_id}Update a subscription - PUT
/subscriptions/{subscription_id}/cancelCancel a subscription - PUT
/subscriptions/{subscription_id}/pausePause a subscription
Fields · 5
id | string | Subscription id |
state | string | active, canceled, expired, future or paused |
plan | object | Plan code and name |
quantity | integer | Units |
current_period_ends_at | datetime | Period end |
Invoices
Billing documents with line items and payment state.
- GET
/invoices/{invoice_id}Fetch an invoice - PUT
/invoices/{invoice_id}/collectCollect an invoice - PUT
/invoices/{invoice_id}/voidVoid an invoice - POST
/invoices/{invoice_id}/refundRefund an invoice - GET
/invoicesList invoices
Fields · 5
id | string | Invoice id |
number | string | Invoice number |
state | string | pending, past_due, paid, failed or voided |
total | number | Total |
balance | number | Amount outstanding |
Transactions
Gateway attempts against invoices.
- GET
/transactions/{transaction_id}Fetch a transaction - GET
/transactionsList transactions - POST
/transactions/{transaction_id}/voidVoid a transaction
Fields · 4
id | string | Transaction id |
type | string | purchase, refund or authorization |
status | string | success, declined or void |
amount | number | Amount |
Test workflow
- Prepare. Select the Recurly setup for your workflow and review its starting records, including accounts, subscriptions, invoices.
- 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
- inv-3301 collected with one new transaction
- inv-3290 marked paid by an external transaction
- inv-3304 and inv-3298 still past_due
- No subscription moved to expired
- No invoice charged more than once
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 · Recurly
version: 2
connector: recurly
seed: recurly-starter
mode: isolated
policy: >
Work the past-due list. Retry any invoice where the card was updated, and
record Lumen Ink's check. Leave everything else in the campaign to keep
retrying.
tasks:
- id: retry-a-past-due-invoice-after-a-card-update
prompt: Retry a past-due invoice after a card update
- id: redeem-a-coupon-on-the-right-account
prompt: Redeem a coupon on the right account
- id: pause-or-cancel-a-renewal
prompt: Pause or cancel a renewal
expected:
- inv-3301 collected with one new transaction
- inv-3290 marked paid by an external transaction
- inv-3304 and inv-3298 still past_due
- No subscription moved to expired
- No invoice charged more than once
scenarios:
- declined
- rate-limited
- duplicate-webhookSee 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 |
|---|---|
declined | Collection attempt returns a declined transaction error |
rate-limited | API returns 429 when retrying in a loop |
duplicate-webhook | failed_payment_notification arrives twice |
validation | Redeeming an expired coupon returns 422 |
Starting data
Start each run from the same records and relationships. The overview below describes the Recurly starter; use the setup supplied for your workflow when preparing your own snapshot.
| Records | Starting setup |
|---|---|
| accounts | 110 with billing info, 9 with expired cards |
| subscriptions | 100 active, 6 in_trial, 4 paused, 3 expired |
| invoices | 14 past_due inside the dunning campaign |
| coupons | SAVE15 single use, ANNUAL2 for yearly plans |
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.
Accounts records
Accounts
Customer accounts that own subscriptions and invoices.
| Field | Type | Meaning / relationship |
|---|---|---|
id | string | Account id |
code | string | Your account code |
email | string | Billing email |
state | string | active or inactive |
{
"id": "<Account id>",
"code": "<Your account code>",
"email": "person@example.test",
"state": "<active or inactive>"
}Subscriptions records
Subscriptions
Plans billed on a schedule.
| Field | Type | Meaning / relationship |
|---|---|---|
id | string | Subscription id |
state | string | active, canceled, expired, future or paused |
plan | object | Plan code and name |
quantity | integer | Units |
current_period_ends_at | datetime | Period end |
{
"id": "<Subscription id>",
"state": "<active, canceled, expired, future or paused>",
"plan": {},
"quantity": 1,
"current_period_ends_at": "<Period end>"
}Invoices records
Invoices
Billing documents with line items and payment state.
| Field | Type | Meaning / relationship |
|---|---|---|
id | string | Invoice id |
number | string | Invoice number |
state | string | pending, past_due, paid, failed or voided |
total | number | Total |
balance | number | Amount outstanding |
{
"id": "<Invoice id>",
"number": "<Invoice number>",
"state": "<pending, past_due, paid, failed or voided>",
"total": 1,
"balance": 1
}Transactions records
Transactions
Gateway attempts against invoices.
| Field | Type | Meaning / relationship |
|---|---|---|
id | string | Transaction id |
type | string | purchase, refund or authorization |
status | string | success, declined or void |
amount | number | Amount |
{
"id": "<Transaction id>",
"type": "<purchase, refund or authorization>",
"status": "<success, declined or void>",
"amount": 1
}