Query 3DS Enrollment Details
Overview
Use this endpoint to query the 3D Secure enrollment details of a specific card. This returns the complete cardholder information associated with the card, including contact details used for OTP delivery during 3DS authentication. This is useful for verifying enrollment status and reviewing the cardholder information linked to a card.
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)
GET https://api.ahrvo.network/card/issuance/api/issuing/3ds/v2/detail
Staging (gateway.ahrvo.network)
GET https://gateway.ahrvo.network/card/issuance/api/issuing/3ds/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 to query enrollment details for |
Response
Success Response (200 OK)
{
"code": "SUCCESS",
"data": {
"cardholder_id": "471041678120300545",
"budget_id": "ci202210231533401801",
"first_name": "Emma",
"last_name": "Johnson",
"email": "emma.johnson@example.com",
"call_prefix": "+1",
"mobile": "2125551234",
"date_of_birth": "1996-10-31",
"country": "United States",
"country_code": "US",
"state": "Illinois",
"city": "Chicago",
"address_line": "456 Maple Avenue",
"post_code": "60601",
"security_index": "2",
"security_question": "What is your maternal grandmother's maiden name?",
"security_answer": "Han"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | string | Status string indicating the result. "SUCCESS" refers to a successful query |
data | object | Response data object containing cardholder information |
Cardholder Data Fields
| Field | Type | Description |
|---|---|---|
cardholder_id | string | A unique ID of the cardholder enrolled for this card |
budget_id | string | ID of the budget account this cardholder associates with |
first_name | string | First name of the cardholder |
last_name | string | Last name of the cardholder |
email | string | Email of the cardholder (used for OTP delivery) |
call_prefix | string | Country code of the mobile number (e.g., +1, +44) |
mobile | string | Mobile number of the cardholder, without country code (used for OTP delivery) |
date_of_birth | string | Date of birth of the cardholder (YYYY-MM-DD) |
country | string | Full country name of the cardholder |
country_code | string | Country in ISO 3166 format (e.g., US) |
state | string | State of the cardholder |
city | string | City of the cardholder |
address_line | string | Address of the cardholder |
post_code | string | Post code of the cardholder |
security_index | string | Index of security question (1-5) |
security_question | string | The full text of the security question |
security_answer | string | Answer to the security question |
Security Questions Reference
| Index | Security Question |
|---|---|
1 | What was your first pet's name? |
2 | What is your maternal grandmother's maiden name? |
3 | What is the name of your favourite childhood friend? |
4 | What was the make of your first car? |
5 | In what city or town did your mother and father meet? |
Error Responses
- 400 Bad Request: Invalid or missing
card_idparameter - 401 Unauthorized: Invalid or missing authentication token
- 403 Forbidden: 3DS feature not enabled for this account
- 404 Not Found: Card does not exist or is not enrolled for 3DS
Code Examples
cURL
curl -X GET \
'https://gateway.ahrvo.network/card/issuance/api/issuing/3ds/v2/detail?card_id=card59202507231957437131' \
-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/3ds/v2/detail"
headers = {
"Accept": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY"
}
params = {
"card_id": "card59202507231957437131"
}
response = requests.get(url, headers=headers, params=params)
print(response.json())
# Check if card is enrolled
if response.status_code == 200:
data = response.json()
print(f"Card is enrolled for 3DS")
print(f"Cardholder: {data['data']['first_name']} {data['data']['last_name']}")
print(f"Email: {data['data']['email']}")
print(f"Mobile: {data['data']['call_prefix']}{data['data']['mobile']}")
elif response.status_code == 404:
print("Card is not enrolled for 3DS")
JavaScript (Node.js)
const axios = require('axios');
const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/3ds/v2/detail';
const headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY'
};
const params = {
card_id: 'card59202507231957437131'
};
axios.get(url, { headers, params })
.then(response => {
console.log(response.data);
const data = response.data;
console.log('Card is enrolled for 3DS');
console.log(`Cardholder: ${data.data.first_name} ${data.data.last_name}`);
console.log(`Email: ${data.data.email}`);
console.log(`Mobile: ${data.data.call_prefix}${data.data.mobile}`);
})
.catch(error => {
if (error.response && error.response.status === 404) {
console.log('Card is not enrolled for 3DS');
} else {
console.error(error.response.data);
}
});
Usage Notes
- Enrollment Verification: Use this endpoint to check if a card is enrolled for 3DS before processing transactions
- Contact Verification: Verify the OTP delivery channels (email and mobile) are correct
- Cardholder Lookup: Retrieve cardholder information associated with a specific card
- Security Sensitive: The response includes security answers in plain text - handle with appropriate security measures
- Single Card Query: This endpoint is designed for querying one card at a time
Common Use Cases
Check Enrollment Status
Before processing a 3DS transaction, verify the card is enrolled:
async function isCardEnrolledFor3DS(cardId) {
try {
const response = await queryEnrollmentDetails(cardId);
return response.status === 200;
} catch (error) {
if (error.response && error.response.status === 404) {
return false;
}
throw error;
}
}
if (await isCardEnrolledFor3DS(cardId)) {
// Proceed with 3DS transaction
} else {
// Enroll card first
}
Verify Cardholder Contact Information
Ensure the contact information is up-to-date before a transaction:
def verify_contact_info(card_id):
response = query_enrollment_details(card_id)
data = response['data']
# Validate email format
if not is_valid_email(data['email']):
print(f"Warning: Invalid email format for card {card_id}")
# Validate mobile number
if not is_valid_mobile(data['call_prefix'], data['mobile']):
print(f"Warning: Invalid mobile number for card {card_id}")
return data
Display Cardholder Information to Customer
Show the cardholder which contact will receive the OTP:
async function showOTPDeliveryInfo(cardId) {
const response = await queryEnrollmentDetails(cardId);
const cardholder = response.data.data;
const maskedEmail = maskEmail(cardholder.email);
const maskedMobile = maskMobile(cardholder.mobile);
console.log(`OTP will be sent to:`);
console.log(`Email: ${maskedEmail}`);
console.log(`Mobile: ${cardholder.call_prefix}${maskedMobile}`);
}
Audit Card Enrollments
Check enrollment details for compliance or auditing:
def audit_card_enrollments(card_ids):
enrolled_cards = []
not_enrolled_cards = []
for card_id in card_ids:
try:
response = query_enrollment_details(card_id)
enrolled_cards.append({
'card_id': card_id,
'cardholder_id': response['data']['cardholder_id'],
'email': response['data']['email']
})
except HTTPError as e:
if e.response.status_code == 404:
not_enrolled_cards.append(card_id)
return enrolled_cards, not_enrolled_cards
Customer Support Workflow
Retrieve enrollment information for support tickets:
async function handleSupportTicket(cardId) {
try {
const enrollment = await queryEnrollmentDetails(cardId);
const data = enrollment.data.data;
return {
status: 'enrolled',
cardholder: `${data.first_name} ${data.last_name}`,
email: data.email,
mobile: `${data.call_prefix}${data.mobile}`,
cardholderId: data.cardholder_id
};
} catch (error) {
if (error.response && error.response.status === 404) {
return {
status: 'not_enrolled',
message: 'Card is not enrolled for 3DS. Please enroll first.'
};
}
throw error;
}
}
Best Practices
- Cache Wisely: Cache enrollment data temporarily but refresh before critical operations
- Error Handling: Distinguish between 404 (not enrolled) and other errors
- Privacy Protection: Mask sensitive information when displaying to users or in logs
- Regular Verification: Periodically verify enrollment status for active cards
- Security: Never log or display security answers in plain text
- Validation: Validate contact information is current before important transactions
Integration Workflow
Complete 3DS Transaction Flow
- Check Enrollment: Use this endpoint to verify card is enrolled
- Display OTP Info: Show customer where OTP will be sent (masked)
- Initiate Transaction: Process the 3DS transaction
- OTP Delivery: System sends OTP to enrolled email/mobile
- OTP Verification: Customer enters OTP to complete transaction
Enrollment Update Flow
- Query Current Details: Get current enrollment information
- Compare with New Data: Check if updates are needed
- Update if Necessary: Update cardholder information if changed
- Re-enroll: If needed, unenroll and re-enroll with updated information
- Verify: Query again to confirm updates
Related Endpoints
- Create Cardholder 3DS Contact - Create cardholder profiles
- Enroll Card for 3DS - Enroll a card for 3DS authentication
- Query 3DS Contact Details - Query cardholder information by cardholder_id or budget_id
- Unenroll Card from 3DS - Remove 3DS enrollment from a card
- Update Cardholder Contact - Update cardholder contact information
Troubleshooting
Card Not Found (404)
- Cause: Card doesn't exist or is not enrolled for 3DS
- Solution:
- Verify the
card_idis correct - Check if the card exists in your system
- Enroll the card first if needed
- Verify the
Invalid card_id Format (400)
- Cause: Malformed or missing
card_idparameter - Solution: Ensure
card_idis provided as a query parameter with the correct format
Forbidden Access (403)
- Cause: 3DS feature not enabled for your account
- Solution: Contact your account manager to enable this feature
Missing Contact Information
- Cause: Incomplete cardholder data during creation
- Solution: Ensure all required fields were provided when creating the cardholder
Security Considerations
- Sensitive Data: The response includes full cardholder details and security answers
- Access Control: Implement strict access controls for this endpoint
- Audit Logging: Log all queries to this endpoint for security audit trails
- Data Minimization: Only query when necessary, don't store responses unnecessarily
- Encryption: Use encrypted connections (HTTPS) for all API calls
- Masking: Always mask sensitive information when displaying to users