Authentication
Base URL variable:
All API examples below use{url}
as the base URL.
Set{url}
to your Fuze API endpoint, e.g.
https://preprod.api.fuze.finance
API Key & Secret Authentication
Introduction
Calling every endpoint requires the following HEADERS to be set in the request.
- X-API-KEY: This is the api-key that you get from Fuze.
- X-TIMESTAMP: This is the Unix time in seconds (i.e. the number of seconds that have elapsed since 00:00:00 UTC on 1 January 1970, the beginning of the Unix epoch, less adjustments made due to leap seconds).
- X-SIGNATURE: This is the HMAC signature which is a keyed HMAC SHA256 operation. You need to use the api-secret as the key and stringified JSON object containing request body, request params, url slug and X-TIMESTAMP as the payload for the HMAC operation. Please check the section on how to generate this signature.
Generating the value for X-SIGNATURE request header
HMAC SHA256 signing operation requires two inputs: a key (with which the payload would be signed) and a payload (the value which would be signed using the key).
For generating the X-SIGNATURE value, you would use the api-secret as the key. The payload (X-SIGNATURE) will be a stringified JSON object where the JSON object would be:
{
"body": "<request body as JSON object>",
"query": "<query parameters as key-value fields in a JSON object>",
"url": "<the url slug for the api endpoint>",
"ts": "<the value of X-TIMESTAMP header casted to string>"
}
Please note that the order of these four fields (viz. "body", "query", "url" & "ts") should be the same as depicted above.
Also note, that the order of body is important for signature generation and verification.
Examples of different kinds of API requests and corresponding payload structure for generating X-SIGNATURE
GET request with no query parameters:
Make a GET call to {url}/api/v1/org/
. This does not contain any body or query parameters.
JSON Payload:
{
"body": {},
"query": {},
"url": "/api/v1/org/",
"ts": "1671444764"
}
GET request with a few query parameters:
Make a GET call to {url}/api/v1/org/?k1=v1&k2=v2
. This does not contain any body but has a couple of query parameters.
JSON Payload:
{
"body": {},
"query": {
"k1": "v1",
"k2": "v2"
},
"url": "/api/v1/org/",
"ts": "1671444764"
}
POST request with a body but no query parameters:
Make a POST call to {url}/api/v1/user/
. This contains a body but no query parameters. The body is as follows:
{
"orgUserId": "ankitshubham97",
"kyc": false,
"tnc": true
}
JSON Payload:
{
"body": {
"orgUserId": "ankitshubham97",
"kyc": false,
"tnc": true
},
"query": {},
"url": "/api/v1/user/",
"ts": "1671444764"
}
POST request with a body and query parameters:
Make a POST call to {url}/api/v1/user/?k1=v1&k2=v2
. This contains a body and a few query parameters. The body is as follows:
{
"orgUserId": "ankitshubham97",
"kyc": false,
"tnc": true
}
JSON Payload:
{
"body": {
"orgUserId": "ankitshubham97",
"kyc": false,
"tnc": true
},
"query": {
"k1": "v1",
"k2": "v2"
},
"url": "/api/v1/user/",
"ts": "1671444764"
}
Sample code to generate HMAC SHA256 signature from a key and payload
PHP Sample code:
<?php
$API_KEY = "your_api_key";
$API_SECRET = "your_api_secret";
$orgUserId = "ankitshubham97";
$API_ENDPOINT = "{url}";
$body = array('orgUserId' => $orgUserId, 'kyc' => true, 'tnc' => true);
$query = new \stdClass();
$url = "/api/v1/user/";
$ts = time() + 3600;
$payload = json_encode(
array(
"body" => $body, "query" => $query, "url" => $url, "ts" => strval($ts)
), JSON_UNESCAPED_SLASHES
);
$sig = hash_hmac('sha256', $payload, $API_SECRET);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $API_ENDPOINT.$url);
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($body) );
$headers = [
'Content-Type:application/json',
'X-API-KEY:'.$API_KEY,
'X-TIMESTAMP:'.strval($ts),
'X-SIGNATURE:'.$sig,
];
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$output = curl_exec($ch);
echo $output;
curl_close($ch);
?>
NodeJS sample code:
import axios from "axios";
import { DateTime } from "luxon";
import * as crypto from "node:crypto";
async function main() {
const API_ENDPOINT = "{url}";
const API_KEY = "your_api_key";
const API_SECRET = "your_api_secret";
const orgUserId = `ankitshubham97`;
const body = {
orgUserId,
kyc: true,
tnc: true,
};
const query = {};
const url = `/api/v1/user/`;
const ts = Math.round(DateTime.utc().toSeconds() + 3600);
const hmac3 = crypto.createHmac("sha256", API_SECRET);
hmac3.update(
JSON.stringify({
body: body,
query: query,
url: `${url}`,
ts: `${ts}`,
})
);
const signature = hmac3.digest("hex");
const response = await axios.post(`${API_ENDPOINT}${url}`, body, {
headers: {
"X-API-KEY": API_KEY,
"X-TIMESTAMP": `${ts}`,
"X-SIGNATURE": signature,
},
});
if (
!(
response.status === 200 &&
response.data?.code === 200 &&
response.data?.data &&
!response.data.error
)
) {
console.error(`Error while calling createUser api`);
return;
}
console.log(`Data response to createUser api: ${response.data}`);
}
main();
IMPORTANT
Note: The signature algorithm assumes that you strip off trailing decimal points when generating the signature.
For example 55000.00
should be represented as 55000
, and 55.50
as 55.5
.
This is to ensure a consistent JSON encoding/decoding across all languages. (We follow the
golang/javascript
version of encoding and decoding.)
OAuth
Introduction
Open Authorization aka OAuth is a widely adopted Authorization framework across the industry. Fuze supports the OAuth client credentials flow, which requires no user involvement & is a machine-to-machine (m2m) flow.
Overview of the workflow for making requests using OAuth
- Generate an access token using
client_id
andclient_secret
provided - Until the access token validity lasts, pass the generated access token in the authorization header.
Prerequisites - You must have client_id
& client_secret
which would've been provided to you by Fuze over a secure channel. Ensure to keep them private & secure at all times.
Generating access token
You need to make a POST
request to {url}/api/v1/oauth/token
with the request details mentioned below to generate the access token
Request & response format
- Request
-
Request content type should be
application/x-www-form-urlencoded
-
Request parameters:
grant_type
- Must be
client_credentials
always
- Must be
client_id
- Use the value provided by Fuze
client_secret
- Use the value provided by Fuze
scope
- Space separated
<MODULE>:<PERMISSION>
values.
- Space separated
-
Sample cURL to make this request:
curl --location '{url}/api/v1/oauth/token' \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode 'grant_type=client_credentials' \ --data-urlencode 'scope=<SCOPE>' \ --data-urlencode 'client_id=<CLIENT_ID>' \ --data-urlencode 'client_secret=<CLIENT_SECRET>'
-
- Response
- Failure responses:
{ "code": 401, "error": "Forbidden", "data": null }
- Success Response:
{ "code": 200, "data": { "access_token": "<access_token>", "expires_in": 300000, "token_type": "Bearer", "scope": "BASE_MODULE:WRITE" }, "error": null }
- Failure responses:
Example request & response
200 Success request
Sample Valid Request:
curl --location '{url}/api/v1/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=BASE_MODULE:WRITE'
Sample 200 Response:
{
"code": 200,
"data": {
"access_token": "<access_token>",
"expires_in": 300000,
"token_type": "Bearer",
"scope": "BASE_MODULE:WRITE"
},
"error": null
}
401 Failure request
Sample Invalid Request:
curl --location '{url}/api/v1/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'scope=BASE_MODULE:WRITE MANAGE_USERS:WRITE'
Sample 401 Response:
{
"code": 401,
"error": "Forbidden",
"data": null
}
Making requests using access token
You need to pass the access token in the Authorization
header as the bearer token. And if all is good, the request would be authorized successfully.
Note:
- You can make use of the
/api/v1/oauth/test
api to test out the OAuth functionality.- Just ensure the access token has the
BASE_MODULE
'sWRITE
/READWRITE
permission, since the test api requiresWRITE
permission.
Example request & response
- 200 - Sample API request using OAuth access token with
WRITE
, API requiresWRITE
: Request:Response:curl --location '{url}/api/v1/oauth/test' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <access_token>' \ --data '{ "hello": "world" }'
{ "code": 200, "data": { "hello": "world" }, "error": null }
- 401 - Sample API request using OAuth access token with
READ
, API requiresWRITE
: Request:Response:curl --location '{url}/api/v1/oauth/test' \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer <access_token>' \ --data '{ "hello": "world" }'
{ "message": "You're not authorized", "status": 401 }