Skip to main content

Query Clearing Logs

Query all cleared transaction records to track settled transactions and reconcile card activity. Clearing logs represent final settled transactions that have been posted to card accounts, as opposed to authorization logs which show attempted transactions. Use this endpoint for financial reconciliation, accounting, expense reporting, and tracking actual card spending.

Resource Access

Production (api.ahrvo.network)

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

Staging (gateway.ahrvo.network)

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

Clearing Logs Overview

Clearing logs (also called settlement logs) show transactions that have moved from authorization to final settlement. Understanding the difference between authorizations and clearings is critical for accurate financial reporting:

Authorization vs. Clearing

AspectAuthorizationClearing
TimingImmediate when card is used1-3 days after authorization
AmountMay include hold amountsFinal settled amount
StatusCan be approved/declinedOnly successful transactions
PurposeTransaction approvalActual fund movement
Balance ImpactTemporary holdPermanent deduction

Key Features

  • Settlement Tracking: Monitor when authorizations convert to final charges
  • Reconciliation: Match cleared transactions with accounting records
  • Credit/Debit Classification: Distinguish between charges and refunds
  • Cross-Border Fees: Track international transaction fees
  • Posting Dates: Filter by settlement date vs. transaction date
  • Authorization Linking: Connect clearings to original authorizations

Request Parameters

Query Parameters

ParameterTypeRequiredDescription
page_nointegerNoPage number (starting from 1, default: 1)
page_sizeintegerNoResults per page (max 100, default: 20)
card_idstringNoFilter by specific card ID
start_posting_datestringNoClearing from date (format: yyyy-MM-dd HH:mm:ss)
end_posting_datestringNoClearing to date (format: yyyy-MM-dd HH:mm:ss)
start_created_datestringNoTransaction creation from date (format: yyyy-MM-dd HH:mm:ss)
end_created_datestringNoTransaction creation to date (format: yyyy-MM-dd HH:mm:ss)
typestringNoTransaction type: Credit or Debit

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 clearing records

Clearing Record Fields

FieldTypeDescription
transaction_idstringUnique ID of the transaction
authorization_idstringRelated authorization ID (may be null for older records)
card_idstringUnique ID of the card
card_numberstringMasked card number (e.g., 5157****8888)
last4stringLast 4 digits of card number
remarkstringCard remark/label
posting_datestringDate when transaction settled
transaction_datestringDate when transaction was processed
merchant_namestringName of merchant
merchant_countrystringCountry of merchant
mccstringMerchant category code
typestringTransaction type: Credit or Debit
billing_amountstringAmount in billing currency
billing_currencystringBilling currency code
transaction_amountstringAmount in merchant's currency
transaction_currencystringMerchant's currency code
approval_codestringApproval code from card network
budget_idstringBudget account ID
cross_border_feestringFee for cross-border transactions
cross_border_fee_currencystringCurrency of cross-border fee

Use Cases

Use Case 1: Monthly Financial Reconciliation

Reconcile all cleared transactions for month-end financial reporting and accounting.

curl -X GET "https://api.ahrvo.network/card/issuance/api/issuing/transaction/v2/clearings?start_posting_date=2026-01-01%2000:00:00&end_posting_date=2026-01-31%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
import csv

class ClearingReconciliation:
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_monthly_clearings(self, year, month):
"""Get all cleared transactions for a specific month"""
# Calculate month date range
start_date = datetime(year, month, 1)
if month == 12:
end_date = datetime(year + 1, 1, 1) - timedelta(seconds=1)
else:
end_date = datetime(year, month + 1, 1) - timedelta(seconds=1)

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

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

all_clearings = []

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

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

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 clearings: {data}")

return all_clearings

def reconcile_transactions(self, year, month):
"""Reconcile transactions and generate financial report"""
clearings = self.get_monthly_clearings(year, month)

# Separate debits and credits
debits = [c for c in clearings if c["type"] == "Debit"]
credits = [c for c in clearings if c["type"] == "Credit"]

# Calculate totals
total_debit = sum(float(c["billing_amount"]) for c in debits)
total_credit = sum(float(c["billing_amount"]) for c in credits)
net_spending = total_debit - total_credit

# Calculate cross-border fees
cross_border_fees = sum(
float(c.get("cross_border_fee", 0))
for c in clearings
if c.get("cross_border_fee")
)

# Group by card
by_card = defaultdict(lambda: {
"debits": 0.0,
"credits": 0.0,
"net": 0.0,
"count": 0,
"card_number": "",
"remark": ""
})

for clearing in clearings:
card_id = clearing["card_id"]
amount = float(clearing["billing_amount"])

by_card[card_id]["count"] += 1
by_card[card_id]["card_number"] = clearing["card_number"]
by_card[card_id]["remark"] = clearing.get("remark", "")

if clearing["type"] == "Debit":
by_card[card_id]["debits"] += amount
else:
by_card[card_id]["credits"] += amount

by_card[card_id]["net"] = (
by_card[card_id]["debits"] - by_card[card_id]["credits"]
)

# Group by budget
by_budget = defaultdict(lambda: {
"debits": 0.0,
"credits": 0.0,
"net": 0.0,
"count": 0
})

for clearing in clearings:
budget_id = clearing.get("budget_id")
if budget_id:
amount = float(clearing["billing_amount"])
by_budget[budget_id]["count"] += 1

if clearing["type"] == "Debit":
by_budget[budget_id]["debits"] += amount
else:
by_budget[budget_id]["credits"] += amount

by_budget[budget_id]["net"] = (
by_budget[budget_id]["debits"] - by_budget[budget_id]["credits"]
)

# Group by merchant category
by_category = defaultdict(lambda: {"count": 0, "amount": 0.0})

for clearing in debits: # Only count spending (debits)
mcc = clearing.get("mcc", "Unknown")
by_category[mcc]["count"] += 1
by_category[mcc]["amount"] += float(clearing["billing_amount"])

return {
"period": f"{year}-{month:02d}",
"summary": {
"total_transactions": len(clearings),
"total_debits": total_debit,
"total_credits": total_credit,
"net_spending": net_spending,
"cross_border_fees": cross_border_fees,
"debit_count": len(debits),
"credit_count": len(credits)
},
"by_card": dict(by_card),
"by_budget": dict(by_budget),
"by_category": dict(by_category),
"transactions": clearings
}

def export_to_csv(self, reconciliation, filename):
"""Export reconciliation report to CSV"""
with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)

# Header
writer.writerow(["MONTHLY RECONCILIATION REPORT"])
writer.writerow(["Period", reconciliation["period"]])
writer.writerow([])

# Summary
writer.writerow(["SUMMARY"])
summary = reconciliation["summary"]
writer.writerow(["Total Transactions", summary["total_transactions"]])
writer.writerow(["Total Debits", f"${summary['total_debits']:.2f}"])
writer.writerow(["Total Credits", f"${summary['total_credits']:.2f}"])
writer.writerow(["Net Spending", f"${summary['net_spending']:.2f}"])
writer.writerow(["Cross-Border Fees", f"${summary['cross_border_fees']:.2f}"])
writer.writerow([])

# By Card
writer.writerow(["BY CARD"])
writer.writerow([
"Card ID", "Card Number", "Remark", "Debits",
"Credits", "Net", "Transactions"
])

for card_id, data in reconciliation["by_card"].items():
writer.writerow([
card_id,
data["card_number"],
data["remark"],
f"${data['debits']:.2f}",
f"${data['credits']:.2f}",
f"${data['net']:.2f}",
data["count"]
])

writer.writerow([])

# By Budget
if reconciliation["by_budget"]:
writer.writerow(["BY BUDGET"])
writer.writerow(["Budget ID", "Debits", "Credits", "Net", "Transactions"])

for budget_id, data in reconciliation["by_budget"].items():
writer.writerow([
budget_id,
f"${data['debits']:.2f}",
f"${data['credits']:.2f}",
f"${data['net']:.2f}",
data["count"]
])

writer.writerow([])

# All Transactions
writer.writerow(["ALL TRANSACTIONS"])
writer.writerow([
"Transaction ID", "Posting Date", "Transaction Date",
"Card Number", "Merchant", "Type", "Amount", "Currency"
])

for txn in reconciliation["transactions"]:
writer.writerow([
txn["transaction_id"],
txn["posting_date"],
txn["transaction_date"],
txn["card_number"],
txn.get("merchant_name", ""),
txn["type"],
txn["billing_amount"],
txn["billing_currency"]
])

print(f"Reconciliation report exported to {filename}")

def print_reconciliation_report(self, reconciliation):
"""Print formatted reconciliation report"""
print("\n" + "="*70)
print(f"MONTHLY RECONCILIATION REPORT - {reconciliation['period']}")
print("="*70)

summary = reconciliation["summary"]
print(f"\nSUMMARY:")
print(f" Total Transactions: {summary['total_transactions']}")
print(f" Total Debits: ${summary['total_debits']:.2f} ({summary['debit_count']} txns)")
print(f" Total Credits: ${summary['total_credits']:.2f} ({summary['credit_count']} txns)")
print(f" Net Spending: ${summary['net_spending']:.2f}")
print(f" Cross-Border Fees: ${summary['cross_border_fees']:.2f}")

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

for card_id, data in sorted_cards:
print(f"\n {data['card_number']} ({data['remark']})")
print(f" Debits: ${data['debits']:.2f}")
print(f" Credits: ${data['credits']:.2f}")
print(f" Net Spending: ${data['net']:.2f}")
print(f" Transactions: {data['count']}")

print(f"\nTOP SPENDING CATEGORIES:")
sorted_categories = sorted(
reconciliation["by_category"].items(),
key=lambda x: x[1]["amount"],
reverse=True
)[:5]

for mcc, data in sorted_categories:
print(f" MCC {mcc}: ${data['amount']:.2f} ({data['count']} txns)")

# Usage
reconciler = ClearingReconciliation("your-api-key", "your-access-token")
reconciliation = reconciler.reconcile_transactions(2026, 1)
reconciler.print_reconciliation_report(reconciliation)
reconciler.export_to_csv(reconciliation, "january_2026_reconciliation.csv")

JavaScript Implementation:

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

async getMonthlyClearings(year, month) {
const startDate = new Date(year, month - 1, 1);
const endDate = new Date(year, month, 0, 23, 59, 59);

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

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

while (true) {
const params = new URLSearchParams({
start_posting_date: this.formatDate(startDate),
end_posting_date: this.formatDate(endDate),
page_size: pageSize,
page_no: pageNo
});

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

const data = await response.json();

if (data.code === 'SUCCESS') {
allClearings.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 clearings: ${JSON.stringify(data)}`);
}
}

return allClearings;
}

formatDate(date) {
return date.toISOString().slice(0, 19).replace('T', ' ');
}

async reconcileTransactions(year, month) {
const clearings = await this.getMonthlyClearings(year, month);

const debits = clearings.filter(c => c.type === 'Debit');
const credits = clearings.filter(c => c.type === 'Credit');

const totalDebit = debits.reduce((sum, c) => sum + parseFloat(c.billing_amount), 0);
const totalCredit = credits.reduce((sum, c) => sum + parseFloat(c.billing_amount), 0);
const netSpending = totalDebit - totalCredit;

const crossBorderFees = clearings.reduce((sum, c) =>
sum + parseFloat(c.cross_border_fee || 0), 0
);

// Group by card
const byCard = {};
clearings.forEach(clearing => {
const cardId = clearing.card_id;
if (!byCard[cardId]) {
byCard[cardId] = {
debits: 0,
credits: 0,
net: 0,
count: 0,
card_number: clearing.card_number,
remark: clearing.remark || ''
};
}

byCard[cardId].count++;
const amount = parseFloat(clearing.billing_amount);

if (clearing.type === 'Debit') {
byCard[cardId].debits += amount;
} else {
byCard[cardId].credits += amount;
}

byCard[cardId].net = byCard[cardId].debits - byCard[cardId].credits;
});

return {
period: `${year}-${month.toString().padStart(2, '0')}`,
summary: {
total_transactions: clearings.length,
total_debits: totalDebit,
total_credits: totalCredit,
net_spending: netSpending,
cross_border_fees: crossBorderFees,
debit_count: debits.length,
credit_count: credits.length
},
by_card: byCard,
transactions: clearings
};
}

printReconciliationReport(reconciliation) {
console.log('\n' + '='.repeat(70));
console.log(`MONTHLY RECONCILIATION REPORT - ${reconciliation.period}`);
console.log('='.repeat(70));

const summary = reconciliation.summary;
console.log('\nSUMMARY:');
console.log(` Total Transactions: ${summary.total_transactions}`);
console.log(` Total Debits: $${summary.total_debits.toFixed(2)} (${summary.debit_count} txns)`);
console.log(` Total Credits: $${summary.total_credits.toFixed(2)} (${summary.credit_count} txns)`);
console.log(` Net Spending: $${summary.net_spending.toFixed(2)}`);
console.log(` Cross-Border Fees: $${summary.cross_border_fees.toFixed(2)}`);

console.log('\nBY CARD:');
Object.entries(reconciliation.by_card)
.sort((a, b) => b[1].net - a[1].net)
.forEach(([cardId, data]) => {
console.log(`\n ${data.card_number} (${data.remark})`);
console.log(` Debits: $${data.debits.toFixed(2)}`);
console.log(` Credits: $${data.credits.toFixed(2)}`);
console.log(` Net Spending: $${data.net.toFixed(2)}`);
console.log(` Transactions: ${data.count}`);
});
}
}

// Usage
const reconciler = new ClearingReconciliation('your-api-key', 'your-access-token');
const reconciliation = await reconciler.reconcileTransactions(2026, 1);
reconciler.printReconciliationReport(reconciliation);

Topics Covered:

  • Monthly date range calculation
  • Debit/credit separation
  • Net spending calculation
  • Cross-border fee aggregation
  • Card-level reconciliation
  • Budget-level grouping
  • CSV export for accounting
  • Multi-currency handling

Use Case 2: Authorization to Clearing Reconciliation

Match authorizations with their corresponding clearings to identify discrepancies and track settlement timing.

Python Implementation:

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

class AuthorizationClearingMatcher:
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_authorizations(self, start_date, end_date):
"""Fetch all authorizations 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 = []

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"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_authorizations

def get_clearings(self, start_date, end_date):
"""Fetch all clearings in date range"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

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

all_clearings = []

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

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

total_num = data["data"]["total_num"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_clearings

def match_auth_to_clearing(self, start_date, end_date):
"""Match authorizations with their clearings"""
# Get authorizations
authorizations = self.get_authorizations(start_date, end_date)

# Get clearings (extend range to catch late settlements)
clearing_end = (
datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") +
timedelta(days=7)
).strftime("%Y-%m-%d %H:%M:%S")

clearings = self.get_clearings(start_date, clearing_end)

# Build authorization lookup
auth_lookup = {}
for auth in authorizations:
if auth["authorization_status"] == "APPROVED":
auth_lookup[auth["authorization_id"]] = auth

# Match clearings to authorizations
matched = []
unmatched_clearings = []

for clearing in clearings:
auth_id = clearing.get("authorization_id")

if auth_id and auth_id in auth_lookup:
matched.append({
"authorization": auth_lookup[auth_id],
"clearing": clearing,
"auth_amount": float(auth_lookup[auth_id]["billing_amount"]),
"clearing_amount": float(clearing["billing_amount"]),
"amount_match": (
float(auth_lookup[auth_id]["billing_amount"]) ==
float(clearing["billing_amount"])
),
"settlement_time": self._calculate_settlement_time(
auth_lookup[auth_id]["authorization_date"],
clearing["posting_date"]
)
})
# Remove from lookup to track uncleared authorizations
del auth_lookup[auth_id]
else:
unmatched_clearings.append(clearing)

# Remaining authorizations are uncleared
uncleared_authorizations = list(auth_lookup.values())

# Calculate statistics
total_matched = len(matched)
amount_mismatches = sum(1 for m in matched if not m["amount_match"])

avg_settlement_time = (
sum(m["settlement_time"] for m in matched) / total_matched
if total_matched > 0 else 0
)

return {
"matched": matched,
"unmatched_clearings": unmatched_clearings,
"uncleared_authorizations": uncleared_authorizations,
"statistics": {
"total_authorizations": len(authorizations),
"total_clearings": len(clearings),
"matched_count": total_matched,
"unmatched_clearing_count": len(unmatched_clearings),
"uncleared_auth_count": len(uncleared_authorizations),
"amount_mismatch_count": amount_mismatches,
"avg_settlement_time_hours": avg_settlement_time
}
}

def _calculate_settlement_time(self, auth_date, posting_date):
"""Calculate hours between authorization and settlement"""
auth_dt = datetime.strptime(auth_date, "%Y-%m-%d %H:%M:%S")
posting_dt = datetime.strptime(posting_date, "%Y-%m-%d")
return (posting_dt - auth_dt).total_seconds() / 3600

def print_matching_report(self, results):
"""Print formatted matching report"""
print("\n" + "="*70)
print("AUTHORIZATION-CLEARING MATCHING REPORT")
print("="*70)

stats = results["statistics"]
print(f"\nSTATISTICS:")
print(f" Total Authorizations: {stats['total_authorizations']}")
print(f" Total Clearings: {stats['total_clearings']}")
print(f" Matched: {stats['matched_count']}")
print(f" Unmatched Clearings: {stats['unmatched_clearing_count']}")
print(f" Uncleared Authorizations: {stats['uncleared_auth_count']}")
print(f" Amount Mismatches: {stats['amount_mismatch_count']}")
print(f" Avg Settlement Time: {stats['avg_settlement_time_hours']:.1f} hours")

if results["uncleared_authorizations"]:
print(f"\n⚠️ UNCLEARED AUTHORIZATIONS ({len(results['uncleared_authorizations'])}):")
for auth in results["uncleared_authorizations"][:10]:
print(f" {auth['authorization_id']} | {auth['card_number']} | "
f"${auth['billing_amount']} | {auth['authorization_date']} | "
f"{auth.get('merchant_name', 'Unknown')}")

if results["unmatched_clearings"]:
print(f"\n⚠️ UNMATCHED CLEARINGS ({len(results['unmatched_clearings'])}):")
for clearing in results["unmatched_clearings"][:10]:
print(f" {clearing['transaction_id']} | {clearing['card_number']} | "
f"${clearing['billing_amount']} | {clearing['posting_date']} | "
f"{clearing.get('merchant_name', 'Unknown')}")

# Amount mismatches
amount_mismatches = [m for m in results["matched"] if not m["amount_match"]]
if amount_mismatches:
print(f"\n⚠️ AMOUNT MISMATCHES ({len(amount_mismatches)}):")
for mismatch in amount_mismatches[:10]:
auth = mismatch["authorization"]
clearing = mismatch["clearing"]
diff = mismatch["clearing_amount"] - mismatch["auth_amount"]
print(f" Card: {auth['card_number']}")
print(f" Auth ID: {auth['authorization_id']}")
print(f" Auth Amount: ${mismatch['auth_amount']:.2f}")
print(f" Clearing Amount: ${mismatch['clearing_amount']:.2f}")
print(f" Difference: ${diff:.2f}")
print(f" Merchant: {auth.get('merchant_name', 'Unknown')}")
print()

# Usage
matcher = AuthorizationClearingMatcher("your-api-key", "your-access-token")
results = matcher.match_auth_to_clearing(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
matcher.print_matching_report(results)

Topics Covered:

  • Authorization-to-clearing matching
  • Settlement time calculation
  • Amount discrepancy detection
  • Uncleared authorization tracking
  • Orphaned clearing identification
  • Reconciliation statistics

Use Case 3: Credit Transaction Monitoring (Refunds and Returns)

Track all credit transactions to monitor refunds, returns, and chargebacks.

Python Implementation:

import requests
from datetime import datetime
from collections import defaultdict

class CreditTransactionMonitor:
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_credit_transactions(self, start_date, end_date):
"""Get all credit transactions (refunds/returns)"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_posting_date": start_date,
"end_posting_date": end_date,
"type": "Credit", # Filter for credits only
"page_size": 100,
"page_no": 1
}

all_credits = []

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

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

total_num = data["data"]["total_num"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_credits

def analyze_credits(self, start_date, end_date):
"""Analyze credit transaction patterns"""
credits = self.get_credit_transactions(start_date, end_date)

# Total credit amount
total_credit_amount = sum(float(c["billing_amount"]) for c in credits)

# Group by card
by_card = defaultdict(lambda: {
"count": 0,
"total_amount": 0.0,
"card_number": "",
"remark": "",
"transactions": []
})

for credit in credits:
card_id = credit["card_id"]
by_card[card_id]["count"] += 1
by_card[card_id]["total_amount"] += float(credit["billing_amount"])
by_card[card_id]["card_number"] = credit["card_number"]
by_card[card_id]["remark"] = credit.get("remark", "")
by_card[card_id]["transactions"].append(credit)

# Group by merchant
by_merchant = defaultdict(lambda: {
"count": 0,
"total_amount": 0.0,
"transactions": []
})

for credit in credits:
merchant = credit.get("merchant_name", "Unknown")
by_merchant[merchant]["count"] += 1
by_merchant[merchant]["total_amount"] += float(credit["billing_amount"])
by_merchant[merchant]["transactions"].append(credit)

# Identify large refunds (>$1000)
large_refunds = [
c for c in credits
if float(c["billing_amount"]) > 1000
]

# Calculate average refund
avg_refund = total_credit_amount / len(credits) if credits else 0

return {
"total_credits": len(credits),
"total_amount": total_credit_amount,
"average_refund": avg_refund,
"by_card": dict(by_card),
"by_merchant": dict(by_merchant),
"large_refunds": large_refunds,
"all_credits": credits
}

def print_credit_report(self, analysis):
"""Print formatted credit transaction report"""
print("\n" + "="*70)
print("CREDIT TRANSACTION REPORT (Refunds & Returns)")
print("="*70)

print(f"\nOVERVIEW:")
print(f" Total Credit Transactions: {analysis['total_credits']}")
print(f" Total Credit Amount: ${analysis['total_amount']:.2f}")
print(f" Average Refund: ${analysis['average_refund']:.2f}")

print(f"\nTOP CARDS BY CREDIT AMOUNT:")
sorted_cards = sorted(
analysis["by_card"].items(),
key=lambda x: x[1]["total_amount"],
reverse=True
)[:5]

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

print(f"\nTOP MERCHANTS BY REFUND COUNT:")
sorted_merchants = sorted(
analysis["by_merchant"].items(),
key=lambda x: x[1]["count"],
reverse=True
)[:5]

for merchant, data in sorted_merchants:
print(f" {merchant}: {data['count']} refunds, ${data['total_amount']:.2f}")

if analysis["large_refunds"]:
print(f"\nLARGE REFUNDS (>$1000) - {len(analysis['large_refunds'])} transactions:")
for refund in analysis["large_refunds"]:
print(f" ${refund['billing_amount']} | {refund['card_number']} | "
f"{refund.get('merchant_name', 'Unknown')} | {refund['posting_date']}")

# Usage
monitor = CreditTransactionMonitor("your-api-key", "your-access-token")
analysis = monitor.analyze_credits(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
monitor.print_credit_report(analysis)

Topics Covered:

  • Credit transaction filtering
  • Refund amount aggregation
  • Card-level credit tracking
  • Merchant refund patterns
  • Large refund identification
  • Return rate analysis

Use Case 4: Cross-Border Transaction Analysis

Analyze international transactions and associated cross-border fees.

Python Implementation:

import requests
from collections import defaultdict

class CrossBorderAnalyzer:
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_clearings(self, start_date, end_date):
"""Get all clearings in date range"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

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

all_clearings = []

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

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

total_num = data["data"]["total_num"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_clearings

def analyze_cross_border(self, start_date, end_date):
"""Analyze cross-border transactions and fees"""
clearings = self.get_clearings(start_date, end_date)

# Identify cross-border transactions
cross_border = []
domestic = []

for clearing in clearings:
fee = float(clearing.get("cross_border_fee", 0))

# Assume transaction is cross-border if it has a fee or currency mismatch
is_cross_border = (
fee > 0 or
clearing["transaction_currency"] != clearing["billing_currency"]
)

if is_cross_border:
cross_border.append(clearing)
else:
domestic.append(clearing)

# Calculate totals
total_cross_border_volume = sum(
float(c["billing_amount"]) for c in cross_border
)
total_cross_border_fees = sum(
float(c.get("cross_border_fee", 0)) for c in cross_border
)

# Group by country
by_country = defaultdict(lambda: {
"count": 0,
"volume": 0.0,
"fees": 0.0,
"avg_fee": 0.0
})

for txn in cross_border:
country = txn.get("merchant_country", "Unknown")
by_country[country]["count"] += 1
by_country[country]["volume"] += float(txn["billing_amount"])
by_country[country]["fees"] += float(txn.get("cross_border_fee", 0))

# Calculate average fees
for country, data in by_country.items():
if data["count"] > 0:
data["avg_fee"] = data["fees"] / data["count"]

# Group by currency pair
by_currency_pair = defaultdict(lambda: {
"count": 0,
"volume": 0.0,
"fees": 0.0
})

for txn in cross_border:
pair = f"{txn['transaction_currency']}{txn['billing_currency']}"
by_currency_pair[pair]["count"] += 1
by_currency_pair[pair]["volume"] += float(txn["billing_amount"])
by_currency_pair[pair]["fees"] += float(txn.get("cross_border_fee", 0))

# Group by card
by_card = defaultdict(lambda: {
"count": 0,
"volume": 0.0,
"fees": 0.0,
"card_number": "",
"remark": ""
})

for txn in cross_border:
card_id = txn["card_id"]
by_card[card_id]["count"] += 1
by_card[card_id]["volume"] += float(txn["billing_amount"])
by_card[card_id]["fees"] += float(txn.get("cross_border_fee", 0))
by_card[card_id]["card_number"] = txn["card_number"]
by_card[card_id]["remark"] = txn.get("remark", "")

# Calculate percentage
total_volume = sum(float(c["billing_amount"]) for c in clearings)
cross_border_percentage = (
(total_cross_border_volume / total_volume * 100)
if total_volume > 0 else 0
)

return {
"total_transactions": len(clearings),
"cross_border_count": len(cross_border),
"domestic_count": len(domestic),
"cross_border_volume": total_cross_border_volume,
"cross_border_fees": total_cross_border_fees,
"cross_border_percentage": cross_border_percentage,
"by_country": dict(by_country),
"by_currency_pair": dict(by_currency_pair),
"by_card": dict(by_card),
"transactions": cross_border
}

def print_cross_border_report(self, analysis):
"""Print formatted cross-border analysis report"""
print("\n" + "="*70)
print("CROSS-BORDER TRANSACTION ANALYSIS")
print("="*70)

print(f"\nOVERVIEW:")
print(f" Total Transactions: {analysis['total_transactions']}")
print(f" Cross-Border: {analysis['cross_border_count']} "
f"({analysis['cross_border_percentage']:.1f}%)")
print(f" Domestic: {analysis['domestic_count']}")
print(f" Cross-Border Volume: ${analysis['cross_border_volume']:.2f}")
print(f" Total Cross-Border Fees: ${analysis['cross_border_fees']:.2f}")

print(f"\nBY COUNTRY:")
sorted_countries = sorted(
analysis["by_country"].items(),
key=lambda x: x[1]["volume"],
reverse=True
)[:10]

for country, data in sorted_countries:
print(f"\n {country}")
print(f" Transactions: {data['count']}")
print(f" Volume: ${data['volume']:.2f}")
print(f" Fees: ${data['fees']:.2f}")
print(f" Avg Fee: ${data['avg_fee']:.2f}")

print(f"\nBY CURRENCY CONVERSION:")
sorted_pairs = sorted(
analysis["by_currency_pair"].items(),
key=lambda x: x[1]["count"],
reverse=True
)[:5]

for pair, data in sorted_pairs:
print(f" {pair}: {data['count']} txns, ${data['volume']:.2f}, "
f"fees: ${data['fees']:.2f}")

print(f"\nTOP CARDS BY CROSS-BORDER FEES:")
sorted_cards = sorted(
analysis["by_card"].items(),
key=lambda x: x[1]["fees"],
reverse=True
)[:5]

for card_id, data in sorted_cards:
print(f"\n {data['card_number']} ({data['remark']})")
print(f" Transactions: {data['count']}")
print(f" Volume: ${data['volume']:.2f}")
print(f" Fees: ${data['fees']:.2f}")

# Usage
analyzer = CrossBorderAnalyzer("your-api-key", "your-access-token")
analysis = analyzer.analyze_cross_border(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
analyzer.print_cross_border_report(analysis)

Topics Covered:

  • Cross-border transaction identification
  • International fee calculation
  • Country-based analysis
  • Currency conversion tracking
  • Fee optimization opportunities
  • Geographic spending patterns

Use Case 5: Expense Categorization by MCC

Categorize and analyze spending by merchant category codes for expense reporting.

Python Implementation:

import requests
from collections import defaultdict

# MCC Category Mappings
MCC_CATEGORIES = {
"Airlines": ["3000-3299", "4511"],
"Hotels": ["3500-3999", "7011"],
"Restaurants": ["5812", "5813", "5814"],
"Gas Stations": ["5541", "5542"],
"Grocery": ["5411", "5422", "5499"],
"Transportation": ["4111", "4121", "4131", "4789"],
"Entertainment": ["7832", "7841", "7922", "7929", "7991", "7996"],
"Online Services": ["5816", "5817", "5818"],
"Office Supplies": ["5111", "5943", "5044"],
"Professional Services": ["8111", "8931"]
}

class ExpenseCategorizer:
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_clearings(self, start_date, end_date, card_id=None):
"""Get clearing transactions for categorization"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

params = {
"start_posting_date": start_date,
"end_posting_date": end_date,
"type": "Debit", # Only expenses
"page_size": 100,
"page_no": 1
}

if card_id:
params["card_id"] = card_id

all_clearings = []

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

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

total_num = data["data"]["total_num"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_clearings

def categorize_by_mcc(self, start_date, end_date, card_id=None):
"""Categorize expenses by merchant category"""
clearings = self.get_clearings(start_date, end_date, card_id)

# Initialize categories
categorized = defaultdict(lambda: {
"count": 0,
"amount": 0.0,
"transactions": []
})

# Categorize each transaction
for clearing in clearings:
mcc = clearing.get("mcc", "")
amount = float(clearing["billing_amount"])

category = self._get_category_from_mcc(mcc)

categorized[category]["count"] += 1
categorized[category]["amount"] += amount
categorized[category]["transactions"].append(clearing)

# Calculate totals
total_amount = sum(cat["amount"] for cat in categorized.values())

# Add percentages
for category, data in categorized.items():
data["percentage"] = (
(data["amount"] / total_amount * 100)
if total_amount > 0 else 0
)

return {
"total_transactions": len(clearings),
"total_amount": total_amount,
"categories": dict(categorized),
"period": f"{start_date} to {end_date}"
}

def _get_category_from_mcc(self, mcc):
"""Map MCC to category"""
if not mcc:
return "Uncategorized"

for category, mcc_list in MCC_CATEGORIES.items():
if mcc in mcc_list:
return category

# Check range (e.g., "3000-3299")
for mcc_range in mcc_list:
if "-" in mcc_range:
start, end = mcc_range.split("-")
if start <= mcc <= end:
return category

return "Other"

def export_expense_report(self, analysis, filename):
"""Export categorized expenses to CSV"""
import csv

with open(filename, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)

# Header
writer.writerow(["EXPENSE REPORT BY CATEGORY"])
writer.writerow(["Period", analysis["period"]])
writer.writerow(["Total Amount", f"${analysis['total_amount']:.2f}"])
writer.writerow([])

# Summary by category
writer.writerow(["CATEGORY SUMMARY"])
writer.writerow(["Category", "Transactions", "Amount", "Percentage"])

sorted_categories = sorted(
analysis["categories"].items(),
key=lambda x: x[1]["amount"],
reverse=True
)

for category, data in sorted_categories:
writer.writerow([
category,
data["count"],
f"${data['amount']:.2f}",
f"{data['percentage']:.1f}%"
])

writer.writerow([])

# Detailed transactions
writer.writerow(["DETAILED TRANSACTIONS"])
writer.writerow([
"Category", "Date", "Merchant", "Card",
"Amount", "Currency", "MCC"
])

for category, data in sorted_categories:
for txn in data["transactions"]:
writer.writerow([
category,
txn["posting_date"],
txn.get("merchant_name", ""),
txn["card_number"],
txn["billing_amount"],
txn["billing_currency"],
txn.get("mcc", "")
])

print(f"Expense report exported to {filename}")

def print_expense_report(self, analysis):
"""Print formatted expense report"""
print("\n" + "="*70)
print("EXPENSE CATEGORIZATION REPORT")
print("="*70)

print(f"\nPeriod: {analysis['period']}")
print(f"Total Transactions: {analysis['total_transactions']}")
print(f"Total Amount: ${analysis['total_amount']:.2f}")

print(f"\nBY CATEGORY:")
sorted_categories = sorted(
analysis["categories"].items(),
key=lambda x: x[1]["amount"],
reverse=True
)

for category, data in sorted_categories:
print(f"\n {category}")
print(f" Transactions: {data['count']}")
print(f" Amount: ${data['amount']:.2f} ({data['percentage']:.1f}%)")

# Top merchants in category
merchant_totals = defaultdict(float)
for txn in data["transactions"]:
merchant = txn.get("merchant_name", "Unknown")
merchant_totals[merchant] += float(txn["billing_amount"])

top_merchants = sorted(
merchant_totals.items(),
key=lambda x: x[1],
reverse=True
)[:3]

if top_merchants:
print(f" Top Merchants:")
for merchant, amount in top_merchants:
print(f" - {merchant}: ${amount:.2f}")

# Usage
categorizer = ExpenseCategorizer("your-api-key", "your-access-token")
analysis = categorizer.categorize_by_mcc(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
categorizer.print_expense_report(analysis)
categorizer.export_expense_report(analysis, "january_2026_expenses.csv")

Topics Covered:

  • MCC-based categorization
  • Expense category grouping
  • Percentage distribution
  • Top merchant identification
  • CSV export for accounting
  • Customizable category mappings

Use Case 6: Settlement Timing Analysis

Analyze settlement patterns to understand when transactions clear and optimize cash flow.

Python Implementation:

import requests
from datetime import datetime
from collections import defaultdict

class SettlementTimingAnalyzer:
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_clearings(self, start_date, end_date):
"""Get clearings with transaction and posting dates"""
headers = {
"Authorization": f"Bearer {self.access_token}",
"x-api-key": self.api_key
}

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

all_clearings = []

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

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

total_num = data["data"]["total_num"]
if params["page_no"] * params["page_size"] >= total_num:
break

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

return all_clearings

def analyze_settlement_timing(self, start_date, end_date):
"""Analyze time between transaction and settlement"""
clearings = self.get_clearings(start_date, end_date)

settlement_times = []
by_merchant = defaultdict(list)
by_mcc = defaultdict(list)
by_day_of_week = defaultdict(list)

for clearing in clearings:
# Calculate settlement time
txn_date = datetime.strptime(
clearing["transaction_date"],
"%Y-%m-%d"
)
posting_date = datetime.strptime(
clearing["posting_date"],
"%Y-%m-%d"
)

days_to_settle = (posting_date - txn_date).days
settlement_times.append(days_to_settle)

# Group by merchant
merchant = clearing.get("merchant_name", "Unknown")
by_merchant[merchant].append(days_to_settle)

# Group by MCC
mcc = clearing.get("mcc", "Unknown")
by_mcc[mcc].append(days_to_settle)

# Group by day of week
day_of_week = txn_date.strftime("%A")
by_day_of_week[day_of_week].append(days_to_settle)

# Calculate statistics
avg_settlement = sum(settlement_times) / len(settlement_times) if settlement_times else 0

# Distribution
settlement_distribution = defaultdict(int)
for days in settlement_times:
settlement_distribution[days] += 1

# Merchant averages
merchant_averages = {}
for merchant, times in by_merchant.items():
if len(times) >= 3: # Only include merchants with 3+ transactions
merchant_averages[merchant] = sum(times) / len(times)

# Day of week averages
dow_averages = {}
for day, times in by_day_of_week.items():
dow_averages[day] = sum(times) / len(times) if times else 0

return {
"total_transactions": len(clearings),
"average_settlement_days": avg_settlement,
"settlement_distribution": dict(settlement_distribution),
"merchant_averages": merchant_averages,
"mcc_analysis": {
mcc: {
"count": len(times),
"avg_days": sum(times) / len(times) if times else 0
}
for mcc, times in by_mcc.items()
if len(times) >= 3
},
"day_of_week_averages": dow_averages,
"fastest_settlements": [
c for c in clearings
if (datetime.strptime(c["posting_date"], "%Y-%m-%d") -
datetime.strptime(c["transaction_date"], "%Y-%m-%d")).days == 0
][:10],
"slowest_settlements": sorted(
[
(c, (datetime.strptime(c["posting_date"], "%Y-%m-%d") -
datetime.strptime(c["transaction_date"], "%Y-%m-%d")).days)
for c in clearings
],
key=lambda x: x[1],
reverse=True
)[:10]
}

def print_timing_report(self, analysis):
"""Print formatted settlement timing report"""
print("\n" + "="*70)
print("SETTLEMENT TIMING ANALYSIS")
print("="*70)

print(f"\nOVERVIEW:")
print(f" Total Transactions: {analysis['total_transactions']}")
print(f" Average Settlement Time: {analysis['average_settlement_days']:.1f} days")

print(f"\nSETTLEMENT DISTRIBUTION:")
for days, count in sorted(analysis["settlement_distribution"].items()):
percentage = (count / analysis["total_transactions"] * 100)
print(f" {days} days: {count} transactions ({percentage:.1f}%)")

print(f"\nBY DAY OF WEEK (Transaction Date):")
days_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
for day in days_order:
if day in analysis["day_of_week_averages"]:
print(f" {day}: {analysis['day_of_week_averages'][day]:.1f} days avg")

print(f"\nFASTEST SETTLING MERCHANTS (Same-day settlement):")
fastest = analysis["fastest_settlements"]
if fastest:
merchant_counts = defaultdict(int)
for txn in fastest:
merchant_counts[txn.get("merchant_name", "Unknown")] += 1

for merchant, count in sorted(
merchant_counts.items(),
key=lambda x: x[1],
reverse=True
)[:5]:
print(f" {merchant}: {count} same-day settlements")

print(f"\nSLOWEST SETTLEMENTS:")
for clearing, days in analysis["slowest_settlements"][:5]:
print(f" {days} days | {clearing['card_number']} | "
f"{clearing.get('merchant_name', 'Unknown')} | "
f"${clearing['billing_amount']}")

# Usage
analyzer = SettlementTimingAnalyzer("your-api-key", "your-access-token")
analysis = analyzer.analyze_settlement_timing(
start_date="2026-01-01 00:00:00",
end_date="2026-01-31 23:59:59"
)
analyzer.print_timing_report(analysis)

Topics Covered:

  • Settlement time calculation
  • Time-to-clear distribution
  • Merchant settlement patterns
  • Day-of-week analysis
  • Fast/slow settlement identification
  • Cash flow optimization insights

Best Practices

1. Use Posting Date for Financial Reports

  • posting_date represents when funds actually settled
  • Use for accurate financial reconciliation
  • transaction_date shows when purchase was made
  • Choose appropriate date field based on use case

2. Credit vs. Debit Classification

  • Filter by type parameter for specific transaction types
  • Credits include refunds, returns, chargebacks
  • Debits are charges and purchases
  • Important for net spending calculations

3. Reconciliation Workflows

  • Match clearings to authorizations via authorization_id
  • Account for settlement delays (1-3 days typical)
  • Identify unmatched transactions
  • Investigate amount discrepancies

4. Cross-Border Fee Tracking

  • Monitor cross_border_fee for international transactions
  • Compare fees across countries and merchants
  • Optimize card usage for international spending
  • Factor fees into total cost analysis

5. MCC-Based Categorization

  • Use merchant category codes for expense classification
  • Build custom category mappings for your business
  • Essential for expense reporting and budgeting
  • Enables policy enforcement

6. Settlement Timing Awareness

  • Understand typical settlement patterns
  • Plan cash flow around settlement schedules
  • Identify fast-settling merchants for urgent needs
  • Monitor for unusual settlement delays

Security Considerations

Authentication

  • Secure storage of API keys and access tokens
  • Use environment variables for credentials
  • Implement token rotation
  • Restrict API access to authorized systems

Data Privacy

  • Clearing logs contain final transaction data
  • Implement access controls for financial data
  • Mask sensitive information in reports
  • Comply with financial data regulations

Reconciliation Controls

  • Implement dual approval for reconciliation
  • Maintain audit trail of reconciliation activities
  • Regular variance analysis
  • Escalation procedures for discrepancies

Compliance

  • Retain clearing logs per regulatory requirements
  • Implement proper archival procedures
  • Regular compliance audits
  • Document reconciliation processes

Troubleshooting

Missing Clearings

  • Issue: Authorized transactions not showing in clearings
  • Solution: Allow 1-3 days for settlement, check authorization status, verify card activity

Amount Mismatches

  • Issue: Clearing amount differs from authorization
  • Solution: Check for tips, currency conversions, partial settlements, merchant adjustments

Duplicate Clearings

  • Issue: Same transaction appears multiple times
  • Solution: Check transaction_id for uniqueness, investigate with card network, may indicate system issue

Cross-Border Fee Errors

  • Issue: Unexpected cross-border fees
  • Solution: Verify merchant country, check currency differences, review card fee structure

Date Range Issues

  • Issue: Missing expected transactions in date range
  • Solution: Check posting_date vs. transaction_date, expand date range, verify timezone handling

API Explorer