Skip to main content

Update Card Remark

Overview

Use this endpoint to update a card's remark field. Remarks are custom descriptions or labels that help you organize, identify, and manage cards more effectively. The remark field is for your internal reference only and is not visible to cardholders.

Common uses for remarks include:

  • Identifying the card's purpose (e.g., "Marketing Budget Q1")
  • Noting the department or team using the card
  • Tracking campaign or project associations
  • Adding employee names or IDs
  • Recording special conditions or limitations

NOTE: This API is offered on a client-by-client approval basis. Speak to your account manager to check eligibility.

TIP: You can set remark to an empty string ("") to clear the existing remark.

Resource Access

Production (api.ahrvo.network)

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

Staging (gateway.ahrvo.network)

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

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
remarkstringYesDescription to help identify the card. Set to empty string to clear remark

Request Example

{
"card_id": "card2020092710410645531",
"remark": "Marketing Team - Q1 2026 Campaign"
}

Clear Remark Example

{
"card_id": "card2020092710410645531",
"remark": ""
}

Response

Success Response (200 OK)

{
"code": "SUCCESS"
}

Response Fields

FieldTypeDescription
codestringStatus string indicating the result. "SUCCESS" refers to a successful update

Error Responses

  • 400 Bad Request: Invalid card_id or remark 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/card/v2/remark' \
-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": "card2020092710410645531",
"remark": "Marketing Team - Q1 2026 Campaign"
}'

Python

import requests

url = "https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/remark"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"card_id": "card2020092710410645531",
"remark": "Marketing Team - Q1 2026 Campaign"
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
print("✓ Card remark updated successfully!")
print(f" Card ID: {payload['card_id']}")
print(f" New Remark: {payload['remark']}")
else:
print(f"Failed to update card remark: {result}")

JavaScript (Node.js)

const axios = require('axios');

const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/remark';
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const payload = {
card_id: 'card2020092710410645531',
remark: 'Marketing Team - Q1 2026 Campaign'
};

axios.post(url, payload, { headers })
.then(response => {
const result = response.data;

if (result.code === 'SUCCESS') {
console.log('✓ Card remark updated successfully!');
console.log(` Card ID: ${payload.card_id}`);
console.log(` New Remark: ${payload.remark}`);
}
})
.catch(error => {
console.error('Failed to update card remark:', error.response.data);
});

Usage Notes

  • Internal Reference: Remarks are for your internal use and not shown to cardholders
  • Searchable: Use Query All Cards endpoint to filter cards by remark
  • Flexible Format: No strict format requirements - use what works for your organization
  • Unlimited Updates: Remarks can be updated as many times as needed
  • Clear Remarks: Set to empty string to remove existing remark
  • Unicode Support: Supports international characters and emojis

Common Use Cases

Organize Cards by Department

Label cards by department or team for easy identification:

def assign_card_to_department(card_id, department_name, employee_name=None):
"""
Update card remark to indicate department and optionally employee

Args:
card_id: Card ID to update
department_name: Name of the department
employee_name: Optional employee name
"""
print(f"\n=== Assign Card to Department ===")
print(f"Card ID: {card_id}")
print(f"Department: {department_name}")
if employee_name:
print(f"Employee: {employee_name}")
print()

# Build remark
if employee_name:
remark = f"{department_name} - {employee_name}"
else:
remark = department_name

payload = {
"card_id": card_id,
"remark": remark
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
print("✓ Card assigned successfully!")
print(f" Remark set to: '{remark}'")

# Log the assignment
log_card_assignment({
'card_id': card_id,
'department': department_name,
'employee': employee_name,
'remark': remark,
'timestamp': datetime.now().isoformat()
})

return {
'success': True,
'card_id': card_id,
'remark': remark
}
else:
print(f"✗ Failed to assign card: {result}")
return {'success': False, 'error': result}

# Example usage
result = assign_card_to_department(
'card2020092710410645531',
'Marketing',
'John Smith'
)

# Organize by department only
assign_card_to_department(
'card2020092710410645532',
'Engineering'
)

# More examples
assign_card_to_department('card001', 'Sales', 'Jane Doe')
assign_card_to_department('card002', 'HR', 'Bob Johnson')
assign_card_to_department('card003', 'Finance')

Tag Cards by Campaign or Project

Track which campaign or project a card is associated with:

async function tagCardForCampaign(cardId, campaignName, startDate, endDate) {
console.log('\n=== Tag Card for Campaign ===');
console.log(`Card: ${cardId}`);
console.log(`Campaign: ${campaignName}`);
console.log(`Period: ${startDate} to ${endDate}\n`);

// Build campaign remark with dates
const remark = `Campaign: ${campaignName} | ${startDate} - ${endDate}`;

const payload = {
card_id: cardId,
remark: remark
};

try {
const response = await updateCardRemark(payload);

if (response.code === 'SUCCESS') {
console.log('✓ Card tagged for campaign!');
console.log(` Remark: ${remark}`);

// Store campaign metadata
await storeCampaignMetadata({
card_id: cardId,
campaign_name: campaignName,
start_date: startDate,
end_date: endDate,
tagged_at: new Date().toISOString()
});

// Set reminder to review after campaign ends
await scheduleRemarkUpdate(cardId, endDate, 'Clear campaign tag');

return {
success: true,
card_id: cardId,
remark: remark
};
} else {
console.log('✗ Failed to tag card:', response);
return { success: false, error: response };
}
} catch (error) {
console.error('Error tagging card:', error.message);
return { success: false, error: error.message };
}
}

async function storeCampaignMetadata(metadata) {
// Store in your database
console.log(' 📊 Campaign metadata stored');
}

async function scheduleRemarkUpdate(cardId, date, action) {
// Schedule future reminder
console.log(` 📅 Reminder scheduled for ${date}: ${action}`);
}

// Example usage
await tagCardForCampaign(
'card2020092710410645531',
'Spring Sale 2026',
'2026-03-01',
'2026-03-31'
);

await tagCardForCampaign(
'card2020092710410645532',
'Product Launch - Widget Pro',
'2026-02-15',
'2026-04-15'
);

Batch Update Remarks for Multiple Cards

Update remarks for multiple cards at once:

def batch_update_card_remarks(updates):
"""
Update remarks for multiple cards

Args:
updates: List of dicts with 'card_id' and 'remark'
"""
from datetime import datetime

print("\n" + "=" * 70)
print("BATCH CARD REMARK UPDATE".center(70))
print("=" * 70)
print(f"Started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"Total Cards: {len(updates)}\n")

results = {
'successful': [],
'failed': []
}

for idx, update in enumerate(updates, 1):
card_id = update['card_id']
remark = update['remark']

print(f"[{idx}/{len(updates)}] Updating {card_id}...")
print(f" New Remark: '{remark}'")

try:
payload = {
"card_id": card_id,
"remark": remark
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
print(f" ✓ Updated successfully\n")

results['successful'].append({
'card_id': card_id,
'remark': remark
})
else:
print(f" ✗ Failed: {result.get('message', 'Unknown error')}\n")

results['failed'].append({
'card_id': card_id,
'remark': remark,
'error': result
})

except Exception as e:
print(f" ✗ Exception: {e}\n")

results['failed'].append({
'card_id': card_id,
'remark': remark,
'error': str(e)
})

# Summary
print("=" * 70)
print("BATCH UPDATE SUMMARY".center(70))
print("=" * 70)
print(f"Total Cards: {len(updates)}")
print(f"Successful: {len(results['successful'])} ✓")
print(f"Failed: {len(results['failed'])} ✗")

if results['failed']:
print(f"\n⚠️ Failed Updates:")
for item in results['failed']:
print(f" • {item['card_id']}: {item.get('error', 'Unknown error')}")

print("\n" + "=" * 70 + "\n")

return results

# Example usage - batch update for department reorganization
updates = [
{'card_id': 'card2020092710410645531', 'remark': 'Sales - East Region'},
{'card_id': 'card2020092710410645532', 'remark': 'Sales - West Region'},
{'card_id': 'card2020092710410645533', 'remark': 'Sales - Central Region'},
{'card_id': 'card2020092710410645534', 'remark': 'Marketing - Digital'},
{'card_id': 'card2020092710410645535', 'remark': 'Marketing - Events'}
]

results = batch_update_card_remarks(updates)

print(f"Batch complete: {len(results['successful'])}/{len(updates)} successful")

Auto-Generate Remarks from Card Metadata

Automatically generate descriptive remarks based on card properties:

async function autoGenerateCardRemark(cardId) {
console.log('\n=== Auto-Generate Card Remark ===');
console.log(`Card: ${cardId}\n`);

try {
// Get card details
console.log('Step 1: Fetching card details...');
const cardDetails = await queryCardDetails(cardId);

if (cardDetails.code !== 'SUCCESS') {
console.log('✗ Failed to get card details');
return { success: false, error: cardDetails };
}

const data = cardDetails.data;
const cardNumber = data.card_number;
const cardStatus = data.card_status;
const cardType = data.share ? 'Shared' : 'Dedicated';
const createdDate = new Date(data.create_time);

console.log(` Card: ${cardNumber}`);
console.log(` Type: ${cardType} Funds`);
console.log(` Status: ${cardStatus}`);

// Build intelligent remark
console.log('\nStep 2: Generating remark...');

const remarkParts = [];

// Add type
remarkParts.push(cardType);

// Add budget info if available
if (data.budget_id) {
remarkParts.push(`Budget: ${data.budget_id}`);
}

// Add cardholder if available
if (data.cardholder_id) {
remarkParts.push(`Holder: ${data.cardholder_id}`);
}

// Add creation date
const monthYear = createdDate.toLocaleDateString('en-US', {
month: 'short',
year: 'numeric'
});
remarkParts.push(`Created: ${monthYear}`);

// Add status indicator if not active
if (cardStatus !== 'ACTIVE') {
remarkParts.push(`[${cardStatus}]`);
}

const generatedRemark = remarkParts.join(' | ');

console.log(` Generated: "${generatedRemark}"`);

// Update card remark
console.log('\nStep 3: Updating card remark...');

const payload = {
card_id: cardId,
remark: generatedRemark
};

const response = await updateCardRemark(payload);

if (response.code === 'SUCCESS') {
console.log('✓ Remark auto-generated and updated!');
console.log(` Card: ${cardNumber}`);
console.log(` Remark: "${generatedRemark}"`);

return {
success: true,
card_id: cardId,
card_number: cardNumber,
remark: generatedRemark
};
} else {
console.log('✗ Failed to update remark:', response);
return { success: false, error: response };
}
} catch (error) {
console.error('Error auto-generating remark:', error.message);
return { success: false, error: error.message };
}
}

// Example usage - auto-generate for multiple cards
async function autoGenerateRemarksForAll(cardIds) {
console.log(`\n🤖 Auto-Generating Remarks for ${cardIds.length} card(s)\n`);

const results = [];

for (const cardId of cardIds) {
const result = await autoGenerateCardRemark(cardId);
results.push(result);
}

const successful = results.filter(r => r.success).length;
console.log(`\n✅ Complete: ${successful}/${cardIds.length} remarks generated`);

return results;
}

const cardList = [
'card2020092710410645531',
'card2020092710410645532',
'card2020092710410645533'
];

await autoGenerateRemarksForAll(cardList);

Track Card Lifecycle with Remark Updates

Update remarks as cards move through different states:

def update_card_lifecycle_remark(card_id, event_type, details=None):
"""
Update card remark to reflect lifecycle events

Args:
card_id: Card ID to update
event_type: Type of event (assigned, frozen, unfrozen, low_balance, etc.)
details: Additional details about the event
"""
from datetime import datetime

print(f"\n=== Card Lifecycle Remark Update ===")
print(f"Card: {card_id}")
print(f"Event: {event_type}")
if details:
print(f"Details: {details}")
print()

# Get current card details
card_details = query_card_details(card_id)

if card_details['code'] != 'SUCCESS':
print(f"✗ Failed to get card details")
return {'success': False, 'error': card_details}

current_remark = card_details['data'].get('remark', '')
card_number = card_details['data']['card_number']

print(f"Current Remark: '{current_remark}'")

# Build new remark based on event
timestamp = datetime.now().strftime('%Y-%m-%d')

lifecycle_remarks = {
'assigned': f"Assigned to {details} on {timestamp}",
'frozen': f"FROZEN on {timestamp} - {details or 'Security hold'}",
'unfrozen': f"Unfrozen on {timestamp} - {details or 'Security cleared'}",
'low_balance': f"⚠️ Low Balance Alert - {timestamp}",
'topped_up': f"Last topped up: {timestamp}",
'high_usage': f"🔥 High Usage Card - {timestamp}",
'dormant': f"Dormant since {timestamp}",
'campaign_start': f"Campaign: {details} - Started {timestamp}",
'campaign_end': f"Campaign: {details} - Ended {timestamp}",
'department_transfer': f"Transferred to {details} on {timestamp}"
}

new_remark = lifecycle_remarks.get(event_type, f"{event_type} - {timestamp}")

if details and event_type not in ['assigned', 'frozen', 'unfrozen',
'campaign_start', 'campaign_end',
'department_transfer']:
new_remark = f"{new_remark} - {details}"

print(f"New Remark: '{new_remark}'")

# Update remark
payload = {
"card_id": card_id,
"remark": new_remark
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
print(f"\n✓ Lifecycle remark updated!")
print(f" Card: {card_number}")
print(f" Event: {event_type}")
print(f" Remark: '{new_remark}'")

# Log the lifecycle event
log_lifecycle_event({
'card_id': card_id,
'card_number': card_number,
'event_type': event_type,
'previous_remark': current_remark,
'new_remark': new_remark,
'details': details,
'timestamp': datetime.now().isoformat()
})

return {
'success': True,
'card_id': card_id,
'event_type': event_type,
'new_remark': new_remark
}
else:
print(f"\n✗ Failed to update remark: {result}")
return {'success': False, 'error': result}

def log_lifecycle_event(event):
"""Log lifecycle event to audit trail"""
# Implement your logging
pass

# Example usage - various lifecycle events

# Card assigned to employee
update_card_lifecycle_remark(
'card2020092710410645531',
'assigned',
'John Smith - Marketing'
)

# Card frozen for security
update_card_lifecycle_remark(
'card2020092710410645532',
'frozen',
'Suspicious transaction detected'
)

# Card unfrozen after verification
update_card_lifecycle_remark(
'card2020092710410645532',
'unfrozen',
'Verified with cardholder'
)

# Low balance alert
update_card_lifecycle_remark(
'card2020092710410645533',
'low_balance',
'Balance below $100'
)

# Campaign started
update_card_lifecycle_remark(
'card2020092710410645534',
'campaign_start',
'Spring Sale 2026'
)

# High usage detected
update_card_lifecycle_remark(
'card2020092710410645535',
'high_usage',
'Over 50 transactions this month'
)

Search and Filter Cards by Remark

Find cards using their remarks:

async function searchCardsByRemark(searchTerm) {
console.log(`\n🔍 Searching cards by remark: "${searchTerm}"\n`);

try {
// Query all cards
const allCards = await queryAllCards({ page_no: 1, page_size: 100 });

if (allCards.code !== 'SUCCESS') {
console.log('✗ Failed to query cards');
return { success: false, error: allCards };
}

const cards = allCards.data.details;

// Filter by remark (case-insensitive)
const matchingCards = cards.filter(card => {
const remark = card.remark || '';
return remark.toLowerCase().includes(searchTerm.toLowerCase());
});

console.log(`Found ${matchingCards.length} matching card(s):\n`);

matchingCards.forEach((card, index) => {
console.log(`${index + 1}. ${card.card_number}`);
console.log(` Remark: "${card.remark}"`);
console.log(` Status: ${card.card_status}`);
console.log(` Type: ${card.share ? 'Shared' : 'Dedicated'} Funds\n`);
});

return {
success: true,
search_term: searchTerm,
total_cards: cards.length,
matching_cards: matchingCards.length,
results: matchingCards
};
} catch (error) {
console.error('Error searching cards:', error.message);
return { success: false, error: error.message };
}
}

// Example searches
await searchCardsByRemark('Marketing'); // Find all marketing cards
await searchCardsByRemark('Campaign'); // Find campaign cards
await searchCardsByRemark('John Smith'); // Find cards assigned to John
await searchCardsByRemark('FROZEN'); // Find frozen cards (if marked in remark)
await searchCardsByRemark('Q1 2026'); // Find Q1 2026 cards

// Advanced: Group cards by remark pattern
async function groupCardsByRemarkPattern() {
console.log('\n📊 Grouping Cards by Remark Pattern\n');

const allCards = await queryAllCards({ page_no: 1, page_size: 100 });

if (allCards.code !== 'SUCCESS') {
console.log('✗ Failed to query cards');
return;
}

const cards = allCards.data.details;
const groups = {};

cards.forEach(card => {
const remark = card.remark || 'No Remark';

// Extract department/category (first word/phrase before dash or pipe)
const category = remark.split(/[-|]/)[0].trim();

if (!groups[category]) {
groups[category] = [];
}

groups[category].push(card);
});

// Display groups
Object.keys(groups).sort().forEach(category => {
const count = groups[category].length;
console.log(`${category}: ${count} card(s)`);

groups[category].forEach(card => {
console.log(`${card.card_number} - "${card.remark}"`);
});
console.log();
});

return groups;
}

await groupCardsByRemarkPattern();

Clear Remarks for Inactive Cards

Remove remarks from cards that are no longer active:

def clear_remarks_for_inactive_cards(days_inactive=90):
"""
Clear remarks for cards that haven't been used recently

Args:
days_inactive: Number of days without activity to consider inactive
"""
from datetime import datetime, timedelta

print("\n" + "=" * 70)
print("CLEAR REMARKS FOR INACTIVE CARDS".center(70))
print("=" * 70)
print(f"Inactivity threshold: {days_inactive} days\n")

# Calculate cutoff date
cutoff_date = datetime.now() - timedelta(days=days_inactive)

print(f"Identifying cards inactive since: {cutoff_date.strftime('%Y-%m-%d')}\n")

# Query all cards
all_cards = query_all_cards()

if all_cards['code'] != 'SUCCESS':
print(f"✗ Failed to query cards")
return

cards = all_cards['data']['details']
inactive_cards = []

# Identify inactive cards with remarks
for card in cards:
card_id = card['card_id']
card_number = card['card_number']
remark = card.get('remark', '')

if not remark:
continue # Skip cards without remarks

# Check last activity (implement based on your tracking)
last_activity = get_card_last_activity(card_id)

if last_activity and last_activity < cutoff_date:
inactive_cards.append({
'card_id': card_id,
'card_number': card_number,
'remark': remark,
'last_activity': last_activity
})

print(f"Found {len(inactive_cards)} inactive card(s) with remarks\n")

if not inactive_cards:
print("✓ No inactive cards with remarks to clear\n")
return

# Clear remarks
results = {
'cleared': 0,
'failed': 0
}

for card in inactive_cards:
card_id = card['card_id']
card_number = card['card_number']

print(f"Clearing remark for {card_number}...")
print(f" Current Remark: '{card['remark']}'")
print(f" Last Activity: {card['last_activity'].strftime('%Y-%m-%d')}")

payload = {
"card_id": card_id,
"remark": "" # Clear remark
}

response = requests.post(url, headers=headers, json=payload)
result = response.json()

if result['code'] == 'SUCCESS':
print(f" ✓ Remark cleared\n")
results['cleared'] += 1
else:
print(f" ✗ Failed to clear remark\n")
results['failed'] += 1

# Summary
print("=" * 70)
print("CLEAR REMARKS SUMMARY".center(70))
print("=" * 70)
print(f"Inactive Cards Found: {len(inactive_cards)}")
print(f"Remarks Cleared: {results['cleared']} ✓")
print(f"Failed: {results['failed']} ✗")
print("\n" + "=" * 70 + "\n")

return results

def get_card_last_activity(card_id):
"""Get last activity date for a card"""
# Implement based on your transaction/activity tracking
# This is a mock implementation
from datetime import datetime, timedelta
import random
return datetime.now() - timedelta(days=random.randint(30, 180))

# Example usage
results = clear_remarks_for_inactive_cards(days_inactive=90)

Best Practices

  • Consistent Format: Use a consistent format for remarks across your organization
  • Meaningful Labels: Make remarks descriptive and searchable
  • Include Dates: Add dates for time-sensitive information
  • Use Separators: Use | or - to separate different pieces of information
  • Keep Updated: Update remarks as card usage or purpose changes
  • Search-Friendly: Use keywords that make cards easy to find
  • Clear When Done: Remove remarks for inactive or closed cards

Remark Format Examples

Department Format:
"Marketing - Digital Ads Team"
"Sales - East Region - John Smith"
"Engineering - Infrastructure"

Campaign Format:
"Campaign: Spring Sale | 2026-03-01 to 2026-03-31"
"Project: Website Redesign | Active"

Status Format:
"High Priority | Marketing Q1 Budget"
"Temporary Card | Expires 2026-06-30"
"VIP Client Services | 24/7 Active"

Employee Format:
"Employee: John Smith | Marketing | EMP-12345"
"Contractor: Jane Doe | 2026-01 to 2026-06"
  • Query All Cards - Search cards by remark using the remark filter
  • Query Card Details - View current card remark
  • Create a Card - Set initial remark when creating card
  • Freeze a Card - Update remark to note freeze reason
  • Unfreeze a Card - Update remark to clear freeze note

Troubleshooting

Card Not Found (404)

  • Cause: Invalid card_id or card doesn't exist
  • Solution:
    • Verify the card ID is correct
    • Use Query All Cards to list available cards
    • Check if card was deleted

Remark Not Updating

  • Cause: API returned success but remark unchanged
  • Solution:
    • Query card details to verify remark was updated
    • Check for caching if viewing through UI
    • Ensure the new remark is different from the old one

Empty Remark Not Clearing

  • Cause: Using null instead of empty string
  • Solution:
    • Use "" (empty string) to clear remarks
    • Don't use null or omit the field

Security Considerations

  • Internal Use Only: Remarks are for internal reference and should not contain sensitive data
  • Access Control: Restrict remark updates to authorized users
  • Audit Trail: Log all remark changes for compliance
  • No PII: Avoid storing personally identifiable information in remarks
  • Data Privacy: Be mindful of what information is stored in remarks
  • Regular Cleanup: Periodically review and clean up outdated remarks

Interactive API Explorer