Control Card Spending
Overview
Use this endpoint to set spending limits for Shared Funds Cards. You can configure multiple types of spending controls including transactional, daily, weekly, monthly, and lifetime limits to manage card usage and prevent overspending.
NOTE: This API is offered on a client-by-client approval basis. Speak to your account manager to check eligibility.
Resource Access
Production (api.ahrvo.network)
POST https://api.ahrvo.network/card/issuance/api/issuing/spending-control/v2/share-card-limit
Staging (gateway.ahrvo.network)
POST https://gateway.ahrvo.network/card/issuance/api/issuing/spending-control/v2/share-card-limit
Request Headers
| Header | Value | Required | Description |
|---|---|---|---|
Accept | application/json | Yes | Content type for the response |
Content-Type | application/json | Yes | Content type of the request body |
Authorization | Bearer {access_token} | Yes | Bearer token for authentication |
x-api-key | API Key | Yes | API key for authentication |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
card_id | string | Yes | A unique ID of the card |
spending_limit | string | Yes | Monetary amount of the spending limit expressed in USD. Must be a positive number with up to 2 decimal places |
limit_type | string | Yes | Define the card spending limit interval. See limit types below |
Limit Types
| Type | Description |
|---|---|
TRANSACTION | Spending limit per single transaction |
DAY | Daily spending limit (resets every 24 hours) |
WEEK | Weekly spending limit (resets every 7 days) |
MONTH | Monthly spending limit (resets every 30 days) |
LIFETIME | Lifetime spending limit (total card lifetime) |
Request Example
{
"card_id": "card2021062115091808923",
"spending_limit": "1.23",
"limit_type": "TRANSACTION"
}
Response
Success Response (200 OK)
{
"code": "SUCCESS"
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | string | Status string indicating the result of the request. "SUCCESS" indicates the limit was set successfully |
Error Responses
- 400 Bad Request: Invalid parameters, invalid limit type, or invalid amount format
- 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 POST \
https://gateway.ahrvo.network/card/issuance/api/issuing/spending-control/v2/share-card-limit \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{
"card_id": "card2021062115091808923",
"spending_limit": "500.00",
"limit_type": "DAY"
}'
Python
import requests
url = "https://gateway.ahrvo.network/card/issuance/api/issuing/spending-control/v2/share-card-limit"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"card_id": "card2021062115091808923",
"spending_limit": "500.00",
"limit_type": "DAY"
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
if result['code'] == 'SUCCESS':
print(f"✓ Spending limit set successfully")
print(f" Card ID: {payload['card_id']}")
print(f" Limit: ${payload['spending_limit']}")
print(f" Type: {payload['limit_type']}")
else:
print(f"Failed to set spending limit: {result}")
JavaScript (Node.js)
const axios = require('axios');
const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/spending-control/v2/share-card-limit';
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const payload = {
card_id: 'card2021062115091808923',
spending_limit: '500.00',
limit_type: 'DAY'
};
axios.post(url, payload, { headers })
.then(response => {
const result = response.data;
if (result.code === 'SUCCESS') {
console.log('✓ Spending limit set successfully');
console.log(` Card ID: ${payload.card_id}`);
console.log(` Limit: $${payload.spending_limit}`);
console.log(` Type: ${payload.limit_type}`);
}
})
.catch(error => {
console.error('Failed to set spending limit:', error.response.data);
});
Usage Notes
- Multiple Limits: You can set different limit types for the same card (e.g., both daily and per-transaction limits)
- Immediate Effect: Spending limits take effect immediately upon setting
- Currency: All amounts are in USD
- Shared Funds Cards Only: This endpoint is for Shared Funds Cards, not Dedicated Funds Cards
- Amount Format: Provide amounts as strings with up to 2 decimal places
- Overwrite: Setting a new limit of the same type will overwrite the previous limit
Common Use Cases
Set Multiple Spending Limits for a Card
Configure comprehensive spending controls:
def set_comprehensive_limits(card_id):
"""
Set multiple spending limits for comprehensive control
"""
limits = [
{
'type': 'TRANSACTION',
'amount': '100.00',
'description': 'Per-transaction limit'
},
{
'type': 'DAY',
'amount': '500.00',
'description': 'Daily spending limit'
},
{
'type': 'WEEK',
'amount': '2000.00',
'description': 'Weekly spending limit'
},
{
'type': 'MONTH',
'amount': '7500.00',
'description': 'Monthly spending limit'
},
{
'type': 'LIFETIME',
'amount': '50000.00',
'description': 'Lifetime spending limit'
}
]
print(f"\nSetting spending limits for card: {card_id}\n")
results = []
for limit in limits:
try:
response = set_card_spending_limit(
card_id=card_id,
spending_limit=limit['amount'],
limit_type=limit['type']
)
if response['code'] == 'SUCCESS':
print(f"✓ {limit['description']}: ${limit['amount']}")
results.append({
'type': limit['type'],
'amount': limit['amount'],
'success': True
})
else:
print(f"✗ {limit['description']}: Failed")
results.append({
'type': limit['type'],
'amount': limit['amount'],
'success': False
})
time.sleep(0.5) # Rate limiting
except Exception as e:
print(f"✗ {limit['description']}: Error - {e}")
results.append({
'type': limit['type'],
'amount': limit['amount'],
'success': False,
'error': str(e)
})
# Summary
successful = sum(1 for r in results if r.get('success'))
print(f"\n✓ Set {successful}/{len(limits)} spending limits successfully")
return results
# Example usage
limits = set_comprehensive_limits('card2021062115091808923')
Employee Card Setup with Spending Controls
Set up employee cards with role-based spending limits:
async function setupEmployeeCard(cardId, employeeRole) {
const spendingLimits = {
'junior': {
transaction: '50.00',
daily: '200.00',
weekly: '750.00',
monthly: '3000.00',
lifetime: '20000.00'
},
'senior': {
transaction: '200.00',
daily: '1000.00',
weekly: '4000.00',
monthly: '15000.00',
lifetime: '100000.00'
},
'manager': {
transaction: '500.00',
daily: '2500.00',
weekly: '10000.00',
monthly: '40000.00',
lifetime: '250000.00'
},
'executive': {
transaction: '2000.00',
daily: '10000.00',
weekly: '50000.00',
monthly: '200000.00',
lifetime: '1000000.00'
}
};
const limits = spendingLimits[employeeRole.toLowerCase()];
if (!limits) {
throw new Error(`Unknown employee role: ${employeeRole}`);
}
console.log(`\nSetting up ${employeeRole} card: ${cardId}`);
console.log('Applying spending limits...\n');
const limitTypes = [
{ type: 'TRANSACTION', amount: limits.transaction, label: 'Per Transaction' },
{ type: 'DAY', amount: limits.daily, label: 'Daily' },
{ type: 'WEEK', amount: limits.weekly, label: 'Weekly' },
{ type: 'MONTH', amount: limits.monthly, label: 'Monthly' },
{ type: 'LIFETIME', amount: limits.lifetime, label: 'Lifetime' }
];
const results = [];
for (const limit of limitTypes) {
try {
const response = await setCardSpendingLimit({
card_id: cardId,
spending_limit: limit.amount,
limit_type: limit.type
});
if (response.code === 'SUCCESS') {
console.log(` ✓ ${limit.label}: $${limit.amount}`);
results.push({ type: limit.type, success: true });
} else {
console.log(` ✗ ${limit.label}: Failed`);
results.push({ type: limit.type, success: false });
}
await new Promise(resolve => setTimeout(resolve, 500));
} catch (error) {
console.error(` ✗ ${limit.label}: Error - ${error.message}`);
results.push({ type: limit.type, success: false, error: error.message });
}
}
const successful = results.filter(r => r.success).length;
console.log(`\n✓ Card setup complete: ${successful}/${limitTypes.length} limits set`);
return {
card_id: cardId,
role: employeeRole,
limits_set: successful,
total_limits: limitTypes.length,
results: results
};
}
// Example usage
const setupResult = await setupEmployeeCard('card2021062115091808923', 'manager');
Bulk Update Card Limits
Update spending limits for multiple cards:
def bulk_update_card_limits(cards, limit_type, amount):
"""
Update the same spending limit for multiple cards
Args:
cards: List of card IDs
limit_type: Type of limit (TRANSACTION, DAY, WEEK, MONTH, LIFETIME)
amount: Limit amount in USD
"""
print(f"\n=== Bulk Update Card Limits ===")
print(f"Limit Type: {limit_type}")
print(f"Amount: ${amount}")
print(f"Cards: {len(cards)}\n")
results = {
'successful': [],
'failed': []
}
for card_id in cards:
try:
response = set_card_spending_limit(
card_id=card_id,
spending_limit=str(amount),
limit_type=limit_type
)
if response['code'] == 'SUCCESS':
print(f"✓ {card_id}: Limit set")
results['successful'].append(card_id)
else:
print(f"✗ {card_id}: Failed - {response}")
results['failed'].append({
'card_id': card_id,
'error': response
})
time.sleep(0.5)
except Exception as e:
print(f"✗ {card_id}: Error - {e}")
results['failed'].append({
'card_id': card_id,
'error': str(e)
})
# Summary
print(f"\n=== Update Summary ===")
print(f"✓ Successful: {len(results['successful'])}")
print(f"✗ Failed: {len(results['failed'])}")
return results
# Example usage - Set daily limit to $500 for all team cards
team_cards = [
'card2021062115091808923',
'card2021062115091808924',
'card2021062115091808925'
]
results = bulk_update_card_limits(team_cards, 'DAY', 500.00)
Temporary Spending Increase
Temporarily increase spending limits for special events:
async function temporarySpendingIncrease(cardId, originalLimits, temporaryLimits, durationHours) {
console.log('\n=== Temporary Spending Increase ===');
console.log(`Card: ${cardId}`);
console.log(`Duration: ${durationHours} hours\n`);
try {
// Set temporary limits
console.log('Setting temporary limits...');
for (const [limitType, amount] of Object.entries(temporaryLimits)) {
const response = await setCardSpendingLimit({
card_id: cardId,
spending_limit: amount,
limit_type: limitType
});
if (response.code === 'SUCCESS') {
console.log(` ✓ ${limitType}: $${amount} (temporary)`);
} else {
console.log(` ✗ ${limitType}: Failed to set temporary limit`);
}
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log(`\n✓ Temporary limits active for ${durationHours} hours`);
console.log(`Automatic restoration scheduled...`);
// Schedule restoration
setTimeout(async () => {
console.log('\n=== Restoring Original Limits ===');
for (const [limitType, amount] of Object.entries(originalLimits)) {
const response = await setCardSpendingLimit({
card_id: cardId,
spending_limit: amount,
limit_type: limitType
});
if (response.code === 'SUCCESS') {
console.log(` ✓ ${limitType}: Restored to $${amount}`);
} else {
console.log(` ✗ ${limitType}: Failed to restore`);
}
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log('\n✓ Original limits restored');
// Send notification
await sendNotification({
type: 'limits_restored',
card_id: cardId,
message: 'Card spending limits have been restored to normal levels'
});
}, durationHours * 60 * 60 * 1000); // Convert hours to milliseconds
return {
success: true,
card_id: cardId,
temporary_limits: temporaryLimits,
original_limits: originalLimits,
restoration_time: new Date(Date.now() + durationHours * 60 * 60 * 1000)
};
} catch (error) {
console.error('Temporary spending increase failed:', error);
throw error;
}
}
// Example usage - Increase limits for a business trip
const result = await temporarySpendingIncrease(
'card2021062115091808923',
{
TRANSACTION: '100.00',
DAY: '500.00',
WEEK: '2000.00'
},
{
TRANSACTION: '500.00',
DAY: '2500.00',
WEEK: '10000.00'
},
48 // 48 hours
);
Dynamic Limit Adjustment Based on Usage
Adjust limits based on spending patterns:
def adjust_limits_based_on_usage(card_id, spending_history):
"""
Adjust card limits dynamically based on historical usage
"""
import statistics
print(f"\n=== Dynamic Limit Adjustment ===")
print(f"Card: {card_id}")
print(f"Analyzing {len(spending_history)} days of history...\n")
# Calculate usage statistics
daily_amounts = [day['amount'] for day in spending_history]
avg_daily = statistics.mean(daily_amounts)
max_daily = max(daily_amounts)
std_dev = statistics.stdev(daily_amounts) if len(daily_amounts) > 1 else 0
print(f"Average Daily Spend: ${avg_daily:.2f}")
print(f"Maximum Daily Spend: ${max_daily:.2f}")
print(f"Standard Deviation: ${std_dev:.2f}\n")
# Calculate recommended limits (with buffer)
buffer_multiplier = 1.5
recommended_limits = {
'TRANSACTION': max([tx['amount'] for day in spending_history for tx in day['transactions']]) * buffer_multiplier,
'DAY': max_daily * buffer_multiplier,
'WEEK': (avg_daily * 7) * buffer_multiplier,
'MONTH': (avg_daily * 30) * buffer_multiplier
}
print("Recommended Limits (with 50% buffer):")
for limit_type, amount in recommended_limits.items():
print(f" {limit_type}: ${amount:.2f}")
# Apply recommended limits
print("\nApplying recommended limits...")
results = []
for limit_type, amount in recommended_limits.items():
try:
response = set_card_spending_limit(
card_id=card_id,
spending_limit=f"{amount:.2f}",
limit_type=limit_type
)
if response['code'] == 'SUCCESS':
print(f" ✓ {limit_type}: ${amount:.2f}")
results.append({'type': limit_type, 'success': True})
else:
print(f" ✗ {limit_type}: Failed")
results.append({'type': limit_type, 'success': False})
time.sleep(0.5)
except Exception as e:
print(f" ✗ {limit_type}: Error - {e}")
results.append({'type': limit_type, 'success': False})
successful = sum(1 for r in results if r.get('success'))
print(f"\n✓ Adjusted {successful}/{len(recommended_limits)} limits")
return {
'card_id': card_id,
'statistics': {
'avg_daily': avg_daily,
'max_daily': max_daily,
'std_dev': std_dev
},
'recommended_limits': recommended_limits,
'applied': successful
}
# Example usage
spending_history = [
{
'date': '2026-02-01',
'amount': 450.00,
'transactions': [
{'amount': 120.00}, {'amount': 200.00}, {'amount': 130.00}
]
},
{
'date': '2026-02-02',
'amount': 320.00,
'transactions': [
{'amount': 80.00}, {'amount': 150.00}, {'amount': 90.00}
]
},
# ... more history
]
result = adjust_limits_based_on_usage('card2021062115091808923', spending_history)
Spending Limit Alerts
Monitor and alert when cards approach spending limits:
async function monitorCardSpendingLimits(cards) {
console.log('\n=== Card Spending Limit Monitor ===\n');
const alerts = [];
for (const card of cards) {
try {
// Get card details including current spending
const cardDetails = await getCardDetails(card.card_id);
const currentSpending = parseFloat(cardDetails.current_spending || 0);
const dailyLimit = parseFloat(card.daily_limit);
const utilizationPercent = (currentSpending / dailyLimit) * 100;
console.log(`Card: ${card.card_id} (${card.cardholder_name})`);
console.log(` Current Spending: $${currentSpending.toFixed(2)}`);
console.log(` Daily Limit: $${dailyLimit.toFixed(2)}`);
console.log(` Utilization: ${utilizationPercent.toFixed(1)}%`);
// Alert thresholds
if (utilizationPercent >= 90) {
console.log(` 🔴 CRITICAL: Approaching limit!\n`);
alerts.push({
card_id: card.card_id,
cardholder_name: card.cardholder_name,
level: 'CRITICAL',
utilization: utilizationPercent,
current_spending: currentSpending,
limit: dailyLimit
});
// Send alert
await sendAlert({
type: 'spending_limit_critical',
card_id: card.card_id,
cardholder: card.cardholder_name,
utilization: utilizationPercent,
message: `Card spending is at ${utilizationPercent.toFixed(1)}% of daily limit`
});
} else if (utilizationPercent >= 75) {
console.log(` 🟡 WARNING: High utilization\n`);
alerts.push({
card_id: card.card_id,
cardholder_name: card.cardholder_name,
level: 'WARNING',
utilization: utilizationPercent,
current_spending: currentSpending,
limit: dailyLimit
});
} else if (utilizationPercent >= 50) {
console.log(` 🟢 NOTICE: Moderate usage\n`);
} else {
console.log(` ✓ Normal usage\n`);
}
} catch (error) {
console.error(` ✗ Error monitoring card: ${error.message}\n`);
}
}
// Summary
console.log(`=== Monitoring Summary ===`);
console.log(`Total Cards: ${cards.length}`);
console.log(`Critical Alerts: ${alerts.filter(a => a.level === 'CRITICAL').length}`);
console.log(`Warnings: ${alerts.filter(a => a.level === 'WARNING').length}`);
return alerts;
}
// Example usage - Monitor every hour
const cardsToMonitor = [
{
card_id: 'card2021062115091808923',
cardholder_name: 'John Doe',
daily_limit: '500.00'
},
{
card_id: 'card2021062115091808924',
cardholder_name: 'Jane Smith',
daily_limit: '750.00'
}
];
setInterval(async () => {
const alerts = await monitorCardSpendingLimits(cardsToMonitor);
}, 3600000); // Check every hour
Best Practices
- Layer Limits: Set multiple limit types (transaction, daily, weekly) for comprehensive control
- Role-Based Limits: Configure limits based on employee roles and responsibilities
- Buffer Room: Set limits slightly higher than expected usage to avoid declined transactions
- Regular Review: Periodically review and adjust limits based on spending patterns
- Emergency Access: Have a process to quickly increase limits for urgent business needs
- Documentation: Document the rationale for limit settings for compliance
- Monitoring: Actively monitor spending against limits and alert on high utilization
Spending Limit Strategy
Recommended Limit Hierarchy
For best control, set limits in this order:
- TRANSACTION - Prevents single large unauthorized purchases
- DAY - Controls daily spending
- WEEK - Manages short-term spending trends
- MONTH - Enforces monthly budgets
- LIFETIME - Sets maximum total card usage
Sample Limit Configurations
Conservative (Entry-Level Employee)
- Transaction: $50
- Daily: $200
- Weekly: $750
- Monthly: $3,000
- Lifetime: $20,000
Moderate (Mid-Level Employee)
- Transaction: $200
- Daily: $1,000
- Weekly: $4,000
- Monthly: $15,000
- Lifetime: $100,000
Liberal (Executive)
- Transaction: $2,000
- Daily: $10,000
- Weekly: $50,000
- Monthly: $200,000
- Lifetime: $1,000,000
Related Endpoints
- Create Card - Issue new cards with initial spending limits
- Query Card Details - View current spending and limits
- Update Card - Modify other card settings
- Card Transaction History - Review spending against limits
Troubleshooting
Card Not Found (404)
- Cause: Invalid
card_idor card doesn't exist - Solution:
- Verify the card ID is correct
- Ensure the card was created successfully
- Check if card was closed or deleted
Invalid Limit Type (400)
- Cause: Unsupported
limit_typevalue - Solution:
- Use only: TRANSACTION, DAY, WEEK, MONTH, or LIFETIME
- Check for typos and use uppercase
Limit Amount Too Low (400)
- Cause: Spending limit is below minimum allowed
- Solution:
- Set limits above the minimum threshold
- Contact support for minimum limit requirements
Changes Not Taking Effect
- Cause: System lag or caching
- Solution:
- Wait a few seconds and retry
- Verify the limit was set by querying card details
- Contact support if issue persists
Security Considerations
- Authorization: Implement proper role-based access control for limit management
- Audit Trail: Log all limit changes with timestamps and responsible parties
- Approval Workflow: Require approval for limit increases above thresholds
- Alerts: Set up alerts for unusual limit modifications
- Review Process: Regularly review and validate limit settings