JavaScript SDK
Overview of the JavaScript SDK for Fans United platform
Welcome to the Fans United JavaScript SDK. This SDK works for client-side, server-side and React Native implementations. The SDK has complete coverage of the Fans United APIs and is split into different namespaces depending on what you want to achieve.
Operations supported by the SDK:
- Profile Operations
- Football Operations
- Predictor Operations
- Top X Operations
- Match Quiz Operations
- Loyalty Operations
- Activity Operations
- Mini-Games Operations
- Progress Operations
- Private Leagues Operations
- Discussions Operations
- Fantasy Operations
- Voting Operations
- Odds Operations
- Bracket Games Operations
- Challenges Operations
- Helpers Operations
- Lists Operations
- Standing Games operations
- Event Games operations
Install the SDK
The JavaScript SDK is distributed as 2 NPM packages - ESM and UMD.
ESM
Install JavaScript SDK as ESM dependency by running the following command:
npm i fansunited-sdk-esm
yarn add fansunited-sdk-esm
UMD
For UMD package run the following command:
npm i fansunited-sdk-umd
yarn add fansunited-sdk-umd
For CDN add the following script command in your html file:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.js"></script>
Where "@1.23.0" is the version of JS SDK that you want to use in your application.
Use the SDK in your app
The SDK works with JWTs provided from OAuth2 provider. The default provider is Firebase Authentication, but if the client has their own provider, it can be integrated into the platform.
The SDK comes with a configuration and an interface. The client needs to implement this interface and pass the implementation in the config.
Initiate the SDK
This is what the SDK config requires:
N.B: The following example is when JavaScript SDK is installed as an ESM dependency
import {FansUnitedSDK} from "fansunited-sdk-esm";
let fansUnitedSdk = FansUnitedSDK({
apiKey: "your-api-key-here",
environment: "prod|watg|yolo|cska", // default: prod
clientId: "your-client-id-here",
lang: "bg|en|ro|el|sk", // default: en
idSchema: "native|enetpulse|sportradar|sportal365", // default: native
errorHandlingMode: "default|standard", // default: default
oddClient: { // Define your odd client here. When not provided, the Odds namespace will NOT work
name: "oddClient",
credentials: {
username: "username",
password: "password",
} // Credentials so SDK can authenticate in Sportal 365 Football API
},
cookieToken: {
name: "nameOfTheCookie",
requestHeaders: Headers, // Fetch API Headers. Optional, but will be required in server-side
}, // optional
authProvider: new myTokenProvider() //Optional, but it will be required if cookieToken not provided
});
You need to create a class that has the following 2 methods:
- getIdToken() - This function should return a valid JWT as a string. This token is used for all requests that require authentication. If any API returns 401 Unauthorized response, the SDK will repeat the request by calling the getIdToken() function again, expecting that the token has been changed. If the token has not changed and the API still returns 401, the exception will be relayed to the client.
- logout() - you can implement custom logout logic here
A client supplied class would look like this:
class myTokenProvider {
getIdToken = () => {
// custom logic ....
return "tokenString"; // no need prefixing this with Bearer. Just the plain token string is needed
}
logout = () => {
// custom logic ....
};
}
TypeScript
Providing configuration to JS SDK in TypeScript projects follow this model:
class SDKConfigurationModel {
apiKey: string;
clientId: string;
environment?: EnvironmentType;
idSchema?: IdSchemaType;
lang?: LangType;
errorHandlingMode?: ErrorHandlingModeType;
oddClient?: OddClientConfig;
cookieToken?: CookieTokenType;
authProvider?: FansUnitedAuthInterface;
}
type EnvironmentType = 'dev' | 'prod' | 'staging' | 'watg' | 'yolo' | 'cska';
type IdSchemaType = 'native' | 'enetpulse' | 'sportal365' | 'sportradar';
type LangType = 'bg' | 'en' | 'ro' | 'el' | 'sk';
type ErrorHandlingModeType = 'default' | 'standard';
type OddClientConfig = {
name: string;
credentials: OddClientCredentials
};
type OddClientCredentials = {
username: string;
password: string;
};
type CookieTokenType = {
name: string;
requestHeaders?: Headers;
};
Here is an example how you can construct this configuration:
class TokenProvider {
public getIdToken = (): string => {
// custom logic ....
return "tokenString";
};
public logout = () => {
// custom logic ....
};
}
const idSchema: IdSchemaType = 'sportal365';
const lang: LangType = 'bg';
const environment: EnvironmentType = 'staging';
const errorHandlingMode: ErrorHandlingModeType = 'standard';
const oddClient = {
name: "oddClient",
credentials: {
username: "username",
password: "password"
}
};
const cookieToken = {
name: "nameOfTheCookie",
headers: Headers
};
const config = {
apiKey: "AIzaSyBDsY25nJ4VZz0iiLLQpPRnjMRnIHkyqg4",
clientId: "productiontesting1",
authProvider: new TokenProvider(),
cookieToken, // Optional, if not provided authProvider will be required
idSchema,
lang,
environment,
errorHandlingMode,
oddClient
};
N.B
As you can see from SDKConfigurationModel, fields idSchema
, lang
, environment
, errorHandlingMode
, oddClient
, cookieToken
and authProvider
are optional. If they are not provided, they will be set to default values (except for oddClient
, cookieToken
and authProvider
). Default values: idSchema: "native"
, lang: "en"
, environment: "prod"
, errorHandlingMode: "default"
.
When no oddClient is provided, the Odds namespace can't be used
When cookieToken is not provided, then authProvider will be required
Configuration validator
When you provide a configuration, it gets validate before Fans United JS SDK initialisation. If some of the fields are missing or invalid, warning messages are logged or error messages are throwed.
Warning messages
All warning messages are logged to the developer. The following cases contains warning messages:
- When
idSchema
is NOT provided. Logs the following message: If no idSchema is passed the default one will be set which is: native. - When
idSchema
is provided, but the value is NOT supported: This idSchema value is not supported, the default one will be set which is: native. - When
environment
is NOT provided. Logs the following message: If no environment is passed the default one will be set which is: prod. - When
environment
is provided, but the value is NOT supported: This environment value is not supported, the default one will be set which is: prod. - When
lang
is NOT provided. Logs the following message: If no lang is passed the default one will be set which is: en. - When
lang
is provided, but the value is NOT supported: This lang value is not supported, the default one will be set which is: en. - When
errorHandlingMode
is NOT provided. Logs the following message: If no errorHandlingMode is passed the default one will be set which is: default. - When
errorHandlingMode
is provided, but the value is NOT supported: This errorHandlingMode value is not supported, the default one will be set which is: default. - When for
authProvider
field has been provided more properties than the expected ones (getIdToken
andlogout
): You have passed a property which is not supported for the authentication provider: - When
oddClient
is NOT provided logs the following message: If no oddClient is passed the Odds namespace will not work. For more information check our documentation. - When
oddClient
contains properties who are not supported: You have passed properties which are not supported for the odd client configuration property:. - When
credentials
inoddClient
contains properties who are not supported: You have passed properties which are not supported for the odd client credentials configuration property:. - When
cookieToken
consist properties who are not supported logs the following message: The following property is missing from the cookieToken object:.
Error messages
All error messages are throwed to the developer. The following cases contains error messages:
- When
apiKey
is NOT provided. Throws the following message: The field apiKey with valid value must be provided to use Fans United JS SDK. - When
clientId
is NOT provided. Throws the following message: The field clientId must be provided to use Fans United JS SDK. - When
cookieToken
is missing some of if properties logs the following message: You have passed properties which are not supported for the cookie token configuration property:. - When
authProvider
is NOT provided. Throws the following message: The field authProvider must be provided to use this SDK. - When
authProvider
is missing some ofFansUnitedAuthInterface
methods. Throws the following message: The following property is missing from the authProvider object: - When
oddClient
is not an object. Throws the following message: The oddClient object is not valid. For more information check our documentation - When
oddClient
has missing properties. Throws the following message: The field oddClient has missing properties. For more information check our documentation - When
credentials
inoddClient
is not an object. Throws the following message: The odd client credentials object is not valid. The odd client will not work without credentials. For more information check our documentation - When
credentials
inoddClient
has missing properties. Throws the following message: The following property is missing from the odd client credentials object: - When
username
orpassword
are not valid incredentials
inoddClient
. Throws the following message: The odd client credentials object is not valid. The odd client will not work without credentials. For more information check our documentation
Authentication via cookie header
The cookieToken
configuration allows the SDK to automatically extract JWT tokens from HTTP cookies on the server-side, eliminating the need to manually pass tokens or implement custom authentication providers for server-side rendering scenarios.
Recommendations:
- All public methods (no authentication required) from the JS SDK can be used from one single (global) instance. This instance can be set up on the server side.
- For private methods (who required authentication), create SDK instance per user with their specific tokens on the client side.
Cookie Token Type
export type CookieTokenType = {
name: string; // The name of the cookie containing the JWT token
requestHeaders?: Headers; // Headers object containing the cookie header. This is required only on server-side
};
NextJS App Router Implementation
Basic Setup
import { FansUnitedSDK, SDKConfiguraitonModel } from "fansunited-sdk-esm";
import { cookies, headers } from "next/headers";
export default async function MyPage() {
// Get server-side headers and cookies
const headersList = headers();
const cookieStore = cookies();
const jwtCookieName = "jwtToken";
// Create Headers object for the SDK
const requestHeaders = new Headers();
const cookieHeader = headersList.get("cookie");
// Set the complete cookie header string
if (cookieHeader) {
requestHeaders.set("cookie", cookieHeader);
}
// Check if JWT token exists
const jwtCookie = cookieStore.get(jwtCookieName);
const hasJwtToken = !!jwtCookie?.value;
if (hasJwtToken) {
// Configure SDK with cookie token
const config: SDKConfiguraitonModel = {
apiKey: "your-api-key",
clientId: "your-client-id",
idSchema: "your-id-schema",
environment: "your-environment",
lang: "your-lang",
errorHandlingMode: "standard",
cookieToken: {
name: jwtCookieName, // Your JWT cookie name
requestHeaders, // Headers object with cookies
},
};
const sdk = FansUnitedSDK(config);
// Use the SDK
try {
const profileData = await sdk.profile.getOwn().getInfo();
// Handle success
} catch (error) {
// Handle error
}
}
return <div>Your component JSX</div>;
}
NextJS Pages Router Implementation
Using getServerSideProps
import { GetServerSideProps } from "next";
import { FansUnitedSDK, SDKConfiguraitonModel } from "fansunited-sdk-esm";
export const getServerSideProps: GetServerSideProps = async ({ req }) => {
// Create Headers object from request
const requestHeaders = new Headers();
const cookieHeader = req.headers.cookie;
if (cookieHeader) {
requestHeaders.set("cookie", cookieHeader);
}
// Configure SDK
const config: SDKConfiguraitonModel = {
apiKey: process.env.FANS_UNITED_API_KEY!,
clientId: process.env.FANS_UNITED_CLIENT_ID!,
idSchema: process.env.FANS_UNITED_ID_SCHEMA!,
environment: process.env.FANS_UNITED_ENVIRONMENT!,
lang: process.env.FANS_UNITED_LANG!,
errorHandlingMode: process.env.FANS_UNITED_ERROR_HANDLING_MODE!,
cookieToken: {
name: "jwtToken",
requestHeaders,
},
};
try {
const sdk = FansUnitedSDK(config);
const data = await sdk.profile.getOwn().getInfo();
return {
props: { data },
};
} catch (error) {
return {
props: { error: error.message },
};
}
};
export default function MyPage({ data, error }) {
if (error) return <div>Error: {error}</div>;
return <div>Data: {JSON.stringify(data)}</div>;
}
Example NextJS API route for setting JWT cookie
export async function POST(request: Request) {
const { token } = await request.json();
const response = NextResponse.json({ success: true });
response.cookies.set({
name: "jwtToken",
value: JSON.stringify({ token }),
httpOnly: true, // Prevent XSS
secure: process.env.NODE_ENV === "production", // HTTPS only in production
sameSite: "strict", // CSRF protection
path: "/",
maxAge: 60 * 60 * 24 * 7, // 1 week
});
return response;
}
NodeJS Implementations
ExpressJS Implementation
import express from "express";
import { FansUnitedSDK, SDKConfiguraitonModel } from "fansunited-sdk-esm";
const app = express();
app.get("/profile", async (req, res) => {
try {
// Create Headers object from Express request
const requestHeaders = new Headers();
const cookieHeader = req.get("Cookie") || req.headers.cookie;
if (!cookieHeader) {
return res.status(401).json({ error: "No cookies found" });
}
requestHeaders.set("cookie", cookieHeader);
// Check if JWT token exists in cookies
const cookies = cookieHeader.split(";").reduce((acc, cookie) => {
const [name, value] = cookie.trim().split("=");
if (name && value) acc[name] = value;
return acc;
}, {} as Record<string, string>);
if (!cookies.jwtToken) {
return res.status(401).json({ error: "JWT token not found" });
}
// Configure SDK
const config: SDKConfiguraitonModel = {
apiKey: process.env.FANS_UNITED_API_KEY!,
clientId: process.env.FANS_UNITED_CLIENT_ID!,
idSchema: process.env.FANS_UNITED_ID_SCHEMA!,
environment: process.env.FANS_UNITED_ENVIRONMENT!,
lang: process.env.FANS_UNITED_LANG!,
errorHandlingMode: process.env.FANS_UNITED_ERROR_HANDLING_MODE!,
cookieToken: {
name: "jwtToken",
requestHeaders,
},
};
const sdk = FansUnitedSDK(config);
const profileData = await sdk.profile.getOwn().getInfo();
res.json(profileData);
} catch (error) {
console.error("SDK Error:", error);
res.status(500).json({ error: error.message });
}
});
// Set JWT cookie endpoint
app.post("/auth/set-token", (req, res) => {
const { token } = req.body;
res.cookie("jwtToken", JSON.stringify({ token }), {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
});
res.json({ success: true, message: "Token set successfully" });
});
Fastify Implementation
import Fastify from "fastify";
import { FansUnitedSDK, SDKConfiguraitonModel } from "fansunited-sdk-esm";
const fastify = Fastify();
// Register cookie plugin
await fastify.register(import("@fastify/cookie"));
fastify.get("/profile", async (request, reply) => {
try {
// Create Headers object from Fastify request
const requestHeaders = new Headers();
const cookieHeader = request.headers.cookie;
if (!cookieHeader) {
return reply.status(401).send({ error: "No cookies found" });
}
requestHeaders.set("cookie", cookieHeader);
// Check if JWT token exists
const jwtToken = request.cookies.jwtToken;
if (!jwtToken) {
return reply.status(401).send({ error: "JWT token not found" });
}
// Configure SDK
const config: SDKConfiguraitonModel = {
apiKey: process.env.FANS_UNITED_API_KEY!,
clientId: process.env.FANS_UNITED_CLIENT_ID!,
idSchema: process.env.FANS_UNITED_ID_SCHEMA!,
environment: process.env.FANS_UNITED_ENVIRONMENT!,
lang: process.env.FANS_UNITED_LANG!,
errorHandlingMode: process.env.FANS_UNITED_ERROR_HANDLING_MODE!,
cookieToken: {
name: "jwtToken",
requestHeaders,
},
};
const sdk = FansUnitedSDK(config);
const profileData = await sdk.profile.getOwn().getInfo();
return profileData;
} catch (error) {
console.error("SDK Error:", error);
return reply.status(500).send({ error: error.message });
}
});
// Set JWT cookie endpoint
fastify.post("/auth/set-token", async (request, reply) => {
const { token } = request.body as { token: string };
reply.setCookie("jwtToken", JSON.stringify({ token }), {
httpOnly: true,
secure: process.env.NODE_ENV === "production",
sameSite: "strict",
maxAge: 7 * 24 * 60 * 60 * 1000, // 1 week
});
return { success: true, message: "Token set successfully" };
});
Raw NodeJS HTTP Server
import http from "http";
import { FansUnitedSDK, SDKConfiguraitonModel } from "fansunited-sdk-esm";
const server = http.createServer(async (req, res) => {
if (req.url === "/profile" && req.method === "GET") {
try {
// Extract cookie header
const cookieHeader = req.headers.cookie;
if (!cookieHeader) {
res.writeHead(401, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "No cookies found" }));
return;
}
// Create Headers object
const requestHeaders = new Headers();
requestHeaders.set("cookie", cookieHeader);
// Parse cookies
const cookies = cookieHeader.split(";").reduce((acc, cookie) => {
const [name, value] = cookie.trim().split("=");
if (name && value) acc[name] = value;
return acc;
}, {} as Record<string, string>);
if (!cookies.jwtToken) {
res.writeHead(401, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: "JWT token not found" }));
return;
}
// Configure SDK
const config: SDKConfiguraitonModel = {
apiKey: process.env.FANS_UNITED_API_KEY!,
clientId: process.env.FANS_UNITED_CLIENT_ID!,
idSchema: process.env.FANS_UNITED_ID_SCHEMA!,
environment: process.env.FANS_UNITED_ENVIRONMENT!,
lang: process.env.FANS_UNITED_LANG!,
errorHandlingMode: process.env.FANS_UNITED_ERROR_HANDLING_MODE!,
cookieToken: {
name: "jwtToken",
requestHeaders,
},
};
const sdk = FansUnitedSDK(config);
const profileData = await sdk.profile.getOwn().getInfo();
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify(profileData));
} catch (error) {
res.writeHead(500, { "Content-Type": "application/json" });
res.end(JSON.stringify({ error: error.message }));
}
}
});
server.listen(3000, () => {
console.log("Server running on port 3000");
});
Supported JWT Cookie Formats
The SDK automatically handles different JWT cookie formats:
1. Direct JWT String
jwtToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
2. JSON Object with Token Property
jwtToken={"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
3. URL-Encoded JSON Object
jwtToken=%7B%22token%22%3A%22eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...%22%7D
SDK instance versioning
getVersion method
To be able to see the current version of SDK that you are using, you can call the getVersion
method. It returns the following method:
Method call:const version = sdk.getVersion(); console.log(version) // See below for logged model
The version as it follows:
{
version: "1.78.0",
major: 1,
minor: 78,
patch: 0,
releaseCandidate: null, // When version is 1.78.0-RC1, then the releaseCandidate will be 1
}
Updated 14 days ago