B2B API v3.0
Last updated: Jun 9, 2023
Introduction
Musaffa’s API is one of the most comprehensive Shariah-Compliant Stock Screener organized around REST. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.
All requests are made to endpoints beginning: https://platform.musaffa.com/api
.
Developer Agreement
By using Musaffa’s API, you agree to our Terms of Use.
Rate Limits
There are limitations for the API calls.
Depending on the B2B subscription plan it can be up to 100 000 API calls per month and 1 API call per second.
If your limit is exceeded, you will receive a response with status code 429.
Authentication and API
Musaffa will provide a secret key and a client ID to every B2B client.
clientId=< should be shared separately for each client >
UTC is used for time zone “UTC+5”
DateTimeFormatter = "yyyyMMddHHmmss"
Using current time, the secret key, the client ID and a body of the message a token is generated using the following code:
The token is placed in the header of the message for both sides of the communication and used for validating messages.
Example Token Generation
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
class ProfileApplicationTests {
private String secretKey = "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ";
private String clientId = "EjXfR2rt7xADG";
private String generatedToken(String time, String jsonInString) {
return Base64.getEncoder().encodeToString(DigestUtils.sha512(secretKey + time + jsonInString));
}
}
String secretKey = "gRUkXp2s5v8yBEyGbPeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
String jsonInStringBody = "{"stock":"AAPL"}"
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
String token = Base64.getEncoder().encodeToString(DigestUtils.sha512(secretKey + time + jsonInStringBody));
List of Stocks
curl --location --request POST
'https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/list'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
--data-raw '{
"country":"US",
"sector":"Information Technology"
}'
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
RestTemplate restTemplate = new RestTemplate();
Instant nowUtc = Instant.now();
ZoneId zoneId = ZoneId.of("UTC+5");
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("country", "ID");
requestBody.put("sector", "Information Technology");
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "";
try {
jsonInString = mapper.writeValueAsString(requestBody);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", generatedToken(time, jsonInString));
headers.set("time", time);
headers.set("clientId", clientId);
HttpEntity<String> http = new HttpEntity<>(jsonInString, headers);
ResponseEntity<Object> response = restTemplate.exchange("https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/list", HttpMethod.POST, http, Object.class);
System.out.println("List ticker RESULT : " + response.getBody());
import requests
import hashlib
import base64
from datetime import datetime
import pytz
client_id = "EjXfR2rt7xADG"
secret_key= "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
url = "https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/list"
country = "US"
sector = "Energy"
json_body = '{"country":"' + country + '","sector":"' + sector + '"}'
now = datetime.utcnow()
date_time_format = now.strftime("%Y%m%d%H%M%S")
token_pre_generate = secret_key + date_time_format + json_body
token_sha512 = hashlib.sha512(token_pre_generate.encode("utf8")).digest()
token_base64 = base64.b64encode(token_sha512)
headers = {
"token" : token_base64,
"clientId" : client_id,
"time" : date_time_format,
"Content-Type" : "application/json"
}
x = requests.post(url=url, data=json_body, headers=headers)
print(x.json())
Success Response
[
{
"stockName": "DCII.JK",
"companyName": "DCI Indonesia Tbk PT",
"status": "COMPLIANT",
"ranking": 5
},
{
"stockName": "DMMX.JK",
"companyName": "Digital Mediatama Maxima PT",
"status": "COMPLIANT",
"ranking": 4
},
{
"stockName": "MCAS.JK",
"companyName": "M Cash Integrasi Tbk PT",
"status": "COMPLIANT",
"ranking": 2
},
......
{
"stockName": "MKNT.JK",
"companyName": "Mitra Komunikasi Nusantara Tbk PT",
"status": "NON_COMPLIANT",
"ranking": 0
},
{
"stockName": "WGSH.JK",
"companyName": "Wira Global Solusi Tbk PT",
"status": "COMPLIANT",
"ranking": 1
}
]
Get Shariah-Compliant Screening Results for stocks. You can query by stock ticker.
List of Sectors:
Sample country codes:
Stocks request information
Category | Value |
---|---|
Http method | POST |
URL | https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/list |
Stocks request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Content-Type | "application/json" | Request content type |
Stocks request body in JSON format
Field | Value | Description |
---|---|---|
country | "US" | Country code |
sector | "Information Technology" | Sector |
Stocks response data structure (JSON array)
Field | Type | Description |
---|---|---|
stockName | String | Stock symbol |
companyName | String | Company name |
status | String | Shariah-compliance Status (Halal, Not Halal, Doubtful, Not Covered) |
ranking | Number | Compliance Rank (0-5) |
Stock Screening Report
curl --location --request POST
'https://platform.musaffa.com/b2b/api/v3/musaffa/stocks/report'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
--data-raw '{
"stock":"AAPL"
}'
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
RestTemplate restTemplate = new RestTemplate();
Instant nowUtc = Instant.now();
ZoneId zoneId = ZoneId.of("UTC+5");
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("stock", "AAPL");
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "";
try {
jsonInString = mapper.writeValueAsString(requestBody);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", generatedToken(time, jsonInString));
headers.set("time", time);
headers.set("clientId", clientId);
HttpEntity<String> requestHttpEntity = new HttpEntity<>(jsonInString, headers);
ResponseEntity<Object> response = restTemplate.exchange("https://platform.musaffa.com/b2b/api/v3/musaffa/stocks/report", HttpMethod.POST, requestHttpEntity, Object.class);
System.out.println("One ticker RESULT : " + response.getBody());
import requests
import hashlib
import base64
from datetime import datetime
import pytz
client_id = "EjXfR2rt7xADG"
secret_key= "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
url = "https://platform.musaffa.com/b2b/api/v3/musaffa/stocks/report"
stock = "AAPL"
json_body = '{"stock":"' + stock + '"}'
now = datetime.utcnow()
date_time_format = now.strftime("%Y%m%d%H%M%S")
token_pre_generate = secret_key + date_time_format + json_body
token_sha512 = hashlib.sha512(token_pre_generate.encode("utf8")).digest()
token_base64 = base64.b64encode(token_sha512)
headers = {
"token" : token_base64,
"clientId" : client_id,
"time" : date_time_format,
"Content-Type" : "application/json"
}
x = requests.post(url=url, data=json_body, headers=headers)
print(x.json())
Success Response
{
"companyName": "Apple Inc",
"symbol": "AAPL",
"lastUpdate": "2023-05-16T10:26:12.034710Z",
"shariahComplianceStatus": "HALAL",
"complianceRanking": 1,
"revenueBreakdown": {
"halalRatio": 95.88,
"notHalalRatio": 0.7354561,
"doubtfulRatio": 3.3891985,
"doubtfulRevenue": 3999999902.815818843788000000,
"halalRevenue": 113159493600.0000,
"notHalalRevenue": 868000009.01937480592000000,
"status": "Pass"
},
"interestBearingSecuritiesAndAssets": {
"amount": 165449999836.70999720513765376,
"ratio": 7.3997383,
"status": "Pass"
},
"interestBearingDebt": {
"amount": 111110000775.74250069871558656,
"ratio": 4.969386,
"status": "Pass"
},
"reportDate": "2022-12-31",
"reportSource": "",
"totalRevenue": 118022000000.00,
"trailing36monAvrCap": 2235889876992.00,
"totalAssets": 346747.00,
"accountsReceivable": 23752.00,
"reportedYear": 2023,
"reportedQuarter": "FIRST_QUARTER",
"mainCurrency": "USD",
"reportPeriod": 91,
"units": 1000000,
"revenueBreakdownDetail": {
"name": "SALES BREAKDOWN",
"items": [
{
"id": "1",
"name": "Sales",
"items": [
{
"id": "101",
"name": "iPhone",
"items": [],
"amount": "65775",
"comment": [],
"selector": "COMPLIANT",
"percentage": 55.73113487315924,
"amountInOnes": 65775000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "111",
"name": "Mac",
"items": [],
"amount": "7735",
"comment": [],
"selector": "COMPLIANT",
"percentage": 6.553862839131687,
"amountInOnes": 7735000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "121",
"name": "iPad",
"items": [],
"amount": "9396",
"comment": [],
"selector": "COMPLIANT",
"percentage": 7.961227567741608,
"amountInOnes": 9396000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "131",
"name": "Wearables, Home and Accessories",
"items": [],
"amount": "13482",
"comment": [],
"selector": "COMPLIANT",
"percentage": 11.423293962142651,
"amountInOnes": 13482000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"amount": 96388,
"comment": "",
"selector": "",
"percentage": 81.66951924217518,
"amountInOnes": 0,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "2",
"name": "Services",
"items": [
{
"id": "201",
"name": "Advertising",
"items": [],
"amount": "1900",
"comment": [
{
"body": "Deduced based on the data provided by Investor's Business Daily",
"files": [],
"source": ""
}
],
"selector": "QUESTIONABLE",
"percentage": 1.6098693463930454,
"openComment": false,
"amountInOnes": 1900000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "211",
"name": "Apple Music",
"items": [],
"amount": "2100",
"comment": [
{
"body": "Deduced based on the data provided by Business of Apps",
"files": []
}
],
"selector": "QUESTIONABLE",
"percentage": 1.7793292775923133,
"openComment": false,
"amountInOnes": 2100000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "221",
"name": "Other",
"items": [],
"amount": "16766",
"comment": [],
"selector": "COMPLIANT",
"percentage": 14.205826032434631,
"amountInOnes": 16766000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"amount": 20766,
"comment": "",
"selector": "",
"percentage": 17.59502465641999,
"amountInOnes": 0,
"itemsNotHalal": 0,
"itemsQuestionable": 4000
}
],
"amount": 117154,
"percentage": 99.26454389859518,
"halalAmount": 113154,
"amountInOnes": 117154000000,
"notHalalAmount": 0,
"halalPercentage": 95.87534527460981,
"halalAmountInOnes": 113154000000,
"notHalalPercentage": 0,
"questionableAmount": 4000,
"notHalalAmountInOnes": 0,
"questionablePercentage": 3.389198623985359,
"questionableAmountInOnes": 4000000000
},
"interestBearingSecuritiesAndAssetsDetail": {
"totalRetio": 7.399738319070711,
"totalAmount": 165450,
"longTermJson": {
"name": "Long-term",
"items": [
{
"id": "1",
"name": "Marketable securities\t",
"items": [],
"amount": "114095",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 5.102889957778016,
"amountInOnes": 114095000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"retio": 5.102889957778016,
"amount": 114095,
"amountInOnes": 114095000000,
"islamicAmount": 0,
"nonIslamicAmount": 114095,
"islamicPercentage": 0,
"islamicAmountInOnes": 0,
"nonIslamicPercentage": 68.9604110003022,
"nonIslamicAmountInOnes": 114095000000
},
"shortTermJson": {
"name": "Short-term",
"items": [
{
"id": "1",
"name": "Cash and cash equivalents\t",
"items": [],
"amount": "20535",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 0.9184262700641708,
"amountInOnes": 20535000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "2",
"name": "Marketable securities\t",
"items": [],
"amount": "30820",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 1.378422091228524,
"amountInOnes": 30820000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"retio": 2.296848361292695,
"amount": 51355,
"amountInOnes": 51355000000,
"islamicAmount": 0,
"nonIslamicAmount": 51355,
"islamicPercentage": 0,
"islamicAmountInOnes": 0,
"nonIslamicPercentage": 31.039588999697795,
"nonIslamicAmountInOnes": 51355000000
},
"totalNonIslamicAmount": 165450
},
"interestIncomeDetail": {
"name": "OTHER INCOME",
"items": [
{
"id": "21",
"name": "Interest Income",
"items": [
{
"id": "211",
"name": "Interest and dividend income\t",
"items": [],
"amount": "868",
"comment": "",
"selector": "NON_COMPLIANT",
"percentage": 0.7354561014048229,
"amountInOnes": 868000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"amount": 868,
"comment": "",
"showCalc": true,
"percentage": 0.7354561014048229,
"amountInOnes": 0,
"itemsNotHalal": 868,
"itemsQuestionable": 0
},
{
"id": "22",
"name": "Other Income",
"items": [],
"amount": 0,
"comment": "",
"percentage": 0,
"amountInOnes": 0,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"amount": 868,
"percentage": 0.7354561014048229,
"halalAmount": 0,
"amountInOnes": 868000000,
"notHalalAmount": 868,
"halalPercentage": 0,
"halalAmountInOnes": 0,
"notHalalPercentage": 0.7354561014048229,
"questionableAmount": 0,
"notHalalAmountInOnes": 868000000,
"questionablePercentage": 0,
"questionableAmountInOnes": 0
},
"interestBearingDebtDetail": {
"totalRetio": 4.96938606607402,
"totalAmount": 111110,
"longTermJson": {
"name": "Long-term",
"items": [
{
"id": "1",
"name": "Term debt",
"items": [],
"amount": "99627",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 4.4558097885406935,
"amountInOnes": 99627000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"retio": 4.4558097885406935,
"amount": 99627,
"amountInOnes": 99627000000,
"islamicAmount": 0,
"nonIslamicAmount": 99627,
"islamicPercentage": 0,
"islamicAmountInOnes": 0,
"nonIslamicPercentage": 89.66519665196653,
"nonIslamicAmountInOnes": 99627000000
},
"shortTermJson": {
"name": "Short-term",
"items": [
{
"id": "1",
"name": "Commercial paper\t",
"items": [],
"amount": "1743",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 0.0779555387738909,
"amountInOnes": 1743000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
},
{
"id": "2",
"name": "Term debt\t",
"items": [],
"amount": "9740",
"comment": "",
"selector": "NON_ISLAMIC",
"percentage": 0.43562073875943624,
"amountInOnes": 9740000000,
"itemsNotHalal": 0,
"itemsQuestionable": 0
}
],
"retio": 0.5135762775333272,
"amount": 11483,
"amountInOnes": 11483000000,
"islamicAmount": 0,
"nonIslamicAmount": 11483,
"islamicPercentage": 0,
"islamicAmountInOnes": 0,
"nonIslamicPercentage": 10.33480334803348,
"nonIslamicAmountInOnes": 11483000000
},
"totalNonIslamicAmount": 111110
}
}
Get Shariah-Compliant Screening Results for stocks. You can query by stock ticker.
Stock request information
Category | Value |
---|---|
Http method | POST |
URL | https://platform.musaffa.com/b2b/api/v3/musaffa/stocks/report |
Stock request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Content-Type | "application/json" | Request content type |
Stock request body in JSON format
Field | Value | Description |
---|---|---|
stock | "AAPL" | Stock symbol |
Stock response data structure (JSON)
Field | Type | Description |
---|---|---|
companyName | String | Company name |
symbol | String | Stock symbol |
lastUpdate | String | Last update date in ISO 8601 Date/Time Format (YYYY-MM-DD). |
shariahComplianceStatus | String | Shariah-compliance Status (Halal, Not Halal, Doubtful, Not Covered) |
complianceRanking | number | Compliance Rank (0-5) |
revenueBreakdown | Object | Revenue Breakdown JSON Object { "halalRatio": "number", // percentage value from 0 to 100 "notHalalRatio": "number", // percentage value from 0 to 100 "doubtfulRatio": "number", // percentage value from 0 to 100 "doubtfulRevenue": "number", // amount in units "halalRevenue": "number", // amount in units "notHalalRevenue": "number", // amount in units "status": "string", // Pass or Fail } Combined revenue from DOUBTFUL and NOT HALAL sources must be less than 5% of total revenue to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
interestBearingSecuritiesAndAssets | Object | Interest-bearing Securities and Assets Interest-Bearing Securities and Assets should be less than 30% of Trailing 36-month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology.Thus,
|
interestBearingDebt | Object | Interest-bearing Debt Interest-Bearing Debt should be less than 30% of Trailing 36-Month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
reportDate | Date | Reporting dates of the company in ISO 8601 Date/Time Format (YYYY-MM-DD). |
reportSource | string | URL link to the company report. |
totalRevenue | number | Total Revenue of the company |
trailing36monAvrCap | number | Trailing 36-month Average Market Capitalization of the company. |
totalAssets | number | Amount of Total Assets (in units) |
accountsReceivable | number | Amount of Accounts Receivable (in units) |
reportedYear | number | Reporting year |
reportedQuarter | string | Reporting period (FIRST_QUARTER, SECOND_QUARTER, THIRD_QUARTER, ANNUAL) |
mainCurrency | string | Reporting currency. Currency used in company filings |
units | number | Number expression (e.g. in million) |
revenueBreakdownDetail | Object | Revenue breakdown JSON object that contains line items with compliance type, ration, amount in once and comments. { "amount": "number", "amountInOnes": "number", "questionablePercentage": "number", "halalPercentage": "number", "questionableAmountInOnes": "number", "notHalalAmount": "number", "notHalalAmountInOnes": "number", "halalAmountInOnes": "number", "percentage": "number", "name": "string", "notHalalPercentage": "number", "halalAmount": "number", "items": "array", "questionableAmount": "number" } |
interestBearingSecuritiesAndAssetsDetail | Object | Interest-bearing securities and assets JSON object that contains line items with compliance type, ration, amount in once and comments. { "totalAmount":"number", "totalRetio":"number", "longTermJson":"object", "totalNonIslamicAmount":"number" "shortTermJson":"object" } |
interestIncomeDetail | Object | Interest Income JSON object that contains line items with compliance type, ration, amount in once and comments. { "amount":"number", "amountInOnes":"number", "questionablePercentage":"number", "halalPercentage":"number", "questionableAmountInOnes":"number", "notHalalAmount":"number", "notHalalAmountInOnes":"number", "halalAmountInOnes":"number", "percentage":"number", "name":"string", "notHalalPercentage":"number", "halalAmount":"number", "items":"array", "questionableAmount":"number" } |
interestBearingDebtDetail | Object | Interest-bearing debt JSON object that contains line items with compliance type, ration, amount in once and comments. { "totalAmount":"number", "totalRetio":"number", "longTermJson":"object", "totalNonIslamicAmount":"number" "shortTermJson":"object" } |
List of Stock Screening Reports
curl --location --request POST
'https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/screening-list'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
--data-raw '{
"stocks":["AAPL","NFLX","TSLA"]
}'
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
RestTemplate restTemplate = new RestTemplate();
Instant nowUtc = Instant.now();
ZoneId zoneId = ZoneId.of("UTC+5");
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "";
try {
jsonInString = mapper.writeValueAsString({"stocks":["AAPL","NFLX","TSLA"]});
} catch (JsonProcessingException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", generatedToken(time, jsonInString));
headers.set("time", time);
headers.set("clientId", clientId);
HttpEntity<String> requestHttpEntity = new HttpEntity<>(jsonInString, headers);
ResponseEntity<Object> response = restTemplate.exchange("https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/screening-list", HttpMethod.POST, requestHttpEntity, Object.class);
System.out.println("One ticker RESULT : " + response.getBody());
import requests
import hashlib
import base64
from datetime import datetime
import pytz
client_id = "EjXfR2rt7xADG"
secret_key= "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
url = "https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/screening-list"
json_body = '{"stocks":["AAPL","NFLX","TSLA"]}'
now = datetime.utcnow()
date_time_format = now.strftime("%Y%m%d%H%M%S")
token_pre_generate = secret_key + date_time_format + json_body
token_sha512 = hashlib.sha512(token_pre_generate.encode("utf8")).digest()
token_base64 = base64.b64encode(token_sha512)
headers = {
"token" : token_base64,
"clientId" : client_id,
"time" : date_time_format,
"Content-Type" : "application/json"
}
x = requests.post(url=url, data=json_body, headers=headers)
print(x.json())
Success Response
[
{
"companyName": "Apple Inc",
"stockName": "AAPL",
"shariahComplianceStatus": "COMPLIANT",
"complianceRanking": 1,
"revenueBreakdown": {
"notHalal": 0.27,
"halal": 95.91,
"doubtful": 3.82,
"status": "Pass"
},
"interestBearingSecuritiesAndAssets": {
"interestRatio": 2.69,
"status": "Pass"
},
"interestBearingDebt": {
"debtRatio": 5.9,
"status": "Pass"
},
"source": "March 26, 2022"
},
{
"companyName": "Netflix Inc",
"stockName": "NFLX",
"shariahComplianceStatus": "QUESTIONABLE",
"complianceRanking": 0,
"revenueBreakdown": {
"notHalal": 2.49,
"halal": 0.0,
"doubtful": 97.51,
"status": "Fail"
},
"interestBearingSecuritiesAndAssets": {
"interestRatio": 3.1,
"status": "Pass"
},
"interestBearingDebt": {
"debtRatio": 7.49,
"status": "Pass"
},
"source": "March 31, 2022"
},
{
"companyName": "Tesla Inc",
"stockName": "TSLA",
"shariahComplianceStatus": "COMPLIANT",
"complianceRanking": 5,
"revenueBreakdown": {
"notHalal": 0.15,
"halal": 99.85,
"doubtful": 0.0,
"status": "Pass"
},
"interestBearingSecuritiesAndAssets": {
"interestRatio": 3.54,
"status": "Pass"
},
"interestBearingDebt": {
"debtRatio": 0.95,
"status": "Pass"
},
"source": "March 31, 2022"
}
]
Get Shariah-Compliant Screening Results for stocks. You can query by stock tickers. Maximum permissible limit of tickers per request is 100.
Stock bulk request information
Category | Value |
---|---|
Http method | POST |
URL | https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/screening-list |
Stock bulk request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Content-Type | "application/json" | Request content type |
Stock bulk request body in JSON format
Field | Value | Description |
---|---|---|
stocks | ["AAPL","NFLX","TSLA, . . . . "] | Stock symbol list (Maximum 100 symbols per request) |
Stock bulk response data structure (JSON array)
Field | Type | Description |
---|---|---|
companyName | String | Company name |
stockName | String | Stock symbol |
shariahComplianceStatus | String | Shariah-compliance Status (Halal, Not Halal, Doubtful, Not Covered) |
complianceRanking | number | Compliance Rank (0-5) |
revenueBreakdown { notHalal, doubtful, halal, status } |
Object notHalal=>Float, doubtful=>Float, halal=>Float, status=>String |
Revenue Breakdown Combined revenue from ‘Doubtful’ and ‘Not-Halal’ sources must be less than 5% of total revenue to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
interestBearingSecuritiesAndAssets { interestRatio, status } |
Object interestRatio=>Float, status=>String |
Interest-bearing Securities and Assets Interest-Bearing Securities and Assets should be less than 30% of Trailing 36-month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology.Thus,
|
interestBearingDebt { debtRatio, status } |
Object debtRatio=>Float, status=>String |
Interest-bearing Debt Interest-Bearing Debt should be less than 30% of Trailing 36-Month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
source | String | Reporting dates of the company |
List of covered stocks
Coming soon
ETF Screening Reports
Coming soon
List of ETFs
Coming soon
Dividend Purification
curl --location --request POST
'https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/dividends/pure'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
--data-raw '{
"stock":"AAPL"
}'
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
RestTemplate restTemplate = new RestTemplate();
Instant nowUtc = Instant.now();
ZoneId zoneId = ZoneId.of("UTC+5");
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("stock", "AAPL");
ObjectMapper mapper = new ObjectMapper();
String jsonInString = "";
try {
jsonInString = mapper.writeValueAsString(requestBody);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("token", generatedToken(time, jsonInString));
headers.set("time", time);
headers.set("clientId", clientId);
HttpEntity<String> requestHttpEntity = new HttpEntity<>(jsonInString, headers);
ResponseEntity<Object> response = restTemplate.exchange("https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/dividends/pure", HttpMethod.POST, requestHttpEntity, Object.class);
System.out.println("One ticker RESULT : " + response.getBody());
import requests
import hashlib
import base64
from datetime import datetime
import pytz
client_id = "EjXfR2rt7xADG"
secret_key= "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
url = "https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/dividends/pure"
stock = "AAPL"
json_body = '{"stock":"' + stock + '"}'
now = datetime.utcnow()
date_time_format = now.strftime("%Y%m%d%H%M%S")
token_pre_generate = secret_key + date_time_format + json_body
token_sha512 = hashlib.sha512(token_pre_generate.encode("utf8")).digest()
token_base64 = base64.b64encode(token_sha512)
headers = {
"token" : token_base64,
"clientId" : client_id,
"time" : date_time_format,
"Content-Type" : "application/json"
}
x = requests.post(url=url, data=json_body, headers=headers)
print(x.json())
Success Response
{
"non-compliant_revenue_ratio": 4.09,
"dividend_per_share_for_quarter": 0.23,
"dividend_purification_amount_per_share": 4.25227049219663e-12
}
Get Dividend Purification Results for stocks. You can query by stock ticker.
Purification request information
Category | Value |
---|---|
Http method | POST |
URL | https://platform.musaffa.com/b2b/api/v2/musaffa/stocks/dividends/pure |
Purification request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Content-Type | "application/json" | Request content type |
Purification request body in JSON format
Field | Value | Description |
---|---|---|
stock | "AAPL" | Stock symbol |
Purification response data structure (JSON)
Field | Type | Description |
---|---|---|
non-compliant_revenue_ratio | Number | Percentage of non-compliant revenue out of total revenue |
dividend_per_share_for_quarter | Number | Dividend per share for the latest quarter |
dividend_purification_amount_per_share | Number | Dividend purification amount per share (DPAPS) |
Formula for dividend purification: Dividend purification amount per share = Last Dividend per Share * (IR+QR)/100
IR - Impermissible Revenue Ratio QR - Questionable Revenue Ratio
Related Stocks
curl --location --request GET
'https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/related/AAPL'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
private String secretKey = "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ";
private String clientId = "EjXfR2rt7xADG";
RestTemplate restTemplate = new RestTemplate();
Instant nowUtc = Instant.now();
ZoneId zoneId = ZoneId.of("UTC+5");
String time = ZonedDateTime.ofInstant(nowUtc, zoneId).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
public String stock = "AAPL";
HttpHeaders headers = new HttpHeaders();
headers.set("token", generatedToken(time, stock));
headers.set("time", time);
headers.set("clientId", clientId);
HttpEntity<String> requestHttpEntity = new HttpEntity<>(headers);
ResponseEntity<Object> response = restTemplate.exchange("https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/related/" + stock, HttpMethod.GET, requestHttpEntity, Object.class);
System.out.println("Related stock RESULT : " + response.getBody());
private String generatedToken(String time, String stock) {
return Base64.getEncoder().encodeToString(DigestUtils.sha512(secretKey + time + stock));
}
import requests
import hashlib
import base64
from datetime import datetime
import pytz
client_id = "EjXfR2rt7xADG"
secret_key= "gUkXp2s5v8yBE(dYjhTi5PeShVmYq3t6w9z$C&F)JMcQfTjWnZ"
stock = "AAPL"
url = "https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/related/{stock}"
now = datetime.utcnow()
date_time_format = now.strftime("%Y%m%d%H%M%S")
token_pre_generate = secret_key + date_time_format + stock
token_sha512 = hashlib.sha512(token_pre_generate.encode("utf8")).digest()
token_base64 = base64.b64encode(token_sha512)
headers = {
"token" : token_base64,
"clientId" : client_id,
"time" : date_time_format,
"Content-Type" : "application/json"
}
x = requests.get(url=url , headers=headers)
print(x.json())
Success Response
[
{
"companyName": "Samsung Electronics Co Ltd",
"stockName": "SSNNF",
"shariahComplianceStatus": "NON_COMPLIANT",
"complianceRanking": 0
},
{
"companyName": "Canon Inc",
"stockName": "CAJ",
"shariahComplianceStatus": "COMPLIANT",
"complianceRanking": 3
},
{
"companyName": "Wipro Ltd",
"stockName": "WIT",
"shariahComplianceStatus": "QUESTIONABLE",
"complianceRanking": 0
},
{
"companyName": "Microsoft Corp",
"stockName": "MSFT",
"shariahComplianceStatus": "QUESTIONABLE",
"complianceRanking": 0
}
]
Related stocks is a list of stocks which match with current stock by market, industry and sector.
Related Stocks request information
Category | Value |
---|---|
Http method | GET |
URL | https://platform.musaffa.com/b2b/api/v1/musaffa/stocks/related/{AAPL} |
URL Param | Stock symbol |
Related Stocks request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Related Stocks response data structure (JSON array)
Field | Type | Description |
---|---|---|
companyName | String | Company name |
stockName | String | Stock symbol |
shariahComplianceStatus | String | Shariah-compliance Status (Halal, Not Halal, Doubtful, Not Covered) |
complianceRanking | number | Compliance Rank (0-5) |
Webhook
curl --location --request POST
'https://webhook_url'
--header 'token: token'
--header 'clientId: clientId'
--header 'time: yyyyMMddHHmmss'
--header 'Content-Type: application/json'
--data-raw '{
"companyName" : "Meta Platforms Inc",
"stockName" : "FB",
"lastUpdate" : "2022-04-05T08:49:28.089Z",
"shariahComplianceStatus" : "DOUBTFUL",
"complianceRanking" : 0,
"revenueBreakdown" : {
"notHalal" : 0.39,
"doubtful" : 97.46,
"halal" : 2.1500015,
"status" : "Fail"
},
"interestBearingSecuritiesAndAssets" : {
"interestRatio" : 6.99,
"status" : "Pass"
},
"interestBearingDebt" : {
"debtRatio" : 0.0,
"status" : "Pass"
},
"source" : "31-12-2021"
}'
Setting up webhook:
You provide us your webhook URL. All stock data updates will be sent through webhook instantly.
You can check your webhook header in the following format:
Webhook request information
Category | Value | Description |
---|---|---|
Http method | POST |
Webhook method |
URL | https://webhook_url | Your webhook URL |
Webhook request headers
Field | Value | Description |
---|---|---|
token | < token > | Should be shared separately for each client |
clientId | < clientId > | Should be shared separately for each client |
time | < yyyyMMddHHmmss > | Server time with "zoneId" TimeZone and formated in yyyyMMddHHmmss string |
Content-Type | "application/json" | Request content type |
Webhook request body in JSON format
Field | Type | Description |
---|---|---|
companyName | String | Company name |
stockName | String | Stock symbol |
shariahComplianceStatus | String | Shariah-compliance Status (Halal, Not Halal, Doubtful, Not Covered) |
complianceRanking | number | Compliance Rank (0-5) |
revenueBreakdown { notHalal, doubtful, halal, status } |
Object notHalal=>Float, doubtful=>Float, halal=>Float, status=>String |
Revenue Breakdown Combined revenue from ‘Doubtful’ and ‘Not-Halal’ sources must be less than 5% of total revenue to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
interestBearingSecuritiesAndAssets { interestRatio, status } |
Object interestRatio=>Float, status=>String |
Interest-bearing Securities and Assets Interest-Bearing Securities and Assets should be less than 30% of Trailing 36-month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology.Thus,
|
interestBearingDebt { debtRatio, status } |
Object debtRatio=>Float, status=>String |
Interest-bearing Debt Interest-Bearing Debt should be less than 30% of Trailing 36-Month Average Market Capitalization to be Shariah compliant based on AAOIFI stock screening methodology. Thus,
|
source | String | Reporting dates of the company |
Errors
The Musaffa API uses the following error codes:
Error Response
400 Bad Request:
{
"message": "Data validation error!",
"errors": [
{
"field": "token",
"value": "",
"message": "Token invalid or token generation error!"
}
]
}
Gives a "Time expired" error if the token time exceeds 5 seconds
400 Bad Request:
{
"message": "Data validation error!",
"errors": [
{
"field": "time",
"value": "20220328162043",
"message": "Time expired!"
}
]
}
Error Response
429 Too Many Requests:
{
"path": "/api/v1/musaffa/stocks/get",
"error": "Too Many Requests",
"message": "Request more than once per second",
"timestamp": "2022-05-12T15:18:17.943",
"status": 429
}
Error Response
429 Too Many Requests:
{
"path": "/api/v1/musaffa/stocks/get",
"error": "Too Many Requests",
"message": "Your monthly limit is over",
"timestamp": "2022-05-12T15:18:17.943",
"status": 429
}
Error Code | Meaning |
---|---|
400 | Bad Request -- Your request is invalid. |
401 | Unauthorized -- The access token is invalid or has been revoked. |
403 | Forbidden -- The stock requested is hidden for administrators only. |
404 | Not Found -- The specified stock could not be found. |
405 | Method Not Allowed -- You tried to access a stock with an invalid method. |
406 | Not Acceptable -- You requested a format that isn't json. |
429 | Too Many Requests -- You're requesting too many stocks! 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. |