Skip to main content

Query Authorization Logs

Query all authorized transaction records with detailed information about card authorization attempts. This endpoint provides comprehensive visibility into all card transaction activity, including approved and declined authorizations, helping you monitor card usage, detect fraud, reconcile transactions, and troubleshoot payment issues.

Resource Access

Production (api.ahrvo.network)

POST https://api.ahrvo.network/card/issuance/api/issuing/transaction/v2/authorizations

Staging (gateway.ahrvo.network)

POST https://gateway.ahrvo.network/card/issuance/api/issuing/transaction/v2/authorizations

Authorization Logs Overview

Authorization logs provide real-time visibility into all card transaction attempts. Each authorization record captures:

  • Transaction Details: Date, amount, currency, merchant information
  • Authorization Result: Approved or declined status with failure reasons
  • Fee Breakdown: Processing fees, authorization fees, 3DS fees
  • Card Information: Card ID, masked card number, card remark
  • Reversal Tracking: Linked reversal transactions and dates
  • Multi-Currency Data: Both billing currency and transaction currency

Key Features

  • Real-Time Monitoring: Track card authorizations as they occur
  • Comprehensive Data: 20+ fields per authorization record
  • Flexible Filtering: Filter by date range, card ID, or pagination
  • Decline Analysis: Detailed failure reasons for declined transactions
  • Fee Transparency: Complete breakdown of all transaction fees
  • Reversal Tracking: Link reversals to original authorizations

Request Parameters

Query Parameters

ParameterTypeRequiredDescription
page_nointegerNoPage number (starting from 1, default: 1)
page_sizeintegerNoResults per page (max 100, default: 20)
start_datestringNoAuthorization start date (format: yyyy-MM-dd HH:mm:ss)
end_datestringNoAuthorization end date (format: yyyy-MM-dd HH:mm:ss)
card_idstringNoFilter by specific card ID

Header Parameters

ParameterTypeRequiredDescription
AuthorizationstringYesBearer token for authentication
x-api-keystringYesAPI key for authentication

Response

Response Body

FieldTypeDescription
codestringStatus code ('SUCCESS' for successful query)
data.total_numintegerTotal number of records matching query criteria
data.listarrayArray of authorization records

Authorization Record Fields

FieldTypeDescription
authorization_idstringUnique ID for this authorization
authorization_datestringAuthorization timestamp (yyyy-MM-dd HH:mm:ss)
card_idstringUnique ID of the card
card_numberstringMasked card number (e.g., 5157****8888)
remarkstringCard remark/label
merchant_namestringName of merchant
merchant_countrystringCountry of merchant
mccstringMerchant category code
billing_amountstringAmount in billing currency
billing_currencystringBilling currency code
transaction_amountstringAmount in merchant's currency
transaction_currencystringMerchant's currency code
authorization_typestringType: Auth, Purchase Return, or Reversal
authorization_statusstringStatus: APPROVED or DECLINED
approve_codestringApproval code from card network
fail_reasonstringDecline reason (if declined)
budget_idstringBudget account ID
rate_feestringTransaction processing fee
rate_fee_currencystringProcessing fee currency
auth_feestringAuthorization fee
auth_fee_currencystringAuthorization fee currency
threeds_feestring3D Secure authentication fee
threeds_fee_currencystring3DS fee currency
reversal_authorization_idstringRelated reversal authorization ID
reversal_txn_datestringReversal date (yyyy-MM-dd HH:mm:ss)

Use Cases

Use Case 1: Daily Transaction Monitoring Dashboard

Build a real-time dashboard to monitor daily card transaction activity across all cards.

curl -X GET "https://api.ahrvo.network/card/issuance/api/issuing/transaction/v2/authorizations?start_date=2026-02-07%2000:00:00&end_date=2026-02-07%2023:59:59&page_size=100" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-api-key: YOUR_API_KEY"

Python Implementation:

import requests
from datetime import datetime, timedelta
from collections import defaultdict

class TransactionMonitor:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def get_daily_summary(self, date=None):
"""Get daily transaction summary with approval/decline statistics"""
if date is None:
date = datetime.now().date()

start_date = f"{date} 00:00:00"
end_date = f"{date} 23:59:59"

headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_date": start_date,
"end_date": end_date,
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all pages
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
authorizations = data["data"]["list"]
all_authorizations.extend(authorizations)

# Check if there are more pages
total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
raise Exception(f"Failed to fetch authorizations: {data}")

# Calculate statistics
stats = {
"total_transactions": len(all_authorizations),
"approved_count": 0,
"declined_count": 0,
"total_volume": 0.0,
"approved_volume": 0.0,
"total_fees": 0.0,
"by_type": defaultdict(int),
"by_merchant": defaultdict(lambda: {"count": 0, "volume": 0.0}),
"decline_reasons": defaultdict(int)
}

for auth in all_authorizations:
# Count by status
if auth["authorization_status"] == "APPROVED":
stats["approved_count"] += 1
billing_amount = float(auth["billing_amount"])
stats["approved_volume"] += billing_amount
else:
stats["declined_count"] += 1
if auth.get("fail_reason"):
stats["decline_reasons"][auth["fail_reason"]] += 1

# Total volume
if auth["authorization_type"] == "Auth":
stats["total_volume"] += float(auth["billing_amount"])

# Count by type
stats["by_type"][auth["authorization_type"]] += 1

# Group by merchant
merchant = auth.get("merchant_name", "Unknown")
stats["by_merchant"][merchant]["count"] += 1
stats["by_merchant"][merchant]["volume"] += float(auth["billing_amount"])

# Sum fees
stats["total_fees"] += float(auth.get("rate_fee", 0))
stats["total_fees"] += float(auth.get("auth_fee", 0))
stats["total_fees"] += float(auth.get("threeds_fee", 0))

# Calculate rates
if stats["total_transactions"] > 0:
stats["approval_rate"] = (stats["approved_count"] / stats["total_transactions"]) * 100
stats["decline_rate"] = (stats["declined_count"] / stats["total_transactions"]) * 100

return stats

def print_dashboard(self, stats):
"""Print formatted dashboard"""
print("\n" + "="*60)
print(f"DAILY TRANSACTION SUMMARY - {datetime.now().strftime('%Y-%m-%d')}")
print("="*60)

print(f"\nOVERVIEW:")
print(f" Total Transactions: {stats['total_transactions']}")
print(f" Approved: {stats['approved_count']} ({stats.get('approval_rate', 0):.2f}%)")
print(f" Declined: {stats['declined_count']} ({stats.get('decline_rate', 0):.2f}%)")

print(f"\nVOLUME:")
print(f" Total Volume: ${stats['total_volume']:.2f}")
print(f" Approved Volume: ${stats['approved_volume']:.2f}")
print(f" Total Fees: ${stats['total_fees']:.2f}")

print(f"\nBY TYPE:")
for auth_type, count in stats['by_type'].items():
print(f" {auth_type}: {count}")

if stats['decline_reasons']:
print(f"\nDECLINE REASONS:")
for reason, count in sorted(stats['decline_reasons'].items(),
key=lambda x: x[1], reverse=True):
print(f" {reason}: {count}")

print(f"\nTOP MERCHANTS:")
sorted_merchants = sorted(stats['by_merchant'].items(),
key=lambda x: x[1]['volume'], reverse=True)[:5]
for merchant, data in sorted_merchants:
print(f" {merchant}: {data['count']} txns, ${data['volume']:.2f}")

# Usage
monitor = TransactionMonitor("your-api-key", "your-access-token")
stats = monitor.get_daily_summary()
monitor.print_dashboard(stats)

JavaScript Implementation:

class TransactionMonitor {
constructor(apiKey, accessToken) {
this.apiKey = apiKey;
this.accessToken = accessToken;
this.baseUrl = 'https://api.ahrvo.network/card/issuance';
}

async getDailySummary(date = null) {
const targetDate = date || new Date().toISOString().split('T')[0];
const startDate = `${targetDate} 00:00:00`;
const endDate = `${targetDate} 23:59:59`;

const headers = {
'Authorization': `Bearer ${this.accessToken}`,
'x-api-key': this.apiKey
};

let allAuthorizations = [];
let pageNo = 1;
const pageSize = 100;

// Fetch all pages
while (true) {
const params = new URLSearchParams({
start_date: startDate,
end_date: endDate,
page_size: pageSize,
page_no: pageNo
});

const response = await fetch(
`${this.baseUrl}/api/issuing/transaction/v2/authorizations?${params}`,
{ headers }
);

const data = await response.json();

if (data.code === 'SUCCESS') {
allAuthorizations.push(...data.data.list);

const totalNum = data.data.total_num;
const currentRecords = pageNo * pageSize;

if (currentRecords >= totalNum) break;
pageNo++;
} else {
throw new Error(`Failed to fetch authorizations: ${JSON.stringify(data)}`);
}
}

// Calculate statistics
const stats = {
total_transactions: allAuthorizations.length,
approved_count: 0,
declined_count: 0,
total_volume: 0,
approved_volume: 0,
total_fees: 0,
by_type: {},
by_merchant: {},
decline_reasons: {}
};

allAuthorizations.forEach(auth => {
// Count by status
if (auth.authorization_status === 'APPROVED') {
stats.approved_count++;
stats.approved_volume += parseFloat(auth.billing_amount);
} else {
stats.declined_count++;
if (auth.fail_reason) {
stats.decline_reasons[auth.fail_reason] =
(stats.decline_reasons[auth.fail_reason] || 0) + 1;
}
}

// Total volume
if (auth.authorization_type === 'Auth') {
stats.total_volume += parseFloat(auth.billing_amount);
}

// Count by type
stats.by_type[auth.authorization_type] =
(stats.by_type[auth.authorization_type] || 0) + 1;

// Group by merchant
const merchant = auth.merchant_name || 'Unknown';
if (!stats.by_merchant[merchant]) {
stats.by_merchant[merchant] = { count: 0, volume: 0 };
}
stats.by_merchant[merchant].count++;
stats.by_merchant[merchant].volume += parseFloat(auth.billing_amount);

// Sum fees
stats.total_fees += parseFloat(auth.rate_fee || 0);
stats.total_fees += parseFloat(auth.auth_fee || 0);
stats.total_fees += parseFloat(auth.threeds_fee || 0);
});

// Calculate rates
if (stats.total_transactions > 0) {
stats.approval_rate = (stats.approved_count / stats.total_transactions) * 100;
stats.decline_rate = (stats.declined_count / stats.total_transactions) * 100;
}

return stats;
}

printDashboard(stats) {
console.log('\n' + '='.repeat(60));
console.log(`DAILY TRANSACTION SUMMARY - ${new Date().toISOString().split('T')[0]}`);
console.log('='.repeat(60));

console.log('\nOVERVIEW:');
console.log(` Total Transactions: ${stats.total_transactions}`);
console.log(` Approved: ${stats.approved_count} (${stats.approval_rate?.toFixed(2)}%)`);
console.log(` Declined: ${stats.declined_count} (${stats.decline_rate?.toFixed(2)}%)`);

console.log('\nVOLUME:');
console.log(` Total Volume: $${stats.total_volume.toFixed(2)}`);
console.log(` Approved Volume: $${stats.approved_volume.toFixed(2)}`);
console.log(` Total Fees: $${stats.total_fees.toFixed(2)}`);

console.log('\nBY TYPE:');
Object.entries(stats.by_type).forEach(([type, count]) => {
console.log(` ${type}: ${count}`);
});

if (Object.keys(stats.decline_reasons).length > 0) {
console.log('\nDECLINE REASONS:');
Object.entries(stats.decline_reasons)
.sort((a, b) => b[1] - a[1])
.forEach(([reason, count]) => {
console.log(` ${reason}: ${count}`);
});
}

console.log('\nTOP MERCHANTS:');
Object.entries(stats.by_merchant)
.sort((a, b) => b[1].volume - a[1].volume)
.slice(0, 5)
.forEach(([merchant, data]) => {
console.log(` ${merchant}: ${data.count} txns, $${data.volume.toFixed(2)}`);
});
}
}

// Usage
const monitor = new TransactionMonitor('your-api-key', 'your-access-token');
const stats = await monitor.getDailySummary();
monitor.printDashboard(stats);

Topics Covered:

  • Multi-page result fetching
  • Approval/decline rate calculation
  • Transaction volume analysis
  • Fee aggregation across all types
  • Merchant activity grouping
  • Decline reason analysis
  • Real-time dashboard display

Use Case 2: Fraud Detection and Suspicious Activity Monitoring

Identify potentially fraudulent transactions by analyzing authorization patterns and decline reasons.

Python Implementation:

import requests
from datetime import datetime, timedelta
from collections import defaultdict

class FraudDetector:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def detect_suspicious_patterns(self, hours=24):
"""Detect suspicious transaction patterns in recent hours"""
end_date = datetime.now()
start_date = end_date - timedelta(hours=hours)

headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_date": start_date.strftime("%Y-%m-%d %H:%M:%S"),
"end_date": end_date.strftime("%Y-%m-%d %H:%M:%S"),
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all authorizations
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
all_authorizations.extend(data["data"]["list"])

total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
break

# Analyze patterns
suspicious_activity = {
"high_frequency_cards": [],
"multiple_countries": [],
"high_decline_rate": [],
"large_transactions": [],
"rapid_succession": []
}

# Group by card
by_card = defaultdict(list)
for auth in all_authorizations:
by_card[auth["card_id"]].append(auth)

# Detect patterns for each card
for card_id, auths in by_card.items():
auths_sorted = sorted(auths, key=lambda x: x["authorization_date"])

# Pattern 1: High frequency (>10 transactions in time period)
if len(auths) > 10:
suspicious_activity["high_frequency_cards"].append({
"card_id": card_id,
"card_number": auths[0]["card_number"],
"transaction_count": len(auths),
"total_amount": sum(float(a["billing_amount"]) for a in auths),
"remark": auths[0].get("remark")
})

# Pattern 2: Multiple countries
countries = set(a["merchant_country"] for a in auths if a.get("merchant_country"))
if len(countries) > 3:
suspicious_activity["multiple_countries"].append({
"card_id": card_id,
"card_number": auths[0]["card_number"],
"countries": list(countries),
"transaction_count": len(auths),
"remark": auths[0].get("remark")
})

# Pattern 3: High decline rate (>50%)
declined = sum(1 for a in auths if a["authorization_status"] == "DECLINED")
decline_rate = (declined / len(auths)) * 100 if auths else 0

if decline_rate > 50 and len(auths) > 3:
suspicious_activity["high_decline_rate"].append({
"card_id": card_id,
"card_number": auths[0]["card_number"],
"decline_rate": decline_rate,
"declined_count": declined,
"total_count": len(auths),
"decline_reasons": [a.get("fail_reason") for a in auths
if a["authorization_status"] == "DECLINED"],
"remark": auths[0].get("remark")
})

# Pattern 4: Large individual transactions (>$5000)
large_txns = [a for a in auths if float(a["billing_amount"]) > 5000]
if large_txns:
for txn in large_txns:
suspicious_activity["large_transactions"].append({
"card_id": card_id,
"card_number": txn["card_number"],
"amount": float(txn["billing_amount"]),
"currency": txn["billing_currency"],
"merchant": txn.get("merchant_name"),
"country": txn.get("merchant_country"),
"status": txn["authorization_status"],
"date": txn["authorization_date"],
"remark": txn.get("remark")
})

# Pattern 5: Rapid succession (>3 transactions within 5 minutes)
for i in range(len(auths_sorted) - 3):
time_window = auths_sorted[i:i+4]
first_time = datetime.strptime(time_window[0]["authorization_date"],
"%Y-%m-%d %H:%M:%S")
last_time = datetime.strptime(time_window[-1]["authorization_date"],
"%Y-%m-%d %H:%M:%S")

if (last_time - first_time).total_seconds() < 300: # 5 minutes
suspicious_activity["rapid_succession"].append({
"card_id": card_id,
"card_number": auths[0]["card_number"],
"transaction_count": len(time_window),
"time_span_seconds": (last_time - first_time).total_seconds(),
"total_amount": sum(float(a["billing_amount"]) for a in time_window),
"merchants": [a.get("merchant_name") for a in time_window],
"remark": auths[0].get("remark")
})
break # Only report once per card

return suspicious_activity

def print_fraud_report(self, activity):
"""Print formatted fraud detection report"""
print("\n" + "="*70)
print("FRAUD DETECTION REPORT")
print("="*70)

total_alerts = sum(len(v) for v in activity.values())
print(f"\nTotal Suspicious Activities Detected: {total_alerts}")

if activity["high_frequency_cards"]:
print(f"\n1. HIGH FREQUENCY CARDS ({len(activity['high_frequency_cards'])} alerts):")
for alert in activity["high_frequency_cards"]:
print(f" Card: {alert['card_number']} (ID: {alert['card_id']})")
print(f" Remark: {alert['remark']}")
print(f" Transactions: {alert['transaction_count']}")
print(f" Total Amount: ${alert['total_amount']:.2f}")
print()

if activity["multiple_countries"]:
print(f"\n2. MULTIPLE COUNTRIES ({len(activity['multiple_countries'])} alerts):")
for alert in activity["multiple_countries"]:
print(f" Card: {alert['card_number']} (ID: {alert['card_id']})")
print(f" Remark: {alert['remark']}")
print(f" Countries: {', '.join(alert['countries'])}")
print(f" Transactions: {alert['transaction_count']}")
print()

if activity["high_decline_rate"]:
print(f"\n3. HIGH DECLINE RATE ({len(activity['high_decline_rate'])} alerts):")
for alert in activity["high_decline_rate"]:
print(f" Card: {alert['card_number']} (ID: {alert['card_id']})")
print(f" Remark: {alert['remark']}")
print(f" Decline Rate: {alert['decline_rate']:.2f}%")
print(f" Declined/Total: {alert['declined_count']}/{alert['total_count']}")
print(f" Reasons: {', '.join(set(r for r in alert['decline_reasons'] if r))}")
print()

if activity["large_transactions"]:
print(f"\n4. LARGE TRANSACTIONS ({len(activity['large_transactions'])} alerts):")
for alert in activity["large_transactions"]:
print(f" Card: {alert['card_number']} (ID: {alert['card_id']})")
print(f" Remark: {alert['remark']}")
print(f" Amount: ${alert['amount']:.2f} {alert['currency']}")
print(f" Merchant: {alert['merchant']} ({alert['country']})")
print(f" Status: {alert['status']}")
print(f" Date: {alert['date']}")
print()

if activity["rapid_succession"]:
print(f"\n5. RAPID SUCCESSION ({len(activity['rapid_succession'])} alerts):")
for alert in activity["rapid_succession"]:
print(f" Card: {alert['card_number']} (ID: {alert['card_id']})")
print(f" Remark: {alert['remark']}")
print(f" Transactions: {alert['transaction_count']} in {alert['time_span_seconds']:.0f}s")
print(f" Total Amount: ${alert['total_amount']:.2f}")
print(f" Merchants: {', '.join(alert['merchants'])}")
print()

# Usage
detector = FraudDetector("your-api-key", "your-access-token")
suspicious_activity = detector.detect_suspicious_patterns(hours=24)
detector.print_fraud_report(suspicious_activity)

# Take action on high-risk cards
for alert in suspicious_activity["high_frequency_cards"]:
print(f"⚠️ ALERT: Consider freezing card {alert['card_id']}")

Topics Covered:

  • High frequency transaction detection
  • Multi-country transaction monitoring
  • Decline rate analysis
  • Large transaction alerts
  • Rapid succession pattern detection
  • Automated fraud reporting

Use Case 3: Card-Specific Authorization History

Track complete authorization history for a specific card to investigate issues or analyze spending patterns.

Python Implementation:

import requests
from datetime import datetime, timedelta

class CardAuthorizationHistory:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def get_card_history(self, card_id, days=30):
"""Get complete authorization history for a specific card"""
end_date = datetime.now()
start_date = end_date - timedelta(days=days)

headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"card_id": card_id,
"start_date": start_date.strftime("%Y-%m-%d %H:%M:%S"),
"end_date": end_date.strftime("%Y-%m-%d %H:%M:%S"),
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all pages
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
authorizations = data["data"]["list"]
all_authorizations.extend(authorizations)

total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
raise Exception(f"Failed to fetch card history: {data}")

return sorted(all_authorizations, key=lambda x: x["authorization_date"], reverse=True)

def analyze_card_activity(self, card_id, days=30):
"""Analyze authorization patterns for a card"""
authorizations = self.get_card_history(card_id, days)

if not authorizations:
return {
"card_id": card_id,
"message": "No authorization history found"
}

# Calculate statistics
approved = [a for a in authorizations if a["authorization_status"] == "APPROVED"]
declined = [a for a in authorizations if a["authorization_status"] == "DECLINED"]

# Total spending
total_spending = sum(float(a["billing_amount"]) for a in approved
if a["authorization_type"] == "Auth")

# Average transaction
avg_transaction = total_spending / len(approved) if approved else 0

# Total fees
total_fees = sum(
float(a.get("rate_fee", 0)) +
float(a.get("auth_fee", 0)) +
float(a.get("threeds_fee", 0))
for a in authorizations
)

# Merchants
merchants = {}
for auth in approved:
merchant = auth.get("merchant_name", "Unknown")
if merchant not in merchants:
merchants[merchant] = {
"count": 0,
"total": 0.0,
"countries": set()
}
merchants[merchant]["count"] += 1
merchants[merchant]["total"] += float(auth["billing_amount"])
if auth.get("merchant_country"):
merchants[merchant]["countries"].add(auth["merchant_country"])

# Decline analysis
decline_reasons = {}
for auth in declined:
reason = auth.get("fail_reason", "Unknown")
decline_reasons[reason] = decline_reasons.get(reason, 0) + 1

# Daily activity
daily_activity = {}
for auth in authorizations:
date = auth["authorization_date"].split()[0]
if date not in daily_activity:
daily_activity[date] = {"count": 0, "approved": 0, "declined": 0, "volume": 0.0}

daily_activity[date]["count"] += 1
if auth["authorization_status"] == "APPROVED":
daily_activity[date]["approved"] += 1
daily_activity[date]["volume"] += float(auth["billing_amount"])
else:
daily_activity[date]["declined"] += 1

return {
"card_id": card_id,
"card_number": authorizations[0]["card_number"],
"remark": authorizations[0].get("remark"),
"period_days": days,
"summary": {
"total_transactions": len(authorizations),
"approved_count": len(approved),
"declined_count": len(declined),
"approval_rate": (len(approved) / len(authorizations) * 100) if authorizations else 0,
"total_spending": total_spending,
"average_transaction": avg_transaction,
"total_fees": total_fees
},
"top_merchants": sorted(
merchants.items(),
key=lambda x: x[1]["total"],
reverse=True
)[:5],
"decline_reasons": decline_reasons,
"daily_activity": daily_activity,
"recent_transactions": authorizations[:10] # Last 10 transactions
}

def print_card_report(self, analysis):
"""Print formatted card analysis report"""
if "message" in analysis:
print(analysis["message"])
return

print("\n" + "="*70)
print(f"CARD AUTHORIZATION HISTORY REPORT")
print("="*70)

print(f"\nCard: {analysis['card_number']} (ID: {analysis['card_id']})")
print(f"Remark: {analysis['remark']}")
print(f"Period: Last {analysis['period_days']} days")

summary = analysis["summary"]
print(f"\nSUMMARY:")
print(f" Total Transactions: {summary['total_transactions']}")
print(f" Approved: {summary['approved_count']} ({summary['approval_rate']:.2f}%)")
print(f" Declined: {summary['declined_count']}")
print(f" Total Spending: ${summary['total_spending']:.2f}")
print(f" Average Transaction: ${summary['average_transaction']:.2f}")
print(f" Total Fees: ${summary['total_fees']:.2f}")

print(f"\nTOP MERCHANTS:")
for merchant, data in analysis["top_merchants"]:
countries = ', '.join(data["countries"])
print(f" {merchant} ({countries})")
print(f" Transactions: {data['count']}, Total: ${data['total']:.2f}")

if analysis["decline_reasons"]:
print(f"\nDECLINE REASONS:")
for reason, count in sorted(analysis["decline_reasons"].items(),
key=lambda x: x[1], reverse=True):
print(f" {reason}: {count}")

print(f"\nRECENT TRANSACTIONS (Last 10):")
for txn in analysis["recent_transactions"]:
status_symbol = "✓" if txn["authorization_status"] == "APPROVED" else "✗"
print(f" {status_symbol} {txn['authorization_date']} | "
f"${txn['billing_amount']} {txn['billing_currency']} | "
f"{txn.get('merchant_name', 'Unknown')} | "
f"{txn['authorization_status']}")

# Usage
history = CardAuthorizationHistory("your-api-key", "your-access-token")
analysis = history.analyze_card_activity("card202008281528548244", days=30)
history.print_card_report(analysis)

Topics Covered:

  • Card-specific filtering
  • Complete transaction history retrieval
  • Spending pattern analysis
  • Merchant frequency analysis
  • Decline reason tracking
  • Daily activity breakdown
  • Recent transaction display

Use Case 4: Fee Reconciliation and Cost Analysis

Calculate and reconcile all transaction fees across different fee types for accounting and cost analysis.

Python Implementation:

import requests
from datetime import datetime
from collections import defaultdict
import csv

class FeeReconciliation:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def get_fee_breakdown(self, start_date, end_date):
"""Get detailed fee breakdown for a date range"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_date": start_date,
"end_date": end_date,
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all authorizations
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
all_authorizations.extend(data["data"]["list"])

total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
raise Exception(f"Failed to fetch authorizations: {data}")

# Calculate fee breakdown
fee_summary = {
"by_type": {
"rate_fee": {"total": 0.0, "count": 0, "by_currency": defaultdict(float)},
"auth_fee": {"total": 0.0, "count": 0, "by_currency": defaultdict(float)},
"threeds_fee": {"total": 0.0, "count": 0, "by_currency": defaultdict(float)}
},
"by_card": defaultdict(lambda: {
"rate_fee": 0.0,
"auth_fee": 0.0,
"threeds_fee": 0.0,
"total_fees": 0.0,
"transaction_count": 0,
"card_number": "",
"remark": ""
}),
"by_budget": defaultdict(lambda: {
"rate_fee": 0.0,
"auth_fee": 0.0,
"threeds_fee": 0.0,
"total_fees": 0.0,
"transaction_count": 0
}),
"grand_total": 0.0,
"transaction_count": len(all_authorizations)
}

for auth in all_authorizations:
# Process each fee type
rate_fee = float(auth.get("rate_fee", 0))
auth_fee = float(auth.get("auth_fee", 0))
threeds_fee = float(auth.get("threeds_fee", 0))
total_fee = rate_fee + auth_fee + threeds_fee

# By type
if rate_fee > 0:
fee_summary["by_type"]["rate_fee"]["total"] += rate_fee
fee_summary["by_type"]["rate_fee"]["count"] += 1
currency = auth.get("rate_fee_currency", "USD")
fee_summary["by_type"]["rate_fee"]["by_currency"][currency] += rate_fee

if auth_fee > 0:
fee_summary["by_type"]["auth_fee"]["total"] += auth_fee
fee_summary["by_type"]["auth_fee"]["count"] += 1
currency = auth.get("auth_fee_currency", "USD")
fee_summary["by_type"]["auth_fee"]["by_currency"][currency] += auth_fee

if threeds_fee > 0:
fee_summary["by_type"]["threeds_fee"]["total"] += threeds_fee
fee_summary["by_type"]["threeds_fee"]["count"] += 1
currency = auth.get("threeds_fee_currency", "USD")
fee_summary["by_type"]["threeds_fee"]["by_currency"][currency] += threeds_fee

# By card
card_id = auth["card_id"]
fee_summary["by_card"][card_id]["rate_fee"] += rate_fee
fee_summary["by_card"][card_id]["auth_fee"] += auth_fee
fee_summary["by_card"][card_id]["threeds_fee"] += threeds_fee
fee_summary["by_card"][card_id]["total_fees"] += total_fee
fee_summary["by_card"][card_id]["transaction_count"] += 1
fee_summary["by_card"][card_id]["card_number"] = auth["card_number"]
fee_summary["by_card"][card_id]["remark"] = auth.get("remark", "")

# By budget
budget_id = auth.get("budget_id")
if budget_id:
fee_summary["by_budget"][budget_id]["rate_fee"] += rate_fee
fee_summary["by_budget"][budget_id]["auth_fee"] += auth_fee
fee_summary["by_budget"][budget_id]["threeds_fee"] += threeds_fee
fee_summary["by_budget"][budget_id]["total_fees"] += total_fee
fee_summary["by_budget"][budget_id]["transaction_count"] += 1

# Grand total
fee_summary["grand_total"] += total_fee

return fee_summary

def export_to_csv(self, fee_summary, filename="fee_reconciliation.csv"):
"""Export fee breakdown to CSV for accounting"""
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)

# Summary section
writer.writerow(["FEE RECONCILIATION REPORT"])
writer.writerow([])
writer.writerow(["Grand Total Fees", f"${fee_summary['grand_total']:.2f}"])
writer.writerow(["Total Transactions", fee_summary['transaction_count']])
writer.writerow([])

# By fee type
writer.writerow(["BY FEE TYPE"])
writer.writerow(["Fee Type", "Total Amount", "Transaction Count", "Avg per Transaction"])

for fee_type, data in fee_summary["by_type"].items():
avg = data["total"] / data["count"] if data["count"] > 0 else 0
writer.writerow([
fee_type.replace("_", " ").title(),
f"${data['total']:.2f}",
data["count"],
f"${avg:.2f}"
])

writer.writerow([])

# By currency
writer.writerow(["BY CURRENCY"])
writer.writerow(["Fee Type", "Currency", "Amount"])

for fee_type, data in fee_summary["by_type"].items():
for currency, amount in data["by_currency"].items():
writer.writerow([
fee_type.replace("_", " ").title(),
currency,
f"${amount:.2f}"
])

writer.writerow([])

# By card
writer.writerow(["BY CARD"])
writer.writerow([
"Card ID", "Card Number", "Remark", "Rate Fee",
"Auth Fee", "3DS Fee", "Total Fees", "Transactions"
])

sorted_cards = sorted(
fee_summary["by_card"].items(),
key=lambda x: x[1]["total_fees"],
reverse=True
)

for card_id, data in sorted_cards:
writer.writerow([
card_id,
data["card_number"],
data["remark"],
f"${data['rate_fee']:.2f}",
f"${data['auth_fee']:.2f}",
f"${data['threeds_fee']:.2f}",
f"${data['total_fees']:.2f}",
data["transaction_count"]
])

writer.writerow([])

# By budget
if fee_summary["by_budget"]:
writer.writerow(["BY BUDGET"])
writer.writerow([
"Budget ID", "Rate Fee", "Auth Fee",
"3DS Fee", "Total Fees", "Transactions"
])

sorted_budgets = sorted(
fee_summary["by_budget"].items(),
key=lambda x: x[1]["total_fees"],
reverse=True
)

for budget_id, data in sorted_budgets:
writer.writerow([
budget_id,
f"${data['rate_fee']:.2f}",
f"${data['auth_fee']:.2f}",
f"${data['threeds_fee']:.2f}",
f"${data['total_fees']:.2f}",
data["transaction_count"]
])

print(f"Fee reconciliation exported to {filename}")

def print_fee_summary(self, fee_summary):
"""Print formatted fee summary"""
print("\n" + "="*70)
print("FEE RECONCILIATION SUMMARY")
print("="*70)

print(f"\nGrand Total Fees: ${fee_summary['grand_total']:.2f}")
print(f"Total Transactions: {fee_summary['transaction_count']}")

print(f"\nBY FEE TYPE:")
for fee_type, data in fee_summary["by_type"].items():
avg = data["total"] / data["count"] if data["count"] > 0 else 0
print(f" {fee_type.replace('_', ' ').title()}:")
print(f" Total: ${data['total']:.2f}")
print(f" Count: {data['count']}")
print(f" Average: ${avg:.2f}")
print(f" By Currency:")
for currency, amount in data["by_currency"].items():
print(f" {currency}: ${amount:.2f}")

print(f"\nTOP 5 CARDS BY FEES:")
sorted_cards = sorted(
fee_summary["by_card"].items(),
key=lambda x: x[1]["total_fees"],
reverse=True
)[:5]

for card_id, data in sorted_cards:
print(f" {data['card_number']} ({data['remark']})")
print(f" Total Fees: ${data['total_fees']:.2f}")
print(f" Transactions: {data['transaction_count']}")
print(f" Breakdown: Rate=${data['rate_fee']:.2f}, "
f"Auth=${data['auth_fee']:.2f}, 3DS=${data['threeds_fee']:.2f}")

# Usage
reconciliation = FeeReconciliation("your-api-key", "your-access-token")
fee_summary = reconciliation.get_fee_breakdown(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
reconciliation.print_fee_summary(fee_summary)
reconciliation.export_to_csv(fee_summary, "january_fees.csv")

Topics Covered:

  • Fee type breakdown (rate, auth, 3DS)
  • Multi-currency fee aggregation
  • Card-level fee analysis
  • Budget-level fee tracking
  • CSV export for accounting
  • Cost per transaction calculation

Use Case 5: Decline Analysis and Troubleshooting

Analyze declined transactions to identify issues and improve authorization success rates.

Python Implementation:

import requests
from datetime import datetime
from collections import defaultdict

class DeclineAnalyzer:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def analyze_declines(self, start_date, end_date):
"""Analyze all declined transactions in date range"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_date": start_date,
"end_date": end_date,
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all authorizations
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
all_authorizations.extend(data["data"]["list"])

total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
raise Exception(f"Failed to fetch authorizations: {data}")

# Filter declined transactions
declined = [a for a in all_authorizations
if a["authorization_status"] == "DECLINED"]

# Analyze decline patterns
analysis = {
"total_transactions": len(all_authorizations),
"declined_count": len(declined),
"decline_rate": (len(declined) / len(all_authorizations) * 100)
if all_authorizations else 0,
"by_reason": defaultdict(lambda: {
"count": 0,
"total_amount": 0.0,
"cards": set(),
"examples": []
}),
"by_card": defaultdict(lambda: {
"decline_count": 0,
"card_number": "",
"remark": "",
"reasons": defaultdict(int),
"total_attempted": 0.0
}),
"by_merchant": defaultdict(lambda: {
"decline_count": 0,
"reasons": defaultdict(int),
"countries": set()
}),
"by_mcc": defaultdict(lambda: {
"decline_count": 0,
"category": "",
"reasons": defaultdict(int)
})
}

# Analyze each declined transaction
for auth in declined:
reason = auth.get("fail_reason", "UNKNOWN")
card_id = auth["card_id"]
merchant = auth.get("merchant_name", "Unknown")
mcc = auth.get("mcc", "Unknown")
amount = float(auth["billing_amount"])

# By reason
analysis["by_reason"][reason]["count"] += 1
analysis["by_reason"][reason]["total_amount"] += amount
analysis["by_reason"][reason]["cards"].add(card_id)
if len(analysis["by_reason"][reason]["examples"]) < 3:
analysis["by_reason"][reason]["examples"].append({
"card_number": auth["card_number"],
"merchant": merchant,
"amount": amount,
"currency": auth["billing_currency"],
"date": auth["authorization_date"]
})

# By card
analysis["by_card"][card_id]["decline_count"] += 1
analysis["by_card"][card_id]["card_number"] = auth["card_number"]
analysis["by_card"][card_id]["remark"] = auth.get("remark", "")
analysis["by_card"][card_id]["reasons"][reason] += 1
analysis["by_card"][card_id]["total_attempted"] += amount

# By merchant
analysis["by_merchant"][merchant]["decline_count"] += 1
analysis["by_merchant"][merchant]["reasons"][reason] += 1
if auth.get("merchant_country"):
analysis["by_merchant"][merchant]["countries"].add(auth["merchant_country"])

# By MCC
analysis["by_mcc"][mcc]["decline_count"] += 1
analysis["by_mcc"][mcc]["reasons"][reason] += 1

return analysis

def generate_recommendations(self, analysis):
"""Generate actionable recommendations based on decline analysis"""
recommendations = []

# High decline rate
if analysis["decline_rate"] > 20:
recommendations.append({
"severity": "HIGH",
"issue": f"High overall decline rate ({analysis['decline_rate']:.2f}%)",
"action": "Review spending limits and card controls urgently"
})

# Top decline reasons
sorted_reasons = sorted(
analysis["by_reason"].items(),
key=lambda x: x[1]["count"],
reverse=True
)

if sorted_reasons:
top_reason = sorted_reasons[0]
if top_reason[0] == "INSUFFICIENT_FUNDS":
recommendations.append({
"severity": "HIGH",
"issue": f"Insufficient funds is top decline reason ({top_reason[1]['count']} transactions)",
"action": "Top up affected cards or increase spending limits"
})
elif top_reason[0] == "CARD_FROZEN":
recommendations.append({
"severity": "HIGH",
"issue": f"Frozen cards causing {top_reason[1]['count']} declines",
"action": "Review and unfreeze legitimate cards"
})
elif top_reason[0] == "SPENDING_LIMIT_EXCEEDED":
recommendations.append({
"severity": "MEDIUM",
"issue": f"Spending limits exceeded in {top_reason[1]['count']} transactions",
"action": "Consider increasing limits for high-activity cards"
})

# Cards with high decline rates
high_decline_cards = [
(card_id, data) for card_id, data in analysis["by_card"].items()
if data["decline_count"] > 5
]

if high_decline_cards:
recommendations.append({
"severity": "MEDIUM",
"issue": f"{len(high_decline_cards)} cards with >5 declines",
"action": "Investigate specific card issues and notify cardholders",
"cards": [(data["card_number"], data["remark"])
for _, data in high_decline_cards[:5]]
})

# Merchant-specific issues
problematic_merchants = [
(merchant, data) for merchant, data in analysis["by_merchant"].items()
if data["decline_count"] > 3
]

if problematic_merchants:
recommendations.append({
"severity": "LOW",
"issue": f"{len(problematic_merchants)} merchants with multiple declines",
"action": "Review merchant category restrictions",
"merchants": [merchant for merchant, _ in problematic_merchants[:5]]
})

return recommendations

def print_decline_report(self, analysis, recommendations):
"""Print formatted decline analysis report"""
print("\n" + "="*70)
print("DECLINE ANALYSIS REPORT")
print("="*70)

print(f"\nOVERVIEW:")
print(f" Total Transactions: {analysis['total_transactions']}")
print(f" Declined Transactions: {analysis['declined_count']}")
print(f" Decline Rate: {analysis['decline_rate']:.2f}%")

print(f"\nTOP DECLINE REASONS:")
sorted_reasons = sorted(
analysis["by_reason"].items(),
key=lambda x: x[1]["count"],
reverse=True
)[:5]

for reason, data in sorted_reasons:
print(f"\n {reason} ({data['count']} transactions)")
print(f" Total Amount Affected: ${data['total_amount']:.2f}")
print(f" Unique Cards: {len(data['cards'])}")
print(f" Examples:")
for example in data["examples"]:
print(f" - {example['card_number']} | {example['merchant']} | "
f"${example['amount']:.2f} {example['currency']} | {example['date']}")

print(f"\nCARDS WITH HIGHEST DECLINE COUNTS:")
sorted_cards = sorted(
analysis["by_card"].items(),
key=lambda x: x[1]["decline_count"],
reverse=True
)[:5]

for card_id, data in sorted_cards:
print(f"\n {data['card_number']} ({data['remark']})")
print(f" Declines: {data['decline_count']}")
print(f" Total Attempted: ${data['total_attempted']:.2f}")
print(f" Reasons:")
for reason, count in sorted(data["reasons"].items(),
key=lambda x: x[1], reverse=True):
print(f" - {reason}: {count}")

print(f"\nRECOMMENDATIONS:")
for i, rec in enumerate(recommendations, 1):
print(f"\n {i}. [{rec['severity']}] {rec['issue']}")
print(f" Action: {rec['action']}")
if "cards" in rec:
print(f" Affected Cards:")
for card_number, remark in rec["cards"]:
print(f" - {card_number} ({remark})")
if "merchants" in rec:
print(f" Merchants: {', '.join(rec['merchants'])}")

# Usage
analyzer = DeclineAnalyzer("your-api-key", "your-access-token")
analysis = analyzer.analyze_declines(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
recommendations = analyzer.generate_recommendations(analysis)
analyzer.print_decline_report(analysis, recommendations)

Topics Covered:

  • Decline rate calculation
  • Decline reason categorization
  • Card-specific decline patterns
  • Merchant-specific issues
  • MCC category analysis
  • Actionable recommendations
  • Troubleshooting workflows

Use Case 6: Reversal Transaction Tracking

Track and reconcile reversal transactions to ensure proper refund processing.

Python Implementation:

import requests
from datetime import datetime
from collections import defaultdict

class ReversalTracker:
def __init__(self, api_key, access_token):
self.api_key = api_key
self.access_token = access_token
self.base_url = "https://api.ahrvo.network/card/issuance"

def track_reversals(self, start_date, end_date):
"""Track all reversal transactions and match with original authorizations"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_date": start_date,
"end_date": end_date,
"page_size": 100,
"page_no": 1
}

all_authorizations = []

# Fetch all authorizations
while True:
response = requests.get(
f"{self.base_url}/api/issuing/transaction/v2/authorizations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()

if data["code"] == "SUCCESS":
all_authorizations.extend(data["data"]["list"])

total_num = data["data"]["total_num"]
current_records = params["page_no"] * params["page_size"]

if current_records >= total_num:
break

params["page_no"] += 1
else:
raise Exception(f"Failed to fetch authorizations: {data}")

# Separate reversals and original transactions
reversals = []
original_auths = {}

for auth in all_authorizations:
if auth["authorization_type"] == "Reversal":
reversals.append(auth)
else:
original_auths[auth["authorization_id"]] = auth

# Match reversals with originals
matched_reversals = []
unmatched_reversals = []

for reversal in reversals:
reversal_auth_id = reversal.get("reversal_authorization_id")

if reversal_auth_id and reversal_auth_id in original_auths:
matched_reversals.append({
"reversal": reversal,
"original": original_auths[reversal_auth_id]
})
else:
unmatched_reversals.append(reversal)

# Calculate statistics
total_reversal_amount = sum(float(r["billing_amount"]) for r in reversals)

reversal_summary = {
"total_reversals": len(reversals),
"matched_count": len(matched_reversals),
"unmatched_count": len(unmatched_reversals),
"total_amount": total_reversal_amount,
"by_card": defaultdict(lambda: {
"count": 0,
"amount": 0.0,
"card_number": "",
"remark": ""
}),
"matched_pairs": matched_reversals,
"unmatched": unmatched_reversals,
"time_to_reversal": []
}

# Analyze by card
for reversal in reversals:
card_id = reversal["card_id"]
reversal_summary["by_card"][card_id]["count"] += 1
reversal_summary["by_card"][card_id]["amount"] += float(reversal["billing_amount"])
reversal_summary["by_card"][card_id]["card_number"] = reversal["card_number"]
reversal_summary["by_card"][card_id]["remark"] = reversal.get("remark", "")

# Calculate time to reversal
for pair in matched_reversals:
original_date = datetime.strptime(
pair["original"]["authorization_date"],
"%Y-%m-%d %H:%M:%S"
)
reversal_date = datetime.strptime(
pair["reversal"]["reversal_txn_date"],
"%Y-%m-%d %H:%M:%S"
)
time_diff = (reversal_date - original_date).total_seconds() / 3600 # hours
reversal_summary["time_to_reversal"].append(time_diff)

# Average time to reversal
if reversal_summary["time_to_reversal"]:
reversal_summary["avg_time_to_reversal"] = (
sum(reversal_summary["time_to_reversal"]) /
len(reversal_summary["time_to_reversal"])
)

return reversal_summary

def print_reversal_report(self, summary):
"""Print formatted reversal tracking report"""
print("\n" + "="*70)
print("REVERSAL TRANSACTION REPORT")
print("="*70)

print(f"\nOVERVIEW:")
print(f" Total Reversals: {summary['total_reversals']}")
print(f" Matched with Originals: {summary['matched_count']}")
print(f" Unmatched: {summary['unmatched_count']}")
print(f" Total Reversal Amount: ${summary['total_amount']:.2f}")

if "avg_time_to_reversal" in summary:
print(f" Average Time to Reversal: {summary['avg_time_to_reversal']:.2f} hours")

print(f"\nBY CARD:")
sorted_cards = sorted(
summary["by_card"].items(),
key=lambda x: x[1]["count"],
reverse=True
)[:5]

for card_id, data in sorted_cards:
print(f" {data['card_number']} ({data['remark']})")
print(f" Reversals: {data['count']}")
print(f" Total Amount: ${data['amount']:.2f}")

if summary["matched_pairs"]:
print(f"\nRECENT MATCHED REVERSALS (Sample):")
for pair in summary["matched_pairs"][:5]:
orig = pair["original"]
rev = pair["reversal"]
print(f"\n Original Authorization:")
print(f" ID: {orig['authorization_id']}")
print(f" Date: {orig['authorization_date']}")
print(f" Amount: ${orig['billing_amount']} {orig['billing_currency']}")
print(f" Merchant: {orig.get('merchant_name', 'Unknown')}")
print(f" Reversal:")
print(f" ID: {rev['authorization_id']}")
print(f" Date: {rev['reversal_txn_date']}")
print(f" Amount: ${rev['billing_amount']} {rev['billing_currency']}")

if summary["unmatched"]:
print(f"\n⚠️ UNMATCHED REVERSALS ({summary['unmatched_count']}):")
for rev in summary["unmatched"][:5]:
print(f" {rev['authorization_id']} | {rev['card_number']} | "
f"${rev['billing_amount']} | {rev['authorization_date']}")

# Usage
tracker = ReversalTracker("your-api-key", "your-access-token")
summary = tracker.track_reversals(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
tracker.print_reversal_report(summary)

Topics Covered:

  • Reversal transaction identification
  • Matching reversals with originals
  • Unmatched reversal detection
  • Time-to-reversal calculation
  • Card-level reversal tracking
  • Refund reconciliation

Best Practices

1. Efficient Pagination

  • Use appropriate page_size based on your needs (max 100)
  • Implement pagination loops to fetch all results
  • Track total_num to determine when to stop fetching

2. Date Range Filtering

  • Use specific date ranges to limit result sets
  • Format dates correctly: yyyy-MM-dd HH:mm:ss
  • Consider time zones in your analysis
  • Avoid overly broad date ranges that return excessive data

3. Card-Specific Queries

  • Use card_id filter when investigating specific cards
  • Combine with date filters for targeted analysis
  • Helps reduce API load and response time

4. Performance Optimization

  • Cache authorization data for frequent analysis
  • Implement incremental fetching for large datasets
  • Use background jobs for comprehensive reports
  • Consider rate limiting in batch operations

5. Data Retention

  • Store authorization logs for compliance requirements
  • Maintain historical records for trend analysis
  • Implement archival strategies for old data

6. Monitoring and Alerting

  • Set up real-time monitoring for high decline rates
  • Create alerts for suspicious activity patterns
  • Track authorization success rates over time
  • Monitor fee accumulation

Security Considerations

Authentication

  • Secure storage of API keys and access tokens
  • Use environment variables, never hardcode credentials
  • Implement token rotation policies
  • Restrict API access to authorized systems only

Data Privacy

  • Authorization logs contain sensitive transaction data
  • Implement access controls for viewing logs
  • Mask sensitive information in reports
  • Comply with PCI DSS requirements

Audit Trail

  • Log all access to authorization logs
  • Track who viewed sensitive transaction data
  • Maintain audit trails for compliance
  • Regular security reviews of log access patterns

Compliance

  • Ensure data retention meets regulatory requirements
  • Implement proper data deletion procedures
  • Regular compliance audits
  • Document data handling procedures

Troubleshooting

Empty Results

  • Issue: Query returns no authorization records
  • Solution: Check date range format, verify cards have transaction history, ensure correct card_id

Missing Decline Reasons

  • Issue: fail_reason field is null for declined transactions
  • Solution: Some declines may not have detailed reasons, check authorization network status

Pagination Issues

  • Issue: Not all records being retrieved
  • Solution: Ensure pagination loop continues until current_records >= total_num

Fee Discrepancies

  • Issue: Fee amounts don't match expected values
  • Solution: Check currency conversions, verify fee types, review card product fee structure

Reversal Matching

  • Issue: Cannot match reversals with original authorizations
  • Solution: Expand date range to include original transaction, check reversal_authorization_id field

API Explorer