Query Card Details
Overview
Use this endpoint to retrieve comprehensive details of a specific card by providing its card ID. This returns complete information including sensitive data like card number, CVC, expiry date, as well as spending limits, status, and configuration.
NOTE: This API is offered on a client-by-client approval basis. Speak to your account manager to check eligibility.
SECURITY WARNING: This endpoint returns sensitive card information including the full card number and CVC. Ensure proper access controls and encryption when handling this data.
Resource Access
Production (api.ahrvo.network)
GET https://api.ahrvo.network/card/issuance/api/issuing/card/v2/detail
Staging (gateway.ahrvo.network)
GET https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/detail
Request Headers
| Header | Value | Required | Description |
|---|---|---|---|
Accept | application/json | Yes | Content type for the response |
Authorization | Bearer {access_token} | Yes | Bearer token for authentication |
x-api-key | API Key | Yes | API key for authentication |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
card_id | string | Yes | A unique ID of the card |
Response
Success Response (200 OK)
{
"code": "SUCCESS",
"data": {
"card_cancelled": "false",
"card_number": "5329111111112321",
"budget_id": "ci202008281528472924",
"created": "2025-07-31 23:00:00",
"remark": "This is my test card",
"type": "SHARE",
"card_id": "card1231231231231231",
"allow_withdrawal": "Y",
"card_status": "ACTIVE",
"cvc": "123",
"cancellation_in_progress": "false",
"billing_currency": "USD",
"card_expiry_date": "2307",
"maximum_transaction_allowed": 53,
"daily_limit": 452.29,
"weekly_limit": 48.15,
"monthly_limit": 858.8,
"lifetime_limit": 930.19,
"transaction_amount_limit": 249.79
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | string | Status string indicating the result. "SUCCESS" refers to a successful query |
data | object | Response data object |
data.card_id | string | A unique ID of the card |
data.card_number | string | A unique 16-digit card number (⚠️ sensitive) |
data.cvc | string | Card security code - CVC/CVV/CVV2 (⚠️ sensitive) |
data.card_expiry_date | string | Card expiry date in YYMM format (e.g., "2307" = July 2023) |
data.card_status | string | Current card status: INACTIVE, ACTIVE, REVOKED, CANCELED |
data.card_cancelled | string | "true": Card has been cancelled; "false": Card is active |
data.cancellation_in_progress | string | "true": Cancellation pending; "false": No cancellation pending |
data.type | string | NORMAL for Dedicated Funds Card; SHARE for Shared Funds Card |
data.budget_id | string | ID of the budget account this card sources from (Shared Funds Cards) |
data.billing_currency | string | The currency for card transactions (e.g., USD) |
data.created | string | Card creation date and time (format: yyyy-MM-dd HH:mm:ss) |
data.remark | string | Optional description to identify the card |
data.allow_withdrawal | string | "Y" or "true": Withdrawals allowed; "N" or "false": Not allowed |
data.transaction_amount_limit | number | Maximum amount for any single transaction |
data.maximum_transaction_allowed | integer | Maximum number of transactions allowed per card |
data.daily_limit | number | Maximum daily spending (Shared Funds Cards only) |
data.weekly_limit | number | Maximum weekly spending (Shared Funds Cards only) |
data.monthly_limit | number | Maximum monthly spending (Shared Funds Cards only) |
data.lifetime_limit | number | Maximum lifetime spending (Shared Funds Cards only) |
Error Responses
- 400 Bad Request: Invalid
card_idparameter - 401 Unauthorized: Invalid or missing authentication token
- 403 Forbidden: Card issuance feature not enabled for this account
- 404 Not Found: Card does not exist
Code Examples
cURL
curl -X GET \
'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/detail?card_id=card17220230919112824519102' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY'
Python
import requests
url = "https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/detail"
headers = {
"Accept": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
params = {
"card_id": "card17220230919112824519102"
}
response = requests.get(url, headers=headers, params=params)
result = response.json()
if result['code'] == 'SUCCESS':
card = result['data']
print(f"Card Details:")
print(f" Card ID: {card['card_id']}")
print(f" Card Number: {card['card_number']}")
print(f" CVC: {card['cvc']}")
print(f" Expiry: {card['card_expiry_date']}")
print(f" Status: {card['card_status']}")
print(f" Type: {'Shared Funds' if card['type'] == 'SHARE' else 'Dedicated Funds'}")
print(f" Budget ID: {card.get('budget_id', 'N/A')}")
print(f" Created: {card['created']}")
if card['type'] == 'SHARE':
print(f"\n Spending Limits:")
print(f" Transaction: ${card.get('transaction_amount_limit', 0):.2f}")
print(f" Daily: ${card.get('daily_limit', 0):.2f}")
print(f" Weekly: ${card.get('weekly_limit', 0):.2f}")
print(f" Monthly: ${card.get('monthly_limit', 0):.2f}")
print(f" Lifetime: ${card.get('lifetime_limit', 0):.2f}")
else:
print(f"Failed to query card: {result}")
JavaScript (Node.js)
const axios = require('axios');
const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/detail';
const headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const params = {
card_id: 'card17220230919112824519102'
};
axios.get(url, { headers, params })
.then(response => {
const result = response.data;
if (result.code === 'SUCCESS') {
const card = result.data;
console.log('Card Details:');
console.log(` Card ID: ${card.card_id}`);
console.log(` Card Number: ${card.card_number}`);
console.log(` CVC: ${card.cvc}`);
console.log(` Expiry: ${card.card_expiry_date}`);
console.log(` Status: ${card.card_status}`);
console.log(` Type: ${card.type === 'SHARE' ? 'Shared Funds' : 'Dedicated Funds'}`);
console.log(` Budget ID: ${card.budget_id || 'N/A'}`);
console.log(` Created: ${card.created}`);
if (card.type === 'SHARE') {
console.log('\n Spending Limits:');
console.log(` Transaction: $${card.transaction_amount_limit?.toFixed(2) || '0.00'}`);
console.log(` Daily: $${card.daily_limit?.toFixed(2) || '0.00'}`);
console.log(` Weekly: $${card.weekly_limit?.toFixed(2) || '0.00'}`);
console.log(` Monthly: $${card.monthly_limit?.toFixed(2) || '0.00'}`);
console.log(` Lifetime: $${card.lifetime_limit?.toFixed(2) || '0.00'}`);
}
}
})
.catch(error => {
console.error('Failed to query card:', error.response.data);
});
Usage Notes
- Sensitive Data: This endpoint returns full card number and CVC - handle with extreme care
- Access Control: Restrict access to authorized personnel only
- Encryption: Always use HTTPS and encrypt stored card details
- Audit Logging: Log all access to this endpoint for security auditing
- Expiry Format: Card expiry date is in YYMM format (e.g., "2307" = July 2023)
- Limit Applicability: Spending limits (daily/weekly/monthly/lifetime) only apply to Shared Funds Cards
Common Use Cases
Display Card Information in UI
Securely display card details to authorized users:
def display_card_details(card_id):
"""
Retrieve and display card details with proper masking
"""
print(f"\nFetching card details for {card_id}...\n")
response = query_card_details(card_id)
if response['code'] == 'SUCCESS':
card = response['data']
# Mask sensitive data for display
masked_number = card['card_number'][:4] + ' **** **** ' + card['card_number'][-4:]
masked_cvc = '***'
print("═" * 60)
print(f"{'CARD DETAILS':^60}")
print("═" * 60)
print(f"\n🔢 Card Information:")
print(f" Card Number: {masked_number}")
print(f" Expiry Date: {card['card_expiry_date'][:2]}/{card['card_expiry_date'][2:]}")
print(f" CVC: {masked_cvc}")
print(f" Status: {card['card_status']}")
status_emoji = {
'ACTIVE': '✅',
'INACTIVE': '⏸️',
'REVOKED': '🚫',
'CANCELED': '❌'
}
print(f" {status_emoji.get(card['card_status'], '❓')} {card['card_status']}")
print(f"\n📋 Card Configuration:")
print(f" Type: {'Shared Funds Card' if card['type'] == 'SHARE' else 'Dedicated Funds Card'}")
print(f" Currency: {card['billing_currency']}")
print(f" Created: {card['created']}")
print(f" Withdrawals: {'Allowed' if card.get('allow_withdrawal') in ['Y', 'true'] else 'Not Allowed'}")
if card.get('remark'):
print(f" Note: {card['remark']}")
if card['type'] == 'SHARE':
print(f"\n💰 Spending Limits:")
print(f" Per Transaction: ${card.get('transaction_amount_limit', 0):,.2f}")
print(f" Daily: ${card.get('daily_limit', 0):,.2f}")
print(f" Weekly: ${card.get('weekly_limit', 0):,.2f}")
print(f" Monthly: ${card.get('monthly_limit', 0):,.2f}")
print(f" Lifetime: ${card.get('lifetime_limit', 0):,.2f}")
if card.get('budget_id'):
print(f"\n🏦 Budget Account:")
print(f" Budget ID: {card['budget_id']}")
if card.get('maximum_transaction_allowed'):
print(f"\n📊 Transaction Limits:")
print(f" Max Transactions: {card['maximum_transaction_allowed']}")
if card.get('cancellation_in_progress') == 'true':
print(f"\n⚠️ WARNING: Cancellation in progress")
print("\n" + "═" * 60 + "\n")
return card
else:
print(f"❌ Failed to retrieve card details: {response}")
return None
# Example usage
card_details = display_card_details('card17220230919112824519102')
Verify Card Before Transaction
Validate card status and limits before processing a transaction:
async function verifyCardForTransaction(cardId, transactionAmount) {
console.log(`\n=== Card Verification for Transaction ===`);
console.log(`Card ID: ${cardId}`);
console.log(`Transaction Amount: $${transactionAmount.toFixed(2)}\n`);
try {
const response = await queryCardDetails(cardId);
if (response.code === 'SUCCESS') {
const card = response.data;
const checks = {
cardExists: true,
isActive: false,
notCancelled: false,
withinTransactionLimit: false,
withinDailyLimit: false,
hasTransactionsLeft: false
};
// Check card status
checks.isActive = card.card_status === 'ACTIVE';
checks.notCancelled = card.card_cancelled === 'false' &&
card.cancellation_in_progress === 'false';
// Check transaction limit
if (card.transaction_amount_limit) {
checks.withinTransactionLimit = transactionAmount <= card.transaction_amount_limit;
} else {
checks.withinTransactionLimit = true; // No limit set
}
// Check daily limit (for Shared Funds Cards)
if (card.type === 'SHARE' && card.daily_limit) {
// Note: This checks the configured limit, not remaining limit
// Use Query Card Remaining Limits endpoint for actual remaining amount
checks.withinDailyLimit = transactionAmount <= card.daily_limit;
} else {
checks.withinDailyLimit = true;
}
// Check transaction count limit
if (card.maximum_transaction_allowed) {
// Note: You'd need transaction history to verify actual count
checks.hasTransactionsLeft = true; // Placeholder
} else {
checks.hasTransactionsLeft = true;
}
// Display results
console.log('Verification Results:');
console.log(` ${checks.isActive ? '✓' : '✗'} Card is ACTIVE: ${checks.isActive ? 'PASS' : 'FAIL'}`);
console.log(` ${checks.notCancelled ? '✓' : '✗'} Card not cancelled: ${checks.notCancelled ? 'PASS' : 'FAIL'}`);
console.log(` ${checks.withinTransactionLimit ? '✓' : '✗'} Within transaction limit: ${checks.withinTransactionLimit ? 'PASS' : 'FAIL'}`);
if (card.type === 'SHARE') {
console.log(` ${checks.withinDailyLimit ? '✓' : '✗'} Within daily limit: ${checks.withinDailyLimit ? 'PASS' : 'FAIL'}`);
}
const allChecks = Object.values(checks).every(check => check === true);
console.log(`\nOverall Result: ${allChecks ? '✓ APPROVED' : '✗ DECLINED'}`);
if (!allChecks) {
console.log('\nReasons for decline:');
if (!checks.isActive) console.log(' • Card is not active');
if (!checks.notCancelled) console.log(' • Card is cancelled or cancellation pending');
if (!checks.withinTransactionLimit) {
console.log(` • Transaction amount ($${transactionAmount.toFixed(2)}) exceeds limit ($${card.transaction_amount_limit?.toFixed(2)})`);
}
if (card.type === 'SHARE' && !checks.withinDailyLimit) {
console.log(` • Transaction amount exceeds daily limit ($${card.daily_limit?.toFixed(2)})`);
}
}
return {
approved: allChecks,
checks: checks,
card: card
};
} else {
console.log('✗ Card not found or error occurred');
return {
approved: false,
checks: { cardExists: false },
error: response
};
}
} catch (error) {
console.error('Verification failed:', error.message);
return {
approved: false,
checks: { cardExists: false },
error: error
};
}
}
// Example usage
const verification = await verifyCardForTransaction(
'card17220230919112824519102',
150.00
);
Export Card Details for Compliance
Generate card detail reports for compliance and auditing:
def export_card_details_for_compliance(card_ids):
"""
Export card details for compliance reporting
"""
import csv
from datetime import datetime
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
filename = f'card_details_compliance_{timestamp}.csv'
print(f"Generating compliance report for {len(card_ids)} cards...\n")
fieldnames = [
'card_id',
'card_number_masked',
'card_status',
'card_type',
'created_date',
'expiry_date',
'billing_currency',
'budget_id',
'daily_limit',
'monthly_limit',
'lifetime_limit',
'transaction_limit',
'max_transactions',
'allow_withdrawal',
'cancellation_status',
'remark'
]
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for card_id in card_ids:
try:
response = query_card_details(card_id)
if response['code'] == 'SUCCESS':
card = response['data']
# Mask card number for security
masked_number = card['card_number'][:4] + '********' + card['card_number'][-4:]
row = {
'card_id': card['card_id'],
'card_number_masked': masked_number,
'card_status': card['card_status'],
'card_type': 'Shared Funds' if card['type'] == 'SHARE' else 'Dedicated Funds',
'created_date': card['created'],
'expiry_date': card['card_expiry_date'],
'billing_currency': card['billing_currency'],
'budget_id': card.get('budget_id', ''),
'daily_limit': card.get('daily_limit', ''),
'monthly_limit': card.get('monthly_limit', ''),
'lifetime_limit': card.get('lifetime_limit', ''),
'transaction_limit': card.get('transaction_amount_limit', ''),
'max_transactions': card.get('maximum_transaction_allowed', ''),
'allow_withdrawal': card.get('allow_withdrawal', ''),
'cancellation_status': card.get('cancellation_in_progress', 'false'),
'remark': card.get('remark', '')
}
writer.writerow(row)
print(f"✓ Exported: {masked_number}")
else:
print(f"✗ Failed to export {card_id}: {response}")
except Exception as e:
print(f"✗ Error processing {card_id}: {e}")
print(f"\n✓ Compliance report saved to: {filename}")
return filename
# Example usage
card_list = [
'card17220230919112824519102',
'card1231231231231231',
'card20820230817163921206780'
]
report_file = export_card_details_for_compliance(card_list)
Card Configuration Comparison
Compare configurations of multiple cards:
async function compareCardConfigurations(cardIds) {
console.log('\n=== Card Configuration Comparison ===\n');
const cards = [];
// Fetch all card details
for (const cardId of cardIds) {
try {
const response = await queryCardDetails(cardId);
if (response.code === 'SUCCESS') {
cards.push(response.data);
}
} catch (error) {
console.error(`Error fetching ${cardId}:`, error.message);
}
}
if (cards.length === 0) {
console.log('No cards to compare');
return null;
}
console.log(`Comparing ${cards.length} cards:\n`);
// Display comparison table
console.log('─'.repeat(100));
console.log('Property'.padEnd(30) + cards.map((c, i) => `Card ${i + 1}`.padEnd(20)).join(''));
console.log('─'.repeat(100));
const properties = [
{ key: 'card_number', label: 'Card Number (Last 4)', format: (v) => '****' + v.slice(-4) },
{ key: 'card_status', label: 'Status', format: (v) => v },
{ key: 'type', label: 'Type', format: (v) => v === 'SHARE' ? 'Shared' : 'Dedicated' },
{ key: 'billing_currency', label: 'Currency', format: (v) => v },
{ key: 'transaction_amount_limit', label: 'Transaction Limit', format: (v) => v ? `$${v}` : 'N/A' },
{ key: 'daily_limit', label: 'Daily Limit', format: (v) => v ? `$${v}` : 'N/A' },
{ key: 'monthly_limit', label: 'Monthly Limit', format: (v) => v ? `$${v}` : 'N/A' },
{ key: 'lifetime_limit', label: 'Lifetime Limit', format: (v) => v ? `$${v}` : 'N/A' },
{ key: 'maximum_transaction_allowed', label: 'Max Transactions', format: (v) => v || 'Unlimited' },
{ key: 'allow_withdrawal', label: 'Withdrawals', format: (v) => v === 'Y' || v === 'true' ? 'Yes' : 'No' }
];
properties.forEach(prop => {
const values = cards.map(card => prop.format(card[prop.key]));
console.log(prop.label.padEnd(30) + values.map(v => String(v).padEnd(20)).join(''));
});
console.log('─'.repeat(100));
// Identify differences
console.log('\n📊 Analysis:');
const sharedCards = cards.filter(c => c.type === 'SHARE').length;
const dedicatedCards = cards.filter(c => c.type === 'NORMAL').length;
console.log(` Card Types: ${sharedCards} Shared, ${dedicatedCards} Dedicated`);
const activeCards = cards.filter(c => c.card_status === 'ACTIVE').length;
console.log(` Active Cards: ${activeCards}/${cards.length}`);
const currencies = [...new Set(cards.map(c => c.billing_currency))];
console.log(` Currencies: ${currencies.join(', ')}`);
return {
cards: cards,
comparison: {
shared_count: sharedCards,
dedicated_count: dedicatedCards,
active_count: activeCards,
currencies: currencies
}
};
}
// Example usage
const comparison = await compareCardConfigurations([
'card17220230919112824519102',
'card1231231231231231',
'card20820230817163921206780'
]);
Check Card Expiry Status
Monitor cards approaching expiry date:
def check_card_expiry_status(card_ids, warning_days=60):
"""
Check expiry status of cards and identify those expiring soon
Args:
card_ids: List of card IDs to check
warning_days: Number of days before expiry to trigger warning
"""
from datetime import datetime, timedelta
print(f"\n=== Card Expiry Status Check ===")
print(f"Warning threshold: {warning_days} days\n")
expiring_soon = []
expired = []
active_cards = []
for card_id in card_ids:
try:
response = query_card_details(card_id)
if response['code'] == 'SUCCESS':
card = response['data']
# Parse expiry date (YYMM format)
expiry_str = card['card_expiry_date']
expiry_year = 2000 + int(expiry_str[:2])
expiry_month = int(expiry_str[2:])
# Card expires at end of month
from calendar import monthrange
last_day = monthrange(expiry_year, expiry_month)[1]
expiry_date = datetime(expiry_year, expiry_month, last_day)
days_until_expiry = (expiry_date - datetime.now()).days
masked_number = card['card_number'][:4] + '********' + card['card_number'][-4:]
card_info = {
'card_id': card['card_id'],
'masked_number': masked_number,
'expiry_date': expiry_date.strftime('%Y-%m-%d'),
'days_until_expiry': days_until_expiry,
'status': card['card_status'],
'remark': card.get('remark', '')
}
if days_until_expiry < 0:
expired.append(card_info)
print(f"❌ EXPIRED: {masked_number}")
print(f" Expired: {abs(days_until_expiry)} days ago")
print(f" Expiry Date: {card_info['expiry_date']}")
print(f" Status: {card['card_status']}\n")
elif days_until_expiry <= warning_days:
expiring_soon.append(card_info)
print(f"⚠️ EXPIRING SOON: {masked_number}")
print(f" Days remaining: {days_until_expiry}")
print(f" Expiry Date: {card_info['expiry_date']}")
print(f" Status: {card['card_status']}\n")
else:
active_cards.append(card_info)
print(f"✅ ACTIVE: {masked_number}")
print(f" Days remaining: {days_until_expiry}")
print(f" Expiry Date: {card_info['expiry_date']}\n")
except Exception as e:
print(f"✗ Error checking {card_id}: {e}\n")
# Summary
print("=" * 60)
print("SUMMARY")
print("=" * 60)
print(f"Total Cards Checked: {len(card_ids)}")
print(f"Expired: {len(expired)}")
print(f"Expiring Soon (< {warning_days} days): {len(expiring_soon)}")
print(f"Active (> {warning_days} days): {len(active_cards)}")
if expired or expiring_soon:
print("\n⚠️ ACTION REQUIRED:")
if expired:
print(f" • {len(expired)} card(s) have expired - consider replacement")
if expiring_soon:
print(f" • {len(expiring_soon)} card(s) expiring soon - plan for renewal")
return {
'expired': expired,
'expiring_soon': expiring_soon,
'active': active_cards
}
# Example usage
cards_to_check = [
'card17220230919112824519102',
'card1231231231231231',
'card20820230817163921206780'
]
expiry_report = check_card_expiry_status(cards_to_check, warning_days=60)
Secure Card Data Display
Display card details securely with progressive disclosure:
async function secureCardDisplay(cardId, showSensitiveData = false) {
console.log('\n🔒 Secure Card Details Display\n');
try {
const response = await queryCardDetails(cardId);
if (response.code === 'SUCCESS') {
const card = response.data;
// Always show non-sensitive data
console.log('Card Information:');
console.log(` Card ID: ${card.card_id}`);
console.log(` Status: ${card.card_status}`);
console.log(` Type: ${card.type === 'SHARE' ? 'Shared Funds' : 'Dedicated Funds'}`);
console.log(` Currency: ${card.billing_currency}`);
console.log(` Created: ${card.created}`);
if (card.remark) {
console.log(` Note: ${card.remark}`);
}
// Conditionally show sensitive data
if (showSensitiveData) {
console.log('\n⚠️ SENSITIVE DATA (Handle with care):');
console.log(` Full Card Number: ${card.card_number}`);
console.log(` CVC: ${card.cvc}`);
console.log(` Expiry: ${card.card_expiry_date.slice(0, 2)}/${card.card_expiry_date.slice(2)}`);
} else {
console.log('\n🔒 Sensitive Data (Masked):');
const masked = card.card_number.slice(0, 4) + ' **** **** ' + card.card_number.slice(-4);
console.log(` Card Number: ${masked}`);
console.log(` CVC: ***`);
console.log(` Expiry: ${card.card_expiry_date.slice(0, 2)}/**`);
console.log('\n ℹ️ Call with showSensitiveData=true to reveal');
}
// Show limits if applicable
if (card.type === 'SHARE') {
console.log('\nSpending Limits:');
if (card.transaction_amount_limit) {
console.log(` Per Transaction: $${card.transaction_amount_limit.toFixed(2)}`);
}
if (card.daily_limit) {
console.log(` Daily: $${card.daily_limit.toFixed(2)}`);
}
if (card.weekly_limit) {
console.log(` Weekly: $${card.weekly_limit.toFixed(2)}`);
}
if (card.monthly_limit) {
console.log(` Monthly: $${card.monthly_limit.toFixed(2)}`);
}
if (card.lifetime_limit) {
console.log(` Lifetime: $${card.lifetime_limit.toFixed(2)}`);
}
}
return card;
} else {
console.log('❌ Failed to retrieve card details');
return null;
}
} catch (error) {
console.error('Error:', error.message);
return null;
}
}
// Example usage - default masked display
await secureCardDisplay('card17220230919112824519102');
// To show sensitive data (requires proper authorization)
// await secureCardDisplay('card17220230919112824519102', true);
Best Practices
- Access Control: Restrict access to this endpoint - it returns sensitive card data
- Data Masking: Always mask card number and CVC when displaying in UI
- Secure Storage: Never log or store full card details in plaintext
- Audit Logging: Log all access to this endpoint with user/timestamp
- HTTPS Only: Always use HTTPS when calling this endpoint
- Token Security: Protect access tokens - they grant access to sensitive data
- Progressive Disclosure: Only reveal sensitive data when absolutely necessary
- Expiry Monitoring: Regularly check card expiry dates for proactive renewal
Understanding Card Types
Shared Funds Card (SHARE)
- Sources funds from a budget account
- Has spending limits (daily, weekly, monthly, lifetime)
- Multiple cards can share the same budget
- Ideal for controlled spending scenarios
Dedicated Funds Card (NORMAL)
- Has its own dedicated balance
- No shared budget integration
- Spending limits may not apply
- Ideal for independent card usage
Related Endpoints
- Query All Cards - List all cards with filters
- Create a Card - Issue new cards
- Control Card Spending - Update spending limits
- Query Card Remaining Limits - Check available spending capacity
- Update Card - Modify card properties
- Cancel Card - Close a card permanently
Troubleshooting
Card Not Found (404)
- Cause: Invalid
card_idor card doesn't exist - Solution:
- Verify the card ID is correct
- Use Query All Cards to list available cards
- Check if card was deleted or cancelled
Missing Fields in Response
- Cause: Some fields may be null/empty based on card type or configuration
- Solution:
- Check card type - some fields only apply to Shared Funds Cards
- Handle null values gracefully in your code
- Use optional chaining or default values
Sensitive Data Security
- Concern: Full card number and CVC are returned
- Solution:
- Implement strict access controls
- Always mask sensitive data in UI
- Use TLS/HTTPS for all communications
- Comply with PCI DSS requirements
- Log and monitor all access
Security Considerations
- PCI DSS Compliance: Ensure compliance with Payment Card Industry Data Security Standards
- Data Encryption: Encrypt card data in transit and at rest
- Access Logging: Maintain audit logs of all card detail queries
- Role-Based Access: Implement RBAC to restrict access
- Token Management: Rotate tokens regularly and revoke compromised tokens
- Secure Display: Never display full card number and CVC together
- Data Retention: Follow data retention policies for card information