Overview
The Holdings API manages your mutual fund portfolio by storing scheme codes and unit quantities. Holdings are persisted in a local JSON file and used by the Portfolio API for valuation calculations.
Get Holdings
Retrieves all stored mutual fund holdings
Example Request
curl http://localhost:8000/api/holdings
Response
Returns an array of holding objects:
AMFI scheme code identifying the mutual fund
Number of units held in this fund
Example Response
[
{
"scheme_code" : "120503" ,
"units" : 150.5
},
{
"scheme_code" : "119551" ,
"units" : 75.25
},
{
"scheme_code" : "118989" ,
"units" : 200.0
}
]
Empty Holdings
When no holdings are configured or file doesn’t exist:
Set Holdings
This endpoint replaces all existing holdings . It does not merge or append.
Replaces all holdings with the provided list
Request Body
Array of holding objects:
AMFI scheme code for the mutual fund
Number of units held (supports decimals)
Example Request
curl -X POST http://localhost:8000/api/holdings \
-H "Content-Type: application/json" \
-d '[
{
"scheme_code": "120503",
"units": 150.5
},
{
"scheme_code": "119551",
"units": 75.25
},
{
"scheme_code": "118989",
"units": 200.0
}
]'
Response
Returns "updated" when holdings are successfully saved
Data Storage
File Location
Holdings are stored in:
[
{
"scheme_code" : "120503" ,
"units" : 150.5
},
{
"scheme_code" : "119551" ,
"units" : 75.25
}
]
File Initialization
If holdings.json doesn’t exist, GET returns []
POST creates the file automatically
Invalid JSON in existing file returns []
Data Validation
Pydantic Model
The API uses this Pydantic model for validation:
class Holding ( BaseModel ):
scheme_code: str
units: float
Validation Rules
Must be a non-empty string
Must be a valid number (integer or decimal)
Invalid Request Examples
Missing required field:
[
{
"scheme_code" : "120503"
// Missing "units"
}
]
Response: 422 Unprocessable Entity
Invalid data type:
[
{
"scheme_code" : "120503" ,
"units" : "not-a-number"
}
]
Response: 422 Unprocessable Entity
Common Use Cases
Initial Setup
Add your first holdings:
curl -X POST http://localhost:8000/api/holdings \
-H "Content-Type: application/json" \
-d '[
{"scheme_code": "120503", "units": 100.0},
{"scheme_code": "119551", "units": 50.0}
]'
Add New Fund
Get current holdings
Add new fund to array
POST complete updated array
const current = await fetch ( 'http://localhost:8000/api/holdings' ). then ( r => r . json ());
current . push ({ scheme_code: "118989" , units: 75.5 });
await fetch ( 'http://localhost:8000/api/holdings' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( current )
});
Update Units
Get current holdings
Modify units for specific fund
POST updated array
const holdings = await fetch ( 'http://localhost:8000/api/holdings' ). then ( r => r . json ());
const fund = holdings . find ( h => h . scheme_code === "120503" );
if ( fund ) {
fund . units = 200.5 ; // Update units
}
await fetch ( 'http://localhost:8000/api/holdings' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( holdings )
});
Remove Fund
Get current holdings
Filter out unwanted fund
POST filtered array
let holdings = await fetch ( 'http://localhost:8000/api/holdings' ). then ( r => r . json ());
holdings = holdings . filter ( h => h . scheme_code !== "119551" );
await fetch ( 'http://localhost:8000/api/holdings' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ( holdings )
});
Clear All Holdings
curl -X POST http://localhost:8000/api/holdings \
-H "Content-Type: application/json" \
-d '[]'
Scheme Codes
What is a Scheme Code?
AMFI (Association of Mutual Funds in India) assigns unique codes to each mutual fund scheme:
120503 : Axis Bluechip Fund - Direct Plan - Growth
119551 : SBI Small Cap Fund - Direct Plan - Growth
118989 : HDFC Mid-Cap Opportunities Fund - Direct Plan - Growth
Finding Scheme Codes
Use MFApi to search:
# Search by fund name
curl "https://api.mfapi.in/mf/search?q=axis%20bluechip"
Example response:
[
{
"schemeCode" : "120503" ,
"schemeName" : "Axis Bluechip Fund - Direct Plan - Growth"
}
]
Integration with Portfolio API
Holdings are used by /api/portfolio to calculate values:
Store Holdings
POST holdings via /api/holdings
Calculate Portfolio
GET /api/portfolio reads holdings and fetches NAV data
Display Value
Portfolio response includes current value for each holding
Example Flow
// 1. Set holdings
await fetch ( 'http://localhost:8000/api/holdings' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ([
{ scheme_code: "120503" , units: 150.5 },
{ scheme_code: "119551" , units: 75.25 }
])
});
// 2. Get portfolio value
const portfolio = await fetch ( 'http://localhost:8000/api/portfolio' )
. then ( r => r . json ());
console . log ( `Total Value: ₹ ${ portfolio . total_value } ` );
// Output: Total Value: ₹16715.29
Data Persistence
File Operations
Load (GET):
if os.path.exists( HOLDINGS_FILE ):
with open ( HOLDINGS_FILE , "r" ) as f:
return json.load(f)
return []
Save (POST):
with open ( HOLDINGS_FILE , "w" ) as f:
json.dump(holdings, f)
Error Handling
File not found : Returns empty array
Invalid JSON : Returns empty array
Write failure : Raises exception (500 error)
No backup is created. Consider implementing versioning for production use.
Best Practices
Decimal Precision
Mutual fund units often have high precision:
{
"scheme_code" : "120503" ,
"units" : 150.523456 // Up to 6 decimal places
}
Always use string type for scheme codes:
// ✅ Correct
{ "scheme_code" : "120503" , "units" : 100 }
// ❌ Wrong (number type)
{ "scheme_code" : 120503 , "units" : 100 }
Validation Before POST
Validate holdings before saving:
function validateHolding ( holding ) {
return (
typeof holding . scheme_code === 'string' &&
holding . scheme_code . length > 0 &&
typeof holding . units === 'number' &&
holding . units >= 0
);
}
const holdings = [ ... ];
if ( holdings . every ( validateHolding )) {
// Safe to POST
}
Error Responses
Scenario Status Response Invalid JSON format 422 Validation error details Missing required field 422 Validation error details Wrong data type 422 Validation error details File write failure 500 Server error
Example Validation Error
{
"detail" : [
{
"loc" : [ "body" , 0 , "units" ],
"msg" : "field required" ,
"type" : "value_error.missing"
}
]
}
Next Steps
View Portfolio Calculate current value of your holdings
API Overview Learn about API architecture and response formats