Authentication
API Key & Secret Authentication
Introduction
Access to Fuze API endpoints requires authentication.
The following section describes the authentication process and how to generate the required headers for making API calls.
The following sections assume that you have the API key and secret provided by Fuze.
Request headers
The following headers are required for all the API requests made to Fuze.
X-API-KEY
This is the API key that will be provided to you by Fuze.
Example: MCowBQYDK2VwAyEAsq2cTpSL0NoJXFmiQPGn+XSSya9ylor/dw1gM6xKmEw=
X-TIMESTAMP
This is the current epoch 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).
Example: 1671444764
X-SIGNATURE
This is the HMAC signature generated using the API secret provided to you by Fuze. The process of generating this signature is described in detail below.
Example: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
Generating request signature
HMAC SHA256 is a cryptographic hash function that is used to ensure the integrity and authenticity of a message.
It requires a secret key and a payload as input, and produces a fixed-size output, called the signature.
Before making any request to the Fuze endpoints, create a JSON payload with the following fields in the given order.
{
"body": "<request body as a 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 type-casted to string>"
}Stringify the above JSON payload and use it as input to the HMAC SHA256 signing operation with the API secret provided by Fuze to generate the signature.
Note that the order of fields in the request body must match exactly to the one used to generate the signature.
Payload examples
Assume that the endpoint https://staging.api.fuze.finance/api/v1/org/ is being called at the epoch 1671444764.
"GET request without query parameters"
URL:
https://staging.api.fuze.finance/api/v1/org/
Payload:
{
"body": {},
"query": {},
"url": "/api/v1/org/",
"ts": "1671444764"
}"GET request with query parameters"
URL:
https://staging.api.fuze.finance/api/v1/org/?key_1=value_1&key_2=value_2
Payload:
{
"body": {},
"query": {
"key_1": "value_1",
"key_2": "value_2"
},
"url": "/api/v1/org/",
"ts": "1671444764"
}"POST request with body"
URL:
https://staging.api.fuze.finance/api/v1/org/
Body:
{
"key_1": "value_1",
"key_2": "value_2"
}
Payload:
{
"body": {
"key_1": "value_1",
"key_2": "value_2"
},
"query": {},
"url": "/api/v1/org/",
"ts": "1671444764"
}"POST request with query parameters and body"
URL:
https://staging.api.fuze.finance/api/v1/org/?key_1=value_1&key_2=value_2
Body:
{
"key_3": "value_3",
"key_4": "value_4"
}
Payload:
{
"body": {
"key_3": "value_3",
"key_4": "value_4"
},
"query": {
"key_1": "value_1",
"key_2": "value_2"
},
"url": "/api/v1/org/",
"ts": "1671444764"
}Sample code
import axios from "axios";
import { DateTime } from "luxon";
import * as crypto from "node:crypto";
async function main() {
const API_ENDPOINT = "https://staging.api.fuze.finance";
// Use your API key and secret
const API_KEY = "MCowBQYDK2VwAyEA4WzlYqeSEuTIddAOo0VIeaZkjTqp8LUCRZz2qxz7ce4=";
const API_SECRET = `MC4CAQAwBQYDK2VwBCIEIEWY0tGWVuA8HEaXFjzC/AT7T2YP9bcW/nsDYnGkk9ib`;
const body = {
orgUserId: "[email protected]",
kyc: true,
tnc: true
};
const query = {};
const slug = `/api/v1/user/`;
const now = DateTime.utc().toSeconds();
const ts = String(Math.round(now + 3600));
// Generate the signature
const hmac3 = crypto.createHmac("sha256", API_SECRET);
const payload = {
body,
query,
url: slug,
ts
};
hmac3.update(JSON.stringify(payload));
const signature = hmac3.digest("hex");
// Send the request
const url = `${API_ENDPOINT}${slug}`
const headers = {
"X-API-KEY": API_KEY,
"X-TIMESTAMP": ts,
"X-SIGNATURE": signature
}
const response = await axios.post(
url,
body,
{ headers }
);
if (
response.status !== 200 ||
response.data?.code !== 200 ||
response.data?.error
) {
console.error(`Error calling the API`);
return;
}
console.log(`Success with data: ${response.data}`);
}
main();OAuth 2.0
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_idandclient_secretprovided - 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_credentialsalways
- 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/testapi to test out the OAuth functionality.- Just ensure the access token has the
BASE_MODULE'sWRITE/READWRITEpermission, since the test api requiresWRITEpermission.
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 }
Updated about 1 month ago