Introduction
Welcome to the Savvy API! You can use our API to access Savvy API endpoints, which helps you create any mutual funds usecase you like. Savvy is your one stop shop, no signups for any other external services are required.
We have language bindings in Shell only for now. We don't have readymade clients as of now, but they'll be coming soon! You can view shell (curl) code examples in the dark area to the right.
Authentication
To authorize, you must pass a Base64 encoded combination of your access key and secret key. Use this code:
# With shell, you can just pass the correct header with each request
# encoded_key = Base64.encode("ACCESS_KEY:SECRET_KEY")
curl "api_endpoint_here" \
-H "Authorization: encoded_key"
Make sure to replace
encoded_key
with your own combination.
Savvy uses API keys to allow access to the API. You can register a new Savvy API key combination at our developer portal or send us an email at hello@savvyapp.in.
Savvy expects for the API key combination to be included in all API requests to the server in a header as follows:
encoded_key = Base64.encode(ACCESS_KEY:SECRET_KEY)
Authorization: encoded_key
Onboardings
Most of our APIs require an onboarding to be done before communicating with them. An onboarding is essentially a KYC (Know Your Customer) workflow which authorizes a person to conduct a mutual fund transaction. The workflow is the following:
Onboarding object
Parameter | Description |
---|---|
uuid | String Unique identifier of the onboarding object |
pan_number | String Customer PAN number. Note that the pan number is overwritten when parsed from the pan card. |
date_of_birth | String Format DD/MM/YYYY. Note that the dob is overwritten when parsed from the pan card. |
name | String Customer's full name. |
String Customer's email address. |
|
phone_number | String Customer's phone number with +91 prefix. |
kyc_status | One of: ["success", "failure", "pending"] Result of KYC verification post submission |
pan_card_image_url | URL String The pan card image submitted |
fathers_name | String Father's name from the pan card |
address_proof_image_url | URL String The address proof image submittted |
address_proof_type | One of: ["aadhaar", "voter_id", "passport", "license"] |
address | String Customer's street address. |
city | String Customer's city. |
pincode | String Customer's pincode. |
signature_image_url | URL String The signature image submitted |
selfie_image_url | URL String The selfie image submitted |
cancelled_cheque_url | URL String The cancelled cheque image submitted |
video_url | URL String The selfie video submitted |
annual_income | String Annual income code (refer to enum list) |
gender | String Gender code (refer to enum list) |
occupation | String Occupation code (refer to enum list) |
marital_status | String Marital status code (refer to enum list) |
Create onboarding
// body
{ "onboarding":
{
"pan_number": "ABCDE1234C",
"date_of_birth": "30/01/1990"
}
}
curl "http://surface.thesavvyapp.in/onboardings" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the onboarding JSON object
HTTP Request
POST http://surface.thesavvyapp.in/onboardings
Parameters
Parameter | Required | Description |
---|---|---|
pan_number | true | String Customer PAN number |
date_of_birth | true | Date Format DD/MM/YYYY |
Create onboarding bank account
// body
{ "onboarding":
{
"account_number": "0012345678901",
"ifsc_code": "HDFC0000873"
}
}
curl "http://surface.thesavvyapp.in/onboardings/<UUID>/bank_account" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the onboarding JSON object
HTTP Request
POST http://surface.thesavvyapp.in/onboardings/<UUID>/bank_account
JSON Parameters
Parameter | Required | Description |
---|---|---|
account_number | true | String A Valid bank account number |
ifsc_code | true | String A valid IFSC code |
Start Full KYC
// body
{ "onboarding":
{
"email": "batman@gmail.com",
"name": "Bruce Wayne",
"phone_number": "+919009012345"
}
}
curl "http://surface.thesavvyapp.in/onboardings/<UUID>/full_kyc" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the onboarding JSON object
This endpoint prepares the onboarding object for a full KYC
HTTP Request
POST http://surface.thesavvyapp.in/onboardings/<UUID>/full_kyc
JSON Parameters
Parameter | Description |
---|---|
name | String Customer's name |
String Customer's email |
|
phone_number | String Customer's phone number |
AMCs
This API gives you a list of supported AMCs by the Savvy API. This list remains relatively static, but we are constantly adding AMCs, so we recommend having some mechanism of fetching this list every so often. A monthly update might be ideal, but this is up to you.
AMC object
Parameter | Description |
---|---|
name | String Name of the AMC. |
code | String Operational code of the AMC. This code must be submitted in API requests, not the name. |
Get all AMCs
curl "http://surface.thesavvyapp.in/amcs" \
-X GET \
-H "Authorization: encoded_key"
The above command returns an array of AMC JSON objects.
HTTP Request
GET http://surface.thesavvyapp.in/amcs
Funds
This API gives you lists of supported mutual funds, by AMC. There is also support for NFOs, along with their timelines. Please note that NFOs are updated 1-2 days before the launch date.
Fund object
Parameter | Description |
---|---|
name | String Name of the fund. |
active | Boolean Whether the fund is currently accepting purchases from customers. |
nav | Decimal Current value of a unit of this fund. |
code | String Global unique identifier of this fund. This code must be submitted in API requests, not the name. |
Get all funds
curl "http://surface.thesavvyapp.in/funds?amc_code=code" \
-X GET \
-H "Authorization: encoded_key"
The above command returns an array of Fund JSON objects.
HTTP Request
GET http://surface.thesavvyapp.in/funds
URL Parameters
Parameter | Required | Description |
---|---|---|
amc_code | true | String Code the AMC from the AMC list API. |
Accounts
For most usecases, the accounts API is a pull-only API. Accounts are created asynchronously; when a purchase transaction is successful, a new account number (Folio number in the MF world) is allocated. You should be listening to webhooks to listen for account creations.
Account object
Parameter | Description |
---|---|
uuid | String Unique identifier of the account. |
amc_code | String Code of the AMC which this account is of. |
amc_name | String Name of the AMC which this account is of. |
amount_deposited | Integer Original amount deposited. |
amount_withdrawn | Decimal Amount withdrawn. |
account_value | Map Fund code => Current investment amount mapping. |
units | Map Fund code => Units mapping. |
holding_mode | Enum: ["SI"] Only Single mode is supported as of now. |
Show account
curl "http://surface.thesavvyapp.in/accounts/<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns a account JSON object.
HTTP Request
GET http://surface.thesavvyapp.in/accounts/<UUID>
Deposits
The deposits API describes how to create a mutual fund purchase transaction. This API can only be accessed post the onboarding flow. The workflow for creating and completing a purchase is:
Deposit object
Parameter | Description |
---|---|
uuid | String Unique identifier of the deposit. |
account_uuid | String Account which the deposit is part of. |
fund_code | String Code of the fund invested in. |
fund_name | String Name of the fund invested in. |
amount | Integer Original amount of the investment. |
current_amount | Decimal Current value of the investment. |
units | Decimal Units allocated for the investment. |
status | Enum: created, payment_made, submitted_to_rta, completed, error Status of the investment. |
status_description | String Reason in case of failure / rejections. |
reinvest_mode | Enum: payout: 'N', reinvestment: 'Y', growth: 'Z', bonus: 'B' What should happen with any dividend that is paid out. |
payment_link | String Only applicable for create API URL to which to take the user for payment checkout. |
partner_transaction_id | String Your ID associated with the transaction. |
user_completed_payment_at | Datetime Time at which payment was completed by the user. |
transferred_to_amc_at | Datetime Time at which the payment was transferred to the AMC. |
created_at | Datetime Time at which the deposit was created. |
sip_uuid | String Identifier of the SIP that the deposit is part of. |
stp_uuid | String Identifier of the STP that the deposit is part of |
Get deposits
curl "http://surface.thesavvyapp.in/deposits?account_uuid=<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns an array of deposit JSON objects.
HTTP Request
GET http://surface.thesavvyapp.in/deposits?account_uuid=<UUID>
URL Parameters
Parameter | Required | Description |
---|---|---|
account_uuid | true | String All deposits associated with a account |
Show deposit
curl "http://surface.thesavvyapp.in/deposits/<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns a deposit JSON object.
HTTP Request
GET http://surface.thesavvyapp.in/deposits/<UUID>
Create deposit
// body
{ "deposit":
{
"amount": "1000",
"fund_code": "1234",
"account_uuid": "aaaaa-bbbb-cccc-dddd",
"redirect_url": "https://example.com/payment_redirect"
}
}
curl "http://surface.thesavvyapp.in/deposits" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the deposit JSON object
HTTP Request
POST http://surface.thesavvyapp.in/deposits
Parameters
Parameter | Required | Description |
---|---|---|
amount | true | Integer Amount to be invested |
fund_code | true | Date Code of the fund to be invested in |
redirect_url | true | String Where to direct the customer after payment. A field called status (as a query param) in the redirect URL will be available to indicate success or failure. |
account_uuid | false | String If the deposit has to be created in an existing account. |
partner_transaction_id | false | String Your custom ID to identify this transaction. |
Withdrawals
The withdrawals API describes how to create a mutual fund redemption transaction. This API can only be accessed post the onboarding flow. The workflow for creating and completing a redemption is:
Withdrawal object
Parameter | Description |
---|---|
uuid | String Unique identifier of the withdrawal. |
account_uuid | String Account which the withdrawal is part of. |
fund_code | String Code of the fund invested in. |
fund_name | String Name of the fund invested in. |
amount | Integer Amount to be withdrawn. |
units | Decimal Units withdrawn for the transaction. |
status | Enum: created, otp_complete, submitted_to_rta, completed, error Status of the withdrawal. |
status_description | String Reason in case of failure / rejections. |
partner_transaction_id | String Your ID associated with the transaction. |
created_at | Datetime Time at which the withdrawal was created. |
swp_uuid | String Identifier of the SIP that the withdrawal is part of. |
stp_uuid | String Identifier of the STP that the withdrawal is part of |
Get withdrawals
curl "http://surface.thesavvyapp.in/withdrawals?account_uuid=<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns an array of withdrawal JSON objects.
HTTP Request
GET http://surface.thesavvyapp.in/withdrawals?account_uuid=<UUID>
URL Parameters
Parameter | Required | Description |
---|---|---|
account_uuid | true | String All withdrawals associated with a account |
Show withdrawal
curl "http://surface.thesavvyapp.in/withdrawals/<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns a withdrawal JSON object.
HTTP Request
GET http://surface.thesavvyapp.in/withdrawals/<UUID>
Create withdrawal
// body
{ "withdrawal":
{
"amount": "1000",
"fund_code": "1234",
"account_uuid": "aaaaa-bbbb-cccc-dddd",
"partner_transaction_id": "xyv-abc"
}
}
curl "http://surface.thesavvyapp.in/withdrawals" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the withdrawal JSON object
HTTP Request
POST http://surface.thesavvyapp.in/withdrawals
On success, an OTP is sent on both the users' registered email and phone number. This OTP has to be verified by the user and sent to us on API.
Parameters
Parameter | Required | Description |
---|---|---|
amount | true | Decimal Amount to be invested |
fund_code | true | Date Code of the fund to be invested in |
account_uuid | true | String If the deposit has to be created in an existing account. |
partner_transaction_id | false | String Your custom ID to identify this transaction. |
Verify withdrawal OTP
// body
{ "withdrawal":
{
"otp": "123456"
}
}
curl "http://surface.thesavvyapp.in/withdrawals/<UUID>/verify_otp" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the withdrawal JSON object
HTTP Request
POST http://surface.thesavvyapp.in/withdrawals/<UUID>/verify_otp
On success, the status of the withdrawal will change to otp_complete
. The OTP verification will expire in 5 minutes, and the OTP can be resent in case of delivery failures after 30 seconds of first attempt.
Parameters
Parameter | Required | Description |
---|---|---|
otp | true | String The user inputted OTP |
Systematic Investment Plans
This API describes how to create a SIP transaction. This API can only be accessed post the onboarding flow. The workflow for creating and registering an SIP is:
SIP object
Parameter | Description |
---|---|
uuid | String Unique identifier of the withdrawal. |
account_uuid | String Account which the SIP is part of. |
fund_code | String Code of the fund invested in. |
fund_name | String Name of the fund invested in. |
start_date | Date Start date of the SIP. |
end_date | Date End date of the SIP. |
frequency | Enum: monthly, weekly, daily, ad-hoc Frequency of debits |
amount | Integer Amount to be withdrawn at each installment. |
payment_link | String Only applicable for create API URL to which to take the user for mandate checkout. |
redirect_url | String Where to direct the customer after payment. A field called status (as a query param) in the redirect URL will be available to indicate success or failure. |
active | Boolean Whether the SIP is actively debiting. |
partner_transaction_id | String Your ID associated with the transaction. |
created_at | Datetime Time at which the SIP was created. |
Get sips
curl "http://surface.thesavvyapp.in/sips?account_uuid=<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns an array of sip JSON objects.
HTTP Request
GET http://surface.thesavvyapp.in/sips?account_uuid=<UUID>
URL Parameters
Parameter | Required | Description |
---|---|---|
account_uuid | true | String All sips associated with a account |
Show sip
curl "http://surface.thesavvyapp.in/sips/<UUID>" \
-X GET \
-H "Authorization: encoded_key"
The above command returns a sip JSON object.
HTTP Request
GET http://surface.thesavvyapp.in/sips/<UUID>
Create sip
// body
{ "sip":
{
"amount": "1000",
"fund_code": "1234",
"account_uuid": "aaaaa-bbbb-cccc-dddd",
"partner_transaction_id": "xyv-abc",
"start_date": "30/01/2022",
"end_date": "30/12/2022",
"frequency": "monthly",
"redirect_url": "https://example.com/redirect"
}
}
curl "http://surface.thesavvyapp.in/sips" \
-X POST \
-H "Authorization: encoded_key" \
-d body
The above command returns the sip JSON object
HTTP Request
POST http://surface.thesavvyapp.in/sips
On success, a payment url is sent. The user must be redirected to this url to sign the e-nach mandate required for periodic auto-debits. If for some reason, the mandate fails to get signed, you can retry the mandate signing for a period of 24 hours, post which a new mandate must be created.
Parameters
Parameter | Required | Description |
---|---|---|
amount | true | Decimal Amount to be invested |
fund_code | true | Date Code of the fund to be invested in |
account_uuid | true | String If the deposit has to be created in an existing account. |
partner_transaction_id | false | String Your custom ID to identify this transaction. |
start_date | true | Date Start date of the SIP. |
end_date | true | Date End date of the SIP. |
frequency | true | Enum: monthly, weekly, daily, ad-hoc Frequency of debits |
redirect_url | true | URL String Where to direct the customer after payment. A field called status (as a query param) in the redirect URL will be available to indicate success or failure. |
Systematic Withdrawal Plans
This API describes how to create a SWP transaction. This API can only be accessed post the onboarding flow. The workflow for creating and registering an SWP is:
SWP Object
Coming Soon!
Systematic Transfer Plans
This API describes how to create a STP transaction, for periodic transfers from one fund to another in the same or different accounts. This API can only be accessed post the onboarding flow. The workflow for creating and registering an STP is:
STP Object
Coming soon!
Risk Profiling
To improve the user experience in terms of fund selection, we offer a risk profiling API that takes customer profile information + a couple of risk related questions as inputs to output a maximum of 4 funds. While designed by our in-house MF experts, this API is provided "as-is", without any guarantees of correctness.
Reports
We offer aggregated reports accross multiple categories for easy reconciliation and customer viewing.
Frontend SDKs
For non-distributors, we offer the ability to use readymade SDKs for offering mutual fund onboarding and transactions. This exposes no private data of the customer. Marketing and non-fintech usecases should use this.
We also offer SDKs for simplified purchase transactions. Instead of redirecting the user to another page for payments, the SDK will allow you to complete the transaction on your assets itself.
Webhooks
The webhooks API is an essential part of the Savvy API. There are several long running tasks and asynchronos activites that occur in the processing of onboardings and mutual fund transactions. For you to provide a good user experience, we offer webhooks that give you async updates about various activities you do via the Savvy API.
Webhook structure
Parameter | Description |
---|---|
event | String Unique identifier of the withdrawal. |
sent_at | Datetime Time at which the SIP was created. |
payload | JSON Data sent as part of webhook. |
signature | String SHA265 signature of the JSON payload. |
Events
Event | Description |
---|---|
deposit.created |
Sent when a deposit is created |
deposit.status.updated |
Sent when a deposit status is updated. Use this for tracking success / failure of deposit transactions. |
withdrawal.created |
Sent when a withdrawal is created |
withdrawal.status.updated |
Sent when a withdrawal status is updated. Use this for tracking success / failure of withdrawal transactions. |
Webhook authentication
To make sure that the webhook is coming from Savvy, we append a signature to all webhooks in the signature
parameter. The signature is a HMAC-SHA256 hash of the payload JSON string using your secret key:
HMAC('sha256', secret_key, payload)
Make sure to verify this signature before using the payload.
Enums
Annual Income Codes
Gender Codes
Occupation Codes
Marital Status Codes
Errors
The Savvy API uses the following error codes:
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- Your API key is wrong. |
403 | Forbidden -- The API requested is hidden for administrators only. |
404 | Not Found -- The specified API / object could not be found. |
405 | Method Not Allowed -- You tried to access an API with an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
410 | Gone -- The API requested has been removed from our servers. |
418 | I'm a teapot. |
429 | Too Many Requests -- You're making too many requests! Slow down! |
500 | Internal Server Error -- We had a problem with our server. Try again later. |
503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. |