Skip to main content

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

HeaderValueRequiredDescription
Acceptapplication/jsonYesContent type for the response
Content-Typeapplication/jsonYesContent type of the request body
AuthorizationBearer {access_token}YesBearer token for authentication
x-api-keyAPI KeyYesAPI key for authentication

Request Body

FieldTypeRequiredDescription
card_idstringYesA unique ID of the card
spending_limitstringYesMonetary amount of the spending limit expressed in USD. Must be a positive number with up to 2 decimal places
limit_typestringYesDefine the card spending limit interval. See limit types below

Limit Types

TypeDescription
TRANSACTIONSpending limit per single transaction
DAYDaily spending limit (resets every 24 hours)
WEEKWeekly spending limit (resets every 7 days)
MONTHMonthly spending limit (resets every 30 days)
LIFETIMELifetime 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

FieldTypeDescription
codestringStatus 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

For best control, set limits in this order:

  1. TRANSACTION - Prevents single large unauthorized purchases
  2. DAY - Controls daily spending
  3. WEEK - Manages short-term spending trends
  4. MONTH - Enforces monthly budgets
  5. 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
  • 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_id or 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_type value
  • 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

Interactive API Explorer