Skip to main content

BFF Specification

Intro

As mentioned above, the BFF (Backend for Frontend) is designed to be a specification rather than an exact implementation. Therefore, this article aims to provide the specifications for a basic BFF server that is compatible with the Invent Platform.

While it is possible to expand the range of endpoints exposed on your BFF, this article will ensure that all essential endpoints are presented.

info

By default for security we are using authorization header. So any protected endpoint will expect an authorization: Bearer header with JWT in it.

Public endpoints could be fetched without going through the auth process. All the public routes are required for platform bootstrapping.

/theme

info

More about the theme contracts can be found in the theme article

GET: /theme

This endpoint should return the theme selected by the user. If no theme is selected - the default theme should be returned.

Method: GET

URI: /theme

Auth: Bearer header

content-type: application/json; charset=utf-8

response-status: 200/400/403/404

response-body: ThemeObject

GET: /theme/list

This endpoint should return a list of theme names.

Method: GET

URI: /theme/list

Auth: Bearer header

content-type: application/json; charset=utf-8

response-status: 200/400/403/404

response-body: ThemeObject[]

GET: /theme/:name

This endpoint provides access to the theme by name. Note that you HAVE to provide a fallback theme. The fallback theme should be prefixed with your company's slug. For example, the slug for Microsoft™ might be MS. So for a company called Owsome Company, it might be OC. And then the default theme name will look like OC-default. And the access endpoint for that theme will be https://my-bff-url.com/themes/OC-default.

Method: GET

URI: /theme/*SLUG*-default

Auth: not needed

response-status: 200/404

content-type: application/json; charset=utf-8

response-body: ThemeObject

POST: /theme/:name

This endpoint is used to upsert the specific theme. This endpoint is protected by default. So it is a good idea to keep it that way. If the theme with this name exists, it should be updated, if not - created. It is also better to create a whitelist of users who can use this endpoint. UserId is expected in the JWT token.

Method: POST

URI: /theme/*theme-name*

Auth: Bearer header.

request-body: ThemeObject

response-status: 200/400/403/404

response-body: -

/extensions

GET: /extensions/list

info

More about extensions you can find in Extension article

This endpoint returns a list of installed extensions.

Method: GET

URI: /extensions/list

Auth: Bearer

response-status: 200/403/404

content-type: application/json; charset=utf-8

response-body: ExtContractBff[]

Extension entity contract will look like:

type ExtContractBff = {
id: number;
name: string;
extHost: string;
version: string;
module: string;
scope: string;
useSharedExts: boolean;
dependencies: string[];
companion: string;
pathList: string[];
author: string;
};

Examples could be found here

/token

POST: /token/validate

This endpoint should return the status of the sent token.

type TokenValidateRT = {
status: "ok" | "unauthorized";
};
Method: POST

URI: /token/validate

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

response-body: TokenValidateRT

/tenent

GET: /tenent

This endpoint should return ENV param of tenentId. This one is used in widget-store

type TenentRT = {
tenentId: string;
};
Method: GET

URI: /tenent

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

response-body: TenentRT

/dashboards

Contracts

type DashboardMeta = {
name: string;
group: string;
version?: number;
role?: string;
id: string;
isVisible: boolean;
isShared: boolean;
sharedFor: string[];
creatorId: string;
couldBeEditedByRoles?: string[];
couldBeEditedByUsers?: string[];
};

type Dashboard = {
meta: DashboardMeta;
widgets: WidgetType[];
};

GET: /dashboards

This endpoint should return a list of dashboards to the user. If you want to apply some sort of access policy for getting a list of dashboards, this is the place to do it. You can also use this approach to implement dashboard sharing. It is also a good idea to return an empty list in case nothing is found by the user's query.

Method: GET

URI: /dashboards

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

response-body: Dashboard[]

POST: /dashboards

This endpoint upsert the dashboard. If the ID is empty or does not exist in the BFF datastore, a new dashboard is created.

Method: POST

URI: /dashboards

Auth: Bearer header.

request-body: Dashboard

response-status: 200/400/403/404

GET: /dashboards/metaList

This endpoint returns a list of dashboards meta-data. Can be used for an overview or quick access. Note that the list of DashboardMeta for users should be the same as for Dashboard.

Method: GET

URI: /dashboards/metaList

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

response-body: DashboardMeta[]

GET /dashboards/:dashboardId

This endpoint returns specific dashboard object.

Method: GET

URI: /dashboards/:dashboardId

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

response-body: Dashboard

DELETE /dashboards/:dashboardId

This endpoint deletes specific dashboard object.

Method: DELETE

URI: /dashboards/:dashboardId

Auth: Bearer

response-status: 200/401/404

content-type: application/json; charset=utf-8

POST: /dashboards/:dashboardId/thumbnail

This endpoint gives you the ability to upload images for a preview of specific dashboards.

Method: POST

URI: /dashboards/:dashboardId/thumbnail

Auth: Bearer header.

request-body: binary-image

response-status: 200/400/403/404

response-body: -