1 · Before you start
You need an agent already connected to COLVO — see connect your own agent. Testing needs no Recharge account: COLVO simulates one. For production you need a Recharge account where you can create API tokens.
On Recharge COLVO can refund a charge, cancel a subscription (now — the next charge doesn’t happen), swap the product (from the next charge) and apply a discount code. Recharge has no end-of-period cancel and no real pause, so COLVO doesn’t offer those there.
2 · Run the Recharge scenarios
Open Test runs → Choose scenarios…, set Simulated provider to Recharge, pick scenarios and start. Your agent’s tools don’t change — it still proposes to COLVO, with Recharge’s numeric ids:
- A charge is the payment. Refunds name the charge in
payment_id(for example92110001). - A product swap is a plan change.
price_idis the product variant; useat: "now". - No idempotency keys. Lost response, no second refund checks there is exactly one refund at the end.
3 · Propose a product swap and a refund (Node and Python)
The same SDK calls as on Stripe — only the ids are Recharge’s.
import { Colvo, messageFor } from '@colvo/sdk';
// Backend (backend key): the subscription and charges this ticket may touch come from your systems.
const backend = new Colvo({ apiKey: process.env.COLVO_BACKEND_KEY });
const mandate = await backend.mandates.create({
project_id: process.env.COLVO_PROJECT_ID, source_request_id: ticket.id,
subject: { customer_id: '7001', subscription_ids: ['41200501'], payment_ids: ['92110001'] },
actions: ['subscription.change_plan', 'coupon.apply', 'subscription.cancel'],
limits: { currency: 'eur', max_amount_minor: 0, max_operations: 1, allowed_price_ids: ['44100001'],
change_plan_at: ['now'], allowed_coupons: ['WINBACK20'], cancel_modes_allowed: ['immediate'] },
});
// Agent (agent key): swap the product — applies from the next charge, nothing is charged today.
const colvo = new Colvo({ apiKey: process.env.COLVO_AGENT_KEY });
const op = await colvo.operations.propose({
mandate_id: mandate.mandate_id, source_request_id: ticket.id, action: 'subscription.change_plan',
parameters: { subscription_id: '41200501', price_id: '44100001', at: 'now' },
});
reply(messageFor(op));import os
from colvo import Colvo, message_for
colvo = Colvo(os.environ["COLVO_AGENT_KEY"])
# A partial refund on the last charge (the subscription keeps running).
op = colvo.operations.propose({
"mandate_id": mandate_id, "source_request_id": ticket_id, "action": "refund.create",
"parameters": {"payment_id": "92110001", "amount_minor": 2000, "currency": "eur"},
})
reply(message_for(op))4 · Connect your Recharge account
In Recharge → Apps & integrations → API tokens, create a token for COLVO with read/write on Subscriptions, Payments and Discounts, and read on Orders and Customers. In COLVO open your project → Add a connection → Recharge, paste the token and press Check and connect. COLVO reads the token’s scopes — nothing else — and then registers its own webhooks in Recharge, so there is nothing to copy. Remove any Recharge token from your agent.
5 · What happens to a real refund
Guard checks the proposal against the mandate — the charge must be one the mandate names. On ALLOW, COLVO refunds the charge once and reads Recharge back: VERIFIED when the charge’s refunded total matches. If Recharge’s answer is lost, COLVO never re-sends (Recharge has no idempotency keys): the operation becomes UNVERIFIABLE and an incident asks a person to check the charge.
Next: set refund limits and read a FAIL.