Create Budget Account
Overview
A budget account is the funding source for cards issued by PingPong. Cards must be associated with a budget account before they can be used. Once a budget account is created, you can transfer funds into it to enable spending on the associated cards. This allows you to organize and control card spending by department, project, or any other business structure.
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/budget/v2/create
Staging (gateway.ahrvo.network)
POST https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/create
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 |
Content-Type | application/json | Yes | Request body content type |
Request Body
The request body should contain a JSON object with the following structure:
{
"budget_name": "Marketing Department Budget"
}
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
budget_name | string | Yes | The name of the budget account. Used for identification and organization purposes |
Naming Guidelines
- Descriptive: Use clear, descriptive names that indicate the purpose or department
- Unique: Each budget account should have a unique name
- Examples:
- "Marketing Department Budget"
- "Q1 2026 Operations"
- "Engineering Team - Project Alpha"
- "Travel Expenses Budget"
- "Office Supplies Fund"
Response
Success Response (200 OK)
{
"code": "SUCCESS",
"data": {
"budget_id": "ci202507232016182661"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
code | string | Status string indicating the result. "SUCCESS" refers to successful creation |
data | object | Response data object |
data.budget_id | string | A unique ID of the created budget account. Use this ID to associate cards and transfer funds |
Error Responses
- 400 Bad Request: Invalid or missing
budget_name - 401 Unauthorized: Invalid or missing authentication token
- 403 Forbidden: Card issuance feature not enabled for this account
- 409 Conflict: Budget account with this name already exists
Code Examples
cURL
curl -X POST \
'https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/create' \
-H 'Accept: application/json' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"budget_name": "Marketing Department Budget"
}'
Python
import requests
url = "https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/create"
headers = {
"Accept": "application/json",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"x-api-key": "YOUR_API_KEY",
"Content-Type": "application/json"
}
data = {
"budget_name": "Marketing Department Budget"
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result['code'] == 'SUCCESS':
budget_id = result['data']['budget_id']
print(f"Budget account created successfully!")
print(f"Budget ID: {budget_id}")
else:
print(f"Failed to create budget account: {result}")
JavaScript (Node.js)
const axios = require('axios');
const url = 'https://gateway.ahrvo.network/card/issuance/api/issuing/budget/v2/create';
const headers = {
'Accept': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'x-api-key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
};
const data = {
budget_name: 'Marketing Department Budget'
};
axios.post(url, data, { headers })
.then(response => {
const result = response.data;
if (result.code === 'SUCCESS') {
console.log('Budget account created successfully!');
console.log(`Budget ID: ${result.data.budget_id}`);
}
})
.catch(error => {
console.error('Failed to create budget account:', error.response.data);
});
Usage Notes
- First Step: Creating a budget account is typically the first step in the card issuance process
- Fund Transfer: After creation, transfer funds into the budget account to enable card spending
- Card Association: Cards must be associated with a budget account during card creation
- Unique Names: Budget names should be unique within your account
- Organization: Use descriptive names to organize budgets by department, project, or purpose
Common Use Cases
Department Budget Setup
Create budget accounts for different departments:
def setup_department_budgets(departments):
"""
Create budget accounts for multiple departments
"""
budget_ids = {}
for dept_name in departments:
try:
budget_name = f"{dept_name} Department Budget"
response = create_budget_account(budget_name)
if response['code'] == 'SUCCESS':
budget_ids[dept_name] = response['data']['budget_id']
print(f"✓ Created budget for {dept_name}: {budget_ids[dept_name]}")
else:
print(f"✗ Failed to create budget for {dept_name}")
except Exception as e:
print(f"✗ Error creating budget for {dept_name}: {e}")
return budget_ids
# Example usage
departments = ['Marketing', 'Engineering', 'Sales', 'Operations', 'HR']
budgets = setup_department_budgets(departments)
Project-Based Budget
Create budgets for specific projects with date ranges:
async function createProjectBudget(projectName, startDate, endDate) {
const budgetName = `${projectName} (${startDate} to ${endDate})`;
try {
const response = await createBudgetAccount(budgetName);
if (response.code === 'SUCCESS') {
const budgetId = response.data.budget_id;
// Store project metadata
await storeProjectMetadata({
budget_id: budgetId,
project_name: projectName,
start_date: startDate,
end_date: endDate,
created_at: new Date().toISOString()
});
console.log(`Project budget created: ${budgetId}`);
return budgetId;
}
} catch (error) {
console.error('Failed to create project budget:', error);
throw error;
}
}
// Example usage
const budgetId = await createProjectBudget('Website Redesign', '2026-03-01', '2026-06-30');
Quarterly Budget Allocation
Create budgets for quarterly financial planning:
def create_quarterly_budgets(year, departments):
"""
Create quarterly budget accounts for each department
"""
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
budgets = {}
for quarter in quarters:
budgets[quarter] = {}
for dept in departments:
budget_name = f"{dept} - {quarter} {year}"
try:
response = create_budget_account(budget_name)
if response['code'] == 'SUCCESS':
budgets[quarter][dept] = response['data']['budget_id']
print(f"Created: {budget_name}")
except Exception as e:
print(f"Failed to create {budget_name}: {e}")
return budgets
# Example usage
year = 2026
departments = ['Marketing', 'Sales', 'Operations']
quarterly_budgets = create_quarterly_budgets(year, departments)
Team and Sub-Team Budgets
Create hierarchical budget structure:
async function createTeamBudgetStructure(teamName, subTeams) {
const results = {
main_budget: null,
sub_budgets: {}
};
try {
// Create main team budget
const mainResponse = await createBudgetAccount(`${teamName} - Main Budget`);
if (mainResponse.code === 'SUCCESS') {
results.main_budget = mainResponse.data.budget_id;
console.log(`✓ Created main budget for ${teamName}`);
}
// Create sub-team budgets
for (const subTeam of subTeams) {
const subResponse = await createBudgetAccount(`${teamName} - ${subTeam}`);
if (subResponse.code === 'SUCCESS') {
results.sub_budgets[subTeam] = subResponse.data.budget_id;
console.log(`✓ Created sub-budget for ${subTeam}`);
}
}
return results;
} catch (error) {
console.error('Error creating team budget structure:', error);
throw error;
}
}
// Example usage
const structure = await createTeamBudgetStructure('Engineering', [
'Frontend Team',
'Backend Team',
'DevOps Team',
'QA Team'
]);
Event or Campaign Budget
Create temporary budgets for specific events:
def create_event_budget(event_name, event_date, initial_amount=None):
"""
Create a budget account for a specific event or campaign
"""
budget_name = f"{event_name} - {event_date}"
try:
# Create budget account
response = create_budget_account(budget_name)
if response['code'] == 'SUCCESS':
budget_id = response['data']['budget_id']
print(f"Event budget created: {budget_id}")
# Optionally fund the budget immediately
if initial_amount:
fund_response = transfer_to_budget(budget_id, initial_amount)
print(f"Funded with {initial_amount}")
return {
'budget_id': budget_id,
'event_name': event_name,
'event_date': event_date,
'initial_amount': initial_amount
}
except Exception as e:
print(f"Failed to create event budget: {e}")
raise
# Example usage
trade_show_budget = create_event_budget(
"Tech Conference 2026",
"2026-05-15",
initial_amount=50000.00
)
Complete Budget Setup Workflow
Full workflow from creation to card issuance:
async function completeCardIssuanceSetup(departmentName, initialFunding) {
console.log('=== Starting Card Issuance Setup ===');
try {
// Step 1: Create budget account
console.log('Step 1: Creating budget account...');
const budgetResponse = await createBudgetAccount(`${departmentName} Budget`);
const budgetId = budgetResponse.data.budget_id;
console.log(`✓ Budget created: ${budgetId}`);
// Step 2: Fund the budget
console.log('Step 2: Funding budget account...');
await transferToBudget(budgetId, initialFunding);
console.log(`✓ Budget funded with $${initialFunding}`);
// Step 3: Create cardholder (if using 3DS)
console.log('Step 3: Creating cardholder profile...');
const cardholderResponse = await createCardholder({
budget_id: budgetId,
first_name: 'John',
last_name: 'Doe',
email: 'john.doe@company.com',
// ... other required fields
});
const cardholderId = cardholderResponse.data.cardholder_id;
console.log(`✓ Cardholder created: ${cardholderId}`);
// Step 4: Issue card
console.log('Step 4: Issuing card...');
const cardResponse = await issueCard({
budget_id: budgetId,
card_type: 'virtual',
// ... other card parameters
});
const cardId = cardResponse.data.card_id;
console.log(`✓ Card issued: ${cardId}`);
// Step 5: Enroll card for 3DS (optional)
console.log('Step 5: Enrolling card for 3DS...');
await enrollCardFor3DS(cardId, cardholderId);
console.log(`✓ Card enrolled for 3DS`);
console.log('=== Setup Complete ===');
return {
budget_id: budgetId,
cardholder_id: cardholderId,
card_id: cardId
};
} catch (error) {
console.error('Setup failed:', error);
throw error;
}
}
// Example usage
const setup = await completeCardIssuanceSetup('Marketing', 100000.00);
Best Practices
- Descriptive Naming: Use clear, descriptive names that indicate purpose and ownership
- Consistent Naming: Establish a naming convention across your organization
- Documentation: Maintain documentation of budget purposes and owners
- Metadata Storage: Store additional metadata (owner, purpose, dates) in your own system
- Regular Review: Periodically review budget accounts and archive unused ones
- Access Control: Implement proper authorization before allowing budget creation
Budget Management Workflow
Standard Setup Process
- Create Budget: Use this endpoint to create the budget account
- Store Budget ID: Save the returned
budget_idsecurely - Fund Budget: Transfer initial funds to the budget account
- Issue Cards: Create cards and associate them with the budget
- Monitor Spending: Track transactions and balance
- Manage Funding: Add or withdraw funds as needed
Budget Lifecycle
class BudgetLifecycle:
def __init__(self, budget_name):
self.budget_name = budget_name
self.budget_id = None
self.status = 'not_created'
def create(self):
"""Create the budget account"""
response = create_budget_account(self.budget_name)
if response['code'] == 'SUCCESS':
self.budget_id = response['data']['budget_id']
self.status = 'created'
print(f"Budget created: {self.budget_id}")
return self.budget_id
def fund(self, amount):
"""Add funds to the budget"""
if not self.budget_id:
raise ValueError("Budget not created yet")
transfer_to_budget(self.budget_id, amount)
self.status = 'active'
print(f"Budget funded with {amount}")
def issue_card(self, card_params):
"""Issue a card associated with this budget"""
if self.status != 'active':
raise ValueError("Budget must be active to issue cards")
card_params['budget_id'] = self.budget_id
card = issue_card(card_params)
return card
def get_balance(self):
"""Check current budget balance"""
return query_budget_balance(self.budget_id)
def archive(self):
"""Archive the budget"""
self.status = 'archived'
print(f"Budget {self.budget_id} archived")
# Example usage
budget = BudgetLifecycle("Q1 2026 Marketing")
budget.create()
budget.fund(50000.00)
card = budget.issue_card({'card_type': 'virtual'})
balance = budget.get_balance()
Related Endpoints
- Query Budget Details - Retrieve budget account information
- Query Budget Balance - Check available balance
- Transfer to Budget - Add funds to the budget account
- Withdraw from Budget - Remove funds from the budget account
- List Budget Accounts - Retrieve all budget accounts
- Issue Card - Create a card associated with a budget account
Troubleshooting
Budget Name Already Exists (409)
- Cause: A budget account with this name already exists
- Solution:
- Use a different, unique name
- Add distinguishing information (dates, IDs, etc.)
- Query existing budgets to check for duplicates
Invalid Budget Name (400)
- Cause: Budget name is empty, too long, or contains invalid characters
- Solution:
- Ensure the name is not empty
- Keep the name length reasonable (typically under 100 characters)
- Avoid special characters that might cause issues
Forbidden Access (403)
- Cause: Card issuance feature not enabled for your account
- Solution: Contact your account manager to enable card issuance
Next Steps After Creation
After creating a budget account:
- Save the budget_id - You'll need this for all subsequent operations
- Fund the budget - Transfer money into the account
- Issue cards - Create cards and associate them with this budget
- Monitor usage - Track spending and balance
Security Considerations
- Access Control: Implement proper authorization for budget creation
- Audit Logging: Log all budget account creation for compliance
- Naming Conventions: Use clear naming to prevent confusion
- Budget Ownership: Assign clear ownership and responsibility
- Regular Review: Periodically audit all budget accounts