Pattern 1: Set Up a Complete Affiliate Program
This workflow creates a program, connects Stripe, checks readiness, publishes marketplace settings, and invites the first affiliates — everything a merchant needs to go live from the REST/SDK surface.import { AgentRef } from 'agentref';
const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });
// Step 1: Create the program
const program = await client.programs.create({
name: 'Acme Pro Referrals',
commissionType: 'recurring',
commissionPercent: 25,
cookieDuration: 60,
payoutThreshold: 5000, // $50.00 in cents
autoApproveAffiliates: true,
currency: 'USD',
}, { idempotencyKey: 'setup-acme-pro-v1' });
console.log(`Program created: ${program.id}`);
// Step 2: Connect Stripe
const stripe = await client.programs.connectStripe(program.id);
console.log(`Complete Stripe OAuth at: ${stripe.authUrl}`);
// The merchant opens this URL in a browser to connect their Stripe account
// Step 3: Check readiness
const detail = await client.programs.get(program.id);
console.log(`Readiness: ${detail.readiness}`);
// Step 4: Publish to marketplace
await client.programs.updateMarketplace(program.id, {
status: 'public',
category: 'SaaS',
description: 'Earn 25% recurring commission on every referral.',
});
// Step 5: Invite affiliates
const invite = await client.programs.createInvite(program.id, {
email: 'top-affiliate@example.com',
name: 'Top Affiliate',
expiresInDays: 14,
}, { idempotencyKey: 'invite-top-affiliate-v1' });
console.log(`Invite sent: ${invite.token}`);
// Step 6: Create a public invite link for broader distribution
const publicInvite = await client.programs.createInvite(program.id, {
isPublic: true,
usageLimit: 100,
expiresInDays: 30,
}, { idempotencyKey: 'public-invite-v1' });
from agentref import AgentRef
client = AgentRef() # reads AGENTREF_API_KEY from env
# Step 1: Create the program
program = client.programs.create(
name="Acme Pro Referrals",
commission_type="recurring",
commission_percent=25,
cookie_duration=60,
payout_threshold=5000, # $50.00 in cents
auto_approve_affiliates=True,
currency="USD",
idempotency_key="setup-acme-pro-v1",
)
print(f"Program created: {program.id}")
# Step 2: Connect Stripe
stripe = client.programs.connect_stripe(program.id)
print(f"Complete Stripe OAuth at: {stripe.auth_url}")
# Step 3: Check readiness
detail = client.programs.get(program.id)
print(f"Readiness: {detail.readiness}")
# Step 4: Publish to marketplace
client.programs.update_marketplace(
program.id,
status="public",
category="SaaS",
description="Earn 25% recurring commission on every referral.",
)
# Step 5: Invite affiliates
invite = client.programs.create_invite(
program.id,
email="top-affiliate@example.com",
name="Top Affiliate",
expires_in_days=14,
idempotency_key="invite-top-affiliate-v1",
)
print(f"Invite sent: {invite.token}")
# Step 6: Public invite link
public_invite = client.programs.create_invite(
program.id,
is_public=True,
usage_limit=100,
expires_in_days=30,
idempotency_key="public-invite-v1",
)
Pattern 2: Monitor Conversions and Flag Fraud
This workflow checks recent conversions, reviews fraud flags, and takes action on suspicious activity. Ideal for a scheduled agent task.import { AgentRef } from 'agentref';
const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });
// Step 1: Check conversion stats for the last 7 days
const stats = await client.conversions.stats({ period: '7d' });
console.log(`Last 7 days: ${stats.total} conversions, $${stats.totalRevenue / 100} revenue`);
console.log(`Pending: ${stats.pending}, Approved: ${stats.approved}`);
// Step 2: List recent conversions that need review
const { data: conversions } = await client.conversions.list({
status: 'pending',
limit: 50,
});
console.log(`${conversions.length} pending conversions to review`);
// Step 3: Check for open fraud flags
const flagStats = await client.flags.stats();
console.log(`Open fraud flags: ${flagStats.open}`);
if (flagStats.open > 0) {
const { data: flags } = await client.flags.list({
status: 'open',
limit: 20,
});
for (const flag of flags) {
console.log(`Flag ${flag.id}: ${flag.type} for affiliate ${flag.affiliateId}`);
// Step 4: Auto-dismiss low-risk flags, escalate high-risk
if (flag.type === 'high_click_frequency') {
// Get the affiliate's full stats for context
const affiliate = await client.affiliates.get(flag.affiliateId, {
include: 'stats',
});
if (affiliate.totalConversions > 0) {
// Has real conversions -- likely legitimate traffic
await client.flags.resolve(flag.id, {
status: 'dismissed',
note: `Auto-dismissed: ${affiliate.totalConversions} conversions confirm legitimate traffic`,
blockAffiliate: false,
}, { idempotencyKey: `resolve-${flag.id}` });
} else {
// No conversions -- suspicious, confirm the flag
await client.flags.resolve(flag.id, {
status: 'confirmed',
note: 'Zero conversions with high click volume -- confirmed suspicious',
blockAffiliate: true,
}, { idempotencyKey: `resolve-${flag.id}` });
}
}
}
}
from agentref import AgentRef
client = AgentRef()
# Step 1: Check conversion stats for the last 7 days
stats = client.conversions.stats(period="7d")
print(f"Last 7 days: {stats.total} conversions, ${stats.total_revenue / 100} revenue")
print(f"Pending: {stats.pending}, Approved: {stats.approved}")
# Step 2: List recent conversions that need review
result = client.conversions.list(status="pending", limit=50)
print(f"{len(result.data)} pending conversions to review")
# Step 3: Check for open fraud flags
flag_stats = client.flags.stats()
print(f"Open fraud flags: {flag_stats.open}")
if flag_stats.open > 0:
flags_result = client.flags.list(status="open", limit=20)
for flag in flags_result.data:
print(f"Flag {flag.id}: {flag.type} for affiliate {flag.affiliate_id}")
# Step 4: Auto-dismiss low-risk flags, escalate high-risk
if flag.type == "high_click_frequency":
affiliate = client.affiliates.get(flag.affiliate_id, include="stats")
if affiliate.total_conversions > 0:
client.flags.resolve(
flag.id,
status="dismissed",
note=f"Auto-dismissed: {affiliate.total_conversions} conversions confirm legitimate traffic",
block_affiliate=False,
idempotency_key=f"resolve-{flag.id}",
)
else:
client.flags.resolve(
flag.id,
status="confirmed",
note="Zero conversions with high click volume -- confirmed suspicious",
block_affiliate=True,
idempotency_key=f"resolve-{flag.id}",
)
Pattern 3: Generate Weekly Payout Report
This workflow lists pending payouts, aggregates stats, and generates a report. Useful for weekly cron jobs or scheduled agent tasks.import { AgentRef } from 'agentref';
const client = new AgentRef({ apiKey: process.env.AGENTREF_API_KEY });
// Step 1: Get payout stats
const payoutStats = await client.payouts.stats({ period: '30d' });
console.log(`Total paid (30d): $${payoutStats.totalPaid / 100}`);
console.log(`Total pending: $${payoutStats.totalPending / 100}`);
// Step 2: List all pending affiliates across programs
const pending = await client.payouts.listPending();
const report = {
generatedAt: new Date().toISOString(),
totalPending: pending.meta.total,
affiliates: pending.data.map(aff => ({
name: aff.name ?? aff.email,
program: aff.programName,
amount: `$${aff.pendingAmount / 100}`,
currency: aff.currency,
method: aff.payoutMethod ?? 'Not set',
meetsThreshold: aff.meetsThreshold,
commissionCount: aff.commissionCount,
})),
};
console.log('--- Weekly Payout Report ---');
console.log(JSON.stringify(report, null, 2));
// Step 3: For affiliates who meet the threshold and have a payout method,
// create the payout
const eligible = pending.data.filter(
aff => aff.meetsThreshold && aff.hasPayoutMethod
);
console.log(`\n${eligible.length} affiliates eligible for payout`);
for (const aff of eligible) {
const payout = await client.payouts.create({
affiliateId: aff.affiliateId,
programId: aff.programId,
method: aff.payoutMethod!,
notes: `Weekly payout - ${new Date().toISOString().split('T')[0]}`,
}, { idempotencyKey: `weekly-payout-${aff.affiliateId}-${Date.now()}` });
console.log(`Created payout for ${aff.name}: $${aff.pendingAmount / 100}`);
}
// Step 4: Get recent completed payouts for the report footer
const { data: recentPayouts } = await client.payouts.list({
status: 'completed',
limit: 10,
});
console.log(`\nRecent completed payouts: ${recentPayouts.length}`);
from datetime import datetime
from agentref import AgentRef
client = AgentRef()
# Step 1: Get payout stats
payout_stats = client.payouts.stats(period="30d")
print(f"Total paid (30d): ${payout_stats.total_paid / 100}")
print(f"Total pending: ${payout_stats.total_pending / 100}")
# Step 2: List all pending affiliates across programs
pending = client.payouts.list_pending()
report = {
"generated_at": datetime.now().isoformat(),
"total_pending": pending.meta.total,
"affiliates": [
{
"name": aff.name or aff.email,
"program": aff.program_name,
"amount": f"${aff.pending_amount / 100}",
"currency": aff.currency,
"method": aff.payout_method or "Not set",
"meets_threshold": aff.meets_threshold,
"commission_count": aff.commission_count,
}
for aff in pending.data
],
}
print("--- Weekly Payout Report ---")
import json
print(json.dumps(report, indent=2))
# Step 3: Create payouts for eligible affiliates
eligible = [
aff for aff in pending.data
if aff.meets_threshold and aff.has_payout_method
]
print(f"\n{len(eligible)} affiliates eligible for payout")
today = datetime.now().strftime("%Y-%m-%d")
for aff in eligible:
payout = client.payouts.create(
affiliate_id=aff.affiliate_id,
program_id=aff.program_id,
method=aff.payout_method,
notes=f"Weekly payout - {today}",
idempotency_key=f"weekly-payout-{aff.affiliate_id}-{today}",
)
print(f"Created payout for {aff.name}: ${aff.pending_amount / 100}")
# Step 4: Recent completed payouts
recent = client.payouts.list(status="completed", limit=10)
print(f"\nRecent completed payouts: {len(recent.data)}")
Idempotency Patterns for Safe Agent Retries
AI agents may retry operations due to timeouts, network failures, or tool-calling loops. Idempotency keys ensure these retries are safe.Deterministic Keys
Generate idempotency keys from the operation’s intent, not random values:// Good: deterministic key based on intent
const key = `create-program-${programName}-${Date.now()}`;
// Better: based on a stable external identifier
const key = `invite-${email}-to-${programId}`;
// Best: includes a version for intentional re-runs
const key = `setup-acme-program-v2`;
# Good: deterministic key based on intent
key = f"create-program-{program_name}-{int(time.time())}"
# Better: based on a stable external identifier
key = f"invite-{email}-to-{program_id}"
# Best: includes a version for intentional re-runs
key = "setup-acme-program-v2"
Retry-Safe Workflows
When chaining multiple operations, use a unique key for each step:const workflowId = 'onboard-acme-2026-03';
// Each step gets its own scoped key
const program = await client.programs.create({
name: 'Acme Referrals',
commissionType: 'recurring',
commissionPercent: 25,
}, { idempotencyKey: `${workflowId}-create-program` });
await client.programs.createInvite(program.id, {
email: 'partner@example.com',
}, { idempotencyKey: `${workflowId}-invite-partner` });
// Review pending applications through the Applications API or MCP review_application tool.
// Use a separate key such as `${workflowId}-approve-application-${applicationId}`.
workflow_id = "onboard-acme-2026-03"
# Each step gets its own scoped key
program = client.programs.create(
name="Acme Referrals",
commission_type="recurring",
commission_percent=25,
idempotency_key=f"{workflow_id}-create-program",
)
client.programs.create_invite(
program.id,
email="partner@example.com",
idempotency_key=f"{workflow_id}-invite-partner",
)
# Review pending applications through the Applications API or MCP review_application tool.
# Use a separate key such as f"{workflow_id}-approve-application-{application_id}".
Error Handling Patterns
Graceful Degradation
When an agent encounters an error, it should attempt recovery before giving up:import { AgentRef, NotFoundError, RateLimitError, AgentRefError } from 'agentref';
const client = new AgentRef();
async function safeGetProgram(id: string) {
try {
return await client.programs.get(id);
} catch (error) {
if (error instanceof NotFoundError) {
// Program doesn't exist -- list all programs and pick the first
const { data } = await client.programs.list({ status: 'active', limit: 1 });
return data[0] ?? null;
}
if (error instanceof RateLimitError) {
// Wait and retry
await new Promise(r => setTimeout(r, error.retryAfter * 1000));
return await client.programs.get(id);
}
throw error;
}
}
async function safeResolveFlag(flagId: string) {
try {
await client.flags.resolve(flagId, {
status: 'reviewed',
note: 'Reviewed by automated agent',
}, { idempotencyKey: `auto-review-${flagId}` });
return { success: true };
} catch (error) {
if (error instanceof AgentRefError) {
return {
success: false,
error: error.code,
message: error.message,
requestId: error.requestId,
};
}
throw error;
}
}
from agentref import AgentRef, NotFoundError, RateLimitError, AgentRefError
import time
client = AgentRef()
def safe_get_program(program_id: str):
try:
return client.programs.get(program_id)
except NotFoundError:
# Program doesn't exist -- list all and pick the first
result = client.programs.list(status="active", limit=1)
return result.data[0] if result.data else None
except RateLimitError as e:
# Wait and retry
time.sleep(e.retry_after)
return client.programs.get(program_id)
def safe_resolve_flag(flag_id: str):
try:
client.flags.resolve(
flag_id,
status="reviewed",
note="Reviewed by automated agent",
idempotency_key=f"auto-review-{flag_id}",
)
return {"success": True}
except AgentRefError as e:
return {
"success": False,
"error": e.code,
"message": str(e),
"request_id": e.request_id,
}
Logging and Observability
Always capture therequestId from errors for debugging:
try {
await client.conversions.list({ status: 'invalid_status' });
} catch (error) {
if (error instanceof AgentRefError) {
console.error(`AgentRef error [${error.requestId}]: ${error.code} - ${error.message}`);
// Send to your observability platform
sentry.captureException(error, {
extra: { requestId: error.requestId, code: error.code },
});
}
}