Create a Card
Overview
Use this endpoint to create a card object. Each card object reflects a card issued, including essential details such as card number and security code, transaction and spending limits, associated cardholder, etc. You may apply for a Shared Funds Card (draws from a budget account) or a Dedicated Funds Card (has its own isolated balance).
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/card/v2/apply
Staging (gateway.ahrvo.network)
POST https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/apply
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_product_code | string | Yes | Card product code to specify the card product. Consult your account manager or call the query card product endpoint |
apply_coupon | boolean | Yes | Use bonus account balance to pay card opening fee. true = use bonus balance, false = don't use bonus |
remark | string | No | An optional description to help identify the card |
transaction_amount_limit | string | No | Maximum amount for any single transaction. Default: 10,000,000 |
daily_limit | string | No | Maximum total amount for daily spending. Default: 10,000,000 |
weekly_limit | string | No | Maximum total amount for weekly spending. Default: 10,000,000 |
monthly_limit | string | No | Maximum total amount for monthly spending. Default: 10,000,000 |
lifetime_limit | string | No | Maximum total amount for card lifetime. Default: 10,000,000 |
budget_id | string | Conditional | Budget account ID for Shared Funds Cards. Required for Shared Funds Cards |
cardholder_id | string | Conditional | Cardholder ID for 3DS enrollment. Required for 3DS-enrolled cards |
Card Types
Shared Funds Card
- Draws funds from a budget account
- Multiple cards can share the same budget
- Requires
budget_idparameter
Dedicated Funds Card
- Has its own isolated balance
- Funded separately via top-up endpoint
- Does not require
budget_id
Request Example
{
"card_product_code": "T1FBXO",
"remark": "Marketing Team - John Doe",
"transaction_amount_limit": "500.00",
"daily_limit": "2000.00",
"weekly_limit": "8000.00",
"monthly_limit": "30000.00",
"lifetime_limit": "200000.00",
"apply_coupon": true,
"budget_id": "ci202008281528472924",
"cardholder_id": "273555991139442689"
}
Response
Success Response (200 OK)
{
"code": "SUCCESS",
"data": {
"card_id": "card201907021723076245"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | string | Status string indicating the result. "SUCCESS" refers to successful card creation |
data | object | Response data object |
data.card_id | string | A unique ID of the newly created card |
Error Responses
- 400 Bad Request: Invalid parameters, invalid card product code, or insufficient balance for card fee
- 401 Unauthorized: Invalid or missing authentication token
- 403 Forbidden: Card issuance feature not enabled for this account
- 404 Not Found: Budget account or card product does not exist
Code Examples
cURL
curl -X POST \
https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/apply \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{
"card_product_code": "T1FBXO",
"remark": "Marketing Team - John Doe",
"transaction_amount_limit": "500.00",
"daily_limit": "2000.00",
"weekly_limit": "8000.00",
"monthly_limit": "30000.00",
"lifetime_limit": "200000.00",
"apply_coupon": true,
"budget_id": "ci202008281528472924",
"cardholder_id": "273555991139442689"
}'
Python
import requests
url = "https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/apply"
headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
payload = {
"card_product_code": "T1FBXO",
"remark": "Marketing Team - John Doe",
"transaction_amount_limit": "500.00",
"daily_limit": "2000.00",
"weekly_limit": "8000.00",
"monthly_limit": "30000.00",
"lifetime_limit": "200000.00",
"apply_coupon": True,
"budget_id": "ci202008281528472924",
"cardholder_id": "273555991139442689"
}
response = requests.post(url, headers=headers, json=payload)
result = response.json()
if result['code'] == 'SUCCESS':
card_id = result['data']['card_id']
print(f"✓ Card created successfully")
print(f" Card ID: {card_id}")
print(f" Remark: {payload['remark']}")
else:
print(f"Failed to create card: {result}")
JavaScript (Node.js)
const axios = require('axios');
const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/card/v2/apply';
const headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const payload = {
card_product_code: 'T1FBXO',
remark: 'Marketing Team - John Doe',
transaction_amount_limit: '500.00',
daily_limit: '2000.00',
weekly_limit: '8000.00',
monthly_limit: '30000.00',
lifetime_limit: '200000.00',
apply_coupon: true,
budget_id: 'ci202008281528472924',
cardholder_id: '273555991139442689'
};
axios.post(url, payload, { headers })
.then(response => {
const result = response.data;
if (result.code === 'SUCCESS') {
console.log('✓ Card created successfully');
console.log(` Card ID: ${result.data.card_id}`);
console.log(` Remark: ${payload.remark}`);
}
})
.catch(error => {
console.error('Failed to create card:', error.response.data);
});
Usage Notes
- Card Product Code: Contact your account manager to obtain the correct card product code for your use case
- Spending Limits: If not specified, all limits default to 10,000,000
- Bonus Balance: Set
apply_coupon: trueto use bonus account balance for card opening fees - 3DS Enrollment: Provide
cardholder_idif the card needs 3DS authentication - Budget Account: Ensure the budget account has sufficient balance before creating Shared Funds Cards
- Amount Format: Provide amounts as strings with up to 2 decimal places
Common Use Cases
Create Employee Cards with Role-Based Limits
Issue cards for team members with spending limits based on their roles:
def create_employee_card(employee_name, role, budget_id, card_product_code):
"""
Create employee card with role-based spending limits
"""
# Define spending limits by role
limits_by_role = {
'intern': {
'transaction': '50.00',
'daily': '200.00',
'weekly': '750.00',
'monthly': '3000.00',
'lifetime': '20000.00'
},
'junior': {
'transaction': '100.00',
'daily': '500.00',
'weekly': '2000.00',
'monthly': '7500.00',
'lifetime': '50000.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'
}
}
limits = limits_by_role.get(role.lower())
if not limits:
raise ValueError(f"Unknown role: {role}")
print(f"\nCreating card for {employee_name} ({role})")
response = create_card(
card_product_code=card_product_code,
remark=f"{role.title()} - {employee_name}",
transaction_amount_limit=limits['transaction'],
daily_limit=limits['daily'],
weekly_limit=limits['weekly'],
monthly_limit=limits['monthly'],
lifetime_limit=limits['lifetime'],
apply_coupon=True,
budget_id=budget_id
)
if response['code'] == 'SUCCESS':
card_id = response['data']['card_id']
print(f"✓ Card created: {card_id}")
print(f" Transaction Limit: ${limits['transaction']}")
print(f" Daily Limit: ${limits['daily']}")
print(f" Monthly Limit: ${limits['monthly']}")
return {
'success': True,
'card_id': card_id,
'employee_name': employee_name,
'role': role,
'limits': limits
}
else:
print(f"✗ Failed to create card: {response}")
return {
'success': False,
'error': response
}
# Example usage
card = create_employee_card(
employee_name='John Doe',
role='manager',
budget_id='ci202008281528472924',
card_product_code='T1FBXO'
)
Bulk Card Issuance for Department
Create multiple cards for a department or team:
async function bulkCreateDepartmentCards(department, employees, budgetId, cardProductCode) {
console.log(`\n=== Bulk Card Issuance: ${department} ===`);
console.log(`Creating ${employees.length} cards...\n`);
const results = {
successful: [],
failed: []
};
for (const employee of employees) {
try {
console.log(`Creating card for ${employee.name}...`);
const response = await createCard({
card_product_code: cardProductCode,
remark: `${department} - ${employee.name}`,
transaction_amount_limit: employee.limits.transaction,
daily_limit: employee.limits.daily,
weekly_limit: employee.limits.weekly,
monthly_limit: employee.limits.monthly,
lifetime_limit: employee.limits.lifetime,
apply_coupon: true,
budget_id: budgetId,
cardholder_id: employee.cardholder_id
});
if (response.code === 'SUCCESS') {
const cardId = response.data.card_id;
console.log(` ✓ Card created: ${cardId}\n`);
results.successful.push({
employee_name: employee.name,
card_id: cardId,
limits: employee.limits
});
} else {
console.log(` ✗ Failed: ${response}\n`);
results.failed.push({
employee_name: employee.name,
error: response
});
}
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 1000));
} catch (error) {
console.error(` ✗ Error: ${error.message}\n`);
results.failed.push({
employee_name: employee.name,
error: error.message
});
}
}
// Summary
console.log(`\n=== Issuance Summary ===`);
console.log(`Department: ${department}`);
console.log(`✓ Successful: ${results.successful.length}`);
console.log(`✗ Failed: ${results.failed.length}`);
return results;
}
// Example usage
const marketingTeam = [
{
name: 'John Doe',
cardholder_id: '273555991139442689',
limits: {
transaction: '200.00',
daily: '1000.00',
weekly: '4000.00',
monthly: '15000.00',
lifetime: '100000.00'
}
},
{
name: 'Jane Smith',
cardholder_id: '273555991139442690',
limits: {
transaction: '500.00',
daily: '2500.00',
weekly: '10000.00',
monthly: '40000.00',
lifetime: '250000.00'
}
}
];
const results = await bulkCreateDepartmentCards(
'Marketing',
marketingTeam,
'ci202008281528472924',
'T1FBXO'
);
Create Card with 3DS Enrollment
Create a card and enroll it for 3D Secure authentication:
def create_card_with_3ds(employee_data, budget_id, card_product_code):
"""
Create card with 3DS enrollment in one workflow
"""
print(f"\n=== Creating 3DS-Enabled Card ===")
print(f"Employee: {employee_data['name']}")
# Step 1: Create 3DS cardholder
print("\n1. Creating 3DS cardholder...")
cardholder_response = create_3ds_cardholder(
mobile_number=employee_data['mobile'],
country_code=employee_data['country_code'],
budget_id=budget_id
)
if cardholder_response['code'] != 'SUCCESS':
print(f"✗ Failed to create cardholder: {cardholder_response}")
return {'success': False, 'error': 'Cardholder creation failed'}
cardholder_id = cardholder_response['data']['cardholder_id']
print(f"✓ Cardholder created: {cardholder_id}")
# Step 2: Create card with cardholder ID
print("\n2. Creating card with 3DS...")
card_response = create_card(
card_product_code=card_product_code,
remark=f"3DS Card - {employee_data['name']}",
transaction_amount_limit=employee_data['limits']['transaction'],
daily_limit=employee_data['limits']['daily'],
weekly_limit=employee_data['limits']['weekly'],
monthly_limit=employee_data['limits']['monthly'],
lifetime_limit=employee_data['limits']['lifetime'],
apply_coupon=True,
budget_id=budget_id,
cardholder_id=cardholder_id
)
if card_response['code'] != 'SUCCESS':
print(f"✗ Failed to create card: {card_response}")
return {'success': False, 'error': 'Card creation failed'}
card_id = card_response['data']['card_id']
print(f"✓ Card created: {card_id}")
# Step 3: Enroll card for 3DS
print("\n3. Enrolling card for 3DS...")
enrollment_response = enroll_card_3ds(
card_id=card_id,
cardholder_id=cardholder_id
)
if enrollment_response['code'] == 'SUCCESS':
print(f"✓ Card enrolled for 3DS")
return {
'success': True,
'card_id': card_id,
'cardholder_id': cardholder_id,
'employee_name': employee_data['name'],
'three_ds_enabled': True
}
else:
print(f"⚠ Card created but 3DS enrollment failed: {enrollment_response}")
return {
'success': True,
'card_id': card_id,
'cardholder_id': cardholder_id,
'employee_name': employee_data['name'],
'three_ds_enabled': False,
'warning': 'Card created but 3DS enrollment failed'
}
# Example usage
employee = {
'name': 'John Doe',
'mobile': '1234567890',
'country_code': '+1',
'limits': {
'transaction': '500.00',
'daily': '2000.00',
'weekly': '8000.00',
'monthly': '30000.00',
'lifetime': '200000.00'
}
}
result = create_card_with_3ds(
employee,
'ci202008281528472924',
'T1FBXO'
)
Create Dedicated Funds Card
Create a card with its own isolated balance:
async function createDedicatedFundsCard(employeeName, initialTopUp, cardProductCode) {
console.log('\n=== Creating Dedicated Funds Card ===');
console.log(`Employee: ${employeeName}`);
console.log(`Initial Top-Up: $${initialTopUp}`);
try {
// Step 1: Create the card (no budget_id for Dedicated Funds)
console.log('\n1. Creating card...');
const cardResponse = await createCard({
card_product_code: cardProductCode,
remark: `Dedicated Funds - ${employeeName}`,
transaction_amount_limit: '200.00',
daily_limit: '1000.00',
weekly_limit: '4000.00',
monthly_limit: '15000.00',
lifetime_limit: '100000.00',
apply_coupon: true
// Note: No budget_id for Dedicated Funds Cards
});
if (cardResponse.code === 'SUCCESS') {
const cardId = cardResponse.data.card_id;
console.log(`✓ Card created: ${cardId}`);
// Step 2: Top up the card with initial funds
if (initialTopUp > 0) {
console.log('\n2. Adding initial funds...');
const topUpResponse = await topUpDedicatedCard({
card_id: cardId,
amount: initialTopUp.toFixed(2),
unique_order_id: `topup_${Date.now()}`
});
if (topUpResponse.code === 'SUCCESS') {
console.log(`✓ Card topped up with $${initialTopUp}`);
return {
success: true,
card_id: cardId,
employee_name: employeeName,
card_type: 'Dedicated Funds',
initial_balance: initialTopUp
};
} else {
console.log(`⚠ Card created but top-up failed: ${topUpResponse}`);
return {
success: true,
card_id: cardId,
employee_name: employeeName,
card_type: 'Dedicated Funds',
initial_balance: 0,
warning: 'Top-up failed'
};
}
} else {
return {
success: true,
card_id: cardId,
employee_name: employeeName,
card_type: 'Dedicated Funds',
initial_balance: 0
};
}
} else {
console.log(`✗ Failed to create card: ${cardResponse}`);
return {
success: false,
error: cardResponse
};
}
} catch (error) {
console.error('Error creating dedicated funds card:', error);
throw error;
}
}
// Example usage
const result = await createDedicatedFundsCard(
'John Doe',
1000.00,
'T1FBXO'
);
Card Creation with Validation
Create a card with pre-validation checks:
def create_card_with_validation(card_config, budget_id, card_product_code):
"""
Create card with comprehensive validation
"""
print("\n=== Card Creation with Validation ===")
validations = []
# Validation 1: Check budget exists and has funds
print("\n1. Validating budget account...")
try:
budget_response = query_budget_balance(budget_id)
if budget_response['code'] == 'SUCCESS':
budget_balance = float(budget_response['data']['balance'])
print(f"✓ Budget exists with balance: ${budget_balance}")
if budget_balance < 100: # Minimum threshold
print(f"⚠ Warning: Budget balance is low (${budget_balance})")
validations.append({
'check': 'budget_balance',
'status': 'warning',
'message': f'Low balance: ${budget_balance}'
})
else:
validations.append({
'check': 'budget_balance',
'status': 'passed'
})
else:
print(f"✗ Budget validation failed: {budget_response}")
return {
'success': False,
'error': 'Budget validation failed',
'validations': validations
}
except Exception as e:
print(f"✗ Error validating budget: {e}")
return {
'success': False,
'error': f'Budget validation error: {e}',
'validations': validations
}
# Validation 2: Verify spending limits hierarchy
print("\n2. Validating spending limits...")
limits = card_config['limits']
transaction_limit = float(limits['transaction'])
daily_limit = float(limits['daily'])
weekly_limit = float(limits['weekly'])
monthly_limit = float(limits['monthly'])
lifetime_limit = float(limits['lifetime'])
if not (transaction_limit <= daily_limit <= weekly_limit <= monthly_limit <= lifetime_limit):
print("✗ Invalid limit hierarchy")
print(f" Transaction: {transaction_limit}")
print(f" Daily: {daily_limit}")
print(f" Weekly: {weekly_limit}")
print(f" Monthly: {monthly_limit}")
print(f" Lifetime: {lifetime_limit}")
return {
'success': False,
'error': 'Invalid spending limit hierarchy',
'validations': validations
}
else:
print("✓ Spending limits hierarchy is valid")
validations.append({
'check': 'limit_hierarchy',
'status': 'passed'
})
# Validation 3: Check cardholder exists (if 3DS)
if card_config.get('cardholder_id'):
print("\n3. Validating cardholder...")
try:
cardholder_response = query_3ds_cardholder(
cardholder_id=card_config['cardholder_id']
)
if cardholder_response['code'] == 'SUCCESS':
print(f"✓ Cardholder validated")
validations.append({
'check': 'cardholder',
'status': 'passed'
})
else:
print(f"✗ Cardholder validation failed")
return {
'success': False,
'error': 'Cardholder validation failed',
'validations': validations
}
except Exception as e:
print(f"✗ Error validating cardholder: {e}")
return {
'success': False,
'error': f'Cardholder validation error: {e}',
'validations': validations
}
# All validations passed - create card
print("\n4. Creating card...")
try:
response = create_card(
card_product_code=card_product_code,
remark=card_config['remark'],
transaction_amount_limit=limits['transaction'],
daily_limit=limits['daily'],
weekly_limit=limits['weekly'],
monthly_limit=limits['monthly'],
lifetime_limit=limits['lifetime'],
apply_coupon=True,
budget_id=budget_id,
cardholder_id=card_config.get('cardholder_id')
)
if response['code'] == 'SUCCESS':
card_id = response['data']['card_id']
print(f"✓ Card created successfully: {card_id}")
return {
'success': True,
'card_id': card_id,
'validations': validations
}
else:
print(f"✗ Card creation failed: {response}")
return {
'success': False,
'error': response,
'validations': validations
}
except Exception as e:
print(f"✗ Error creating card: {e}")
return {
'success': False,
'error': str(e),
'validations': validations
}
# Example usage
card_config = {
'remark': 'Sales Team - John Doe',
'limits': {
'transaction': '200.00',
'daily': '1000.00',
'weekly': '4000.00',
'monthly': '15000.00',
'lifetime': '100000.00'
},
'cardholder_id': '273555991139442689'
}
result = create_card_with_validation(
card_config,
'ci202008281528472924',
'T1FBXO'
)
Best Practices
- Spending Limits: Always set appropriate spending limits based on employee roles and responsibilities
- Limit Hierarchy: Ensure transaction ≤ daily ≤ weekly ≤ monthly ≤ lifetime
- Remarks: Use descriptive remarks (e.g., "Department - Employee Name") for easy identification
- Budget Validation: Verify budget account has sufficient balance before creating Shared Funds Cards
- 3DS Enrollment: For enhanced security, create cardholder and enroll cards in 3DS
- Card Products: Consult your account manager to select the appropriate card product code
- Bonus Balance: Set
apply_coupon: trueto use bonus balance for card fees when available
Card Creation Workflow
Standard Process
- Select Card Type: Decide between Shared Funds or Dedicated Funds
- Obtain Product Code: Get the appropriate card product code from your account manager
- Create Budget (if Shared Funds): Ensure budget account exists with sufficient funds
- Create Cardholder (if 3DS): Create cardholder for 3DS authentication
- Set Spending Limits: Define appropriate limits based on use case
- Create Card: Call this endpoint with all required parameters
- Store Card ID: Save the returned
card_idfor future operations - Fund Card (if Dedicated Funds): Top up the card with initial balance
Related Endpoints
- Create Budget Account - Create budget accounts for Shared Funds Cards
- Create 3DS Cardholder - Create cardholder for 3DS enrollment
- Enroll Card for 3DS - Enroll cards for 3D Secure authentication
- Control Card Spending - Update spending limits after card creation
- Top Up Dedicated Funds Card - Add funds to Dedicated Funds Cards
- Query Card Details - View card information and status
Troubleshooting
Invalid Card Product Code (400)
- Cause: The
card_product_codeis invalid or not available - Solution:
- Contact your account manager for valid card product codes
- Query available card products using the card product endpoint
Budget Not Found (404)
- Cause: The specified
budget_iddoesn't exist - Solution:
- Verify the budget ID is correct
- Create the budget account first using Create Budget Account endpoint
Insufficient Balance for Card Fee (400)
- Cause: Not enough funds to pay the card opening fee
- Solution:
- Top up your account or budget
- Set
apply_coupon: trueto use bonus balance if available
Invalid Spending Limit Hierarchy (400)
- Cause: Spending limits don't follow proper hierarchy
- Solution:
- Ensure: transaction ≤ daily ≤ weekly ≤ monthly ≤ lifetime
- Review and correct limit values
Cardholder Not Found (404)
- Cause: The specified
cardholder_iddoesn't exist - Solution:
- Create the cardholder first using Create 3DS Cardholder endpoint
- Verify the cardholder ID is correct
Security Considerations
- Spending Limits: Set conservative limits initially, can be increased later if needed
- Access Control: Implement proper authorization before allowing card creation
- Audit Trail: Log all card creation events with timestamps and responsible parties
- Card Remarks: Use consistent naming conventions for easy tracking
- Approval Workflow: Require approval for high-limit cards