B2B API v1.0
Last updated: April 27, 2022
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/v1/musaffa/stocks/get'
--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/v1/musaffa/stocks/get", 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/v1/musaffa/stocks/get"
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",
"stockName": "AAPL",
"shariahComplianceStatus": "COMPLIANT",
"complianceRanking": 1,
"revenueBreakdown": {
"notHalal": 2.1,
"doubtful": 2.0,
"halal": 95.9,
"status": "Pass"
},
"interestBearingSecuritiesAndAssets": {
"interestRatio": 10.0,
"status": "Pass"
},
"interestBearingDebt": {
"debtRatio": 5.0,
"status": "Pass"
},
"source": "30-MARCH-2021"
}
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/v1/musaffa/stocks/get |
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 |
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 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 |
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. |