REST API
REST API enables Cube to deliver data over the HTTP protocol to certain kinds of data applications, including but not limited to the following ones:
- Most commonly, front-end applications
- Some data notebooks, e.g., Observable
- Low-code tools, e.g., Retool
- Automated jobs
Often, the REST API is used to enable embedded analytics (opens in a new tab) and real-time analytics (opens in a new tab) use cases.
If you've chosen GraphQL (opens in a new tab) as a query language for your front-end application, consider using the GraphQL API that Cube also provides.
Under the hood, REST API also provides endpoints for GraphQL API and Orchestration API. However, they target specific use cases and are not usually considered part of the REST API.
Example request
You can use the curl
utility to execute requests to the REST API:
curl \
-H "Authorization: JSON.WEB.TOKEN" \
-G \
--data-urlencode 'query={
"dimensions": [
"users.state",
"users.city",
"orders.status"
],
"measures": [
"orders.count"
],
"filters": [
{
"member": "users.state",
"operator": "notEquals",
"values": ["us-wa"]
}
],
"timeDimensions": [
{
"dimension": "orders.created_at",
"dateRange": ["2020-01-01", "2021-01-01"]
}
],
"limit": 10
}' \
http://localhost:4000/cubejs-api/v1/load
You can also use the jq
utility (opens in a new tab) to format responses
from the REST API in your terminal:
curl \
-H "Authorization: JSON.WEB.TOKEN" \
-G \
--data-urlencode 'query={"measures": ["orders.count"]}' \
http://localhost:4000/cubejs-api/v1/load | jq .data
You can also introspect the data model by querying the /v1/meta
endpoint:
curl \
-H "Authorization: JSON.WEB.TOKEN" \
http://localhost:4000/cubejs-api/v1/meta | jq
Check query format for details about supported queries. Also, check REST API reference for the list of supported API endpoints.
Configuration
REST API is enabled by default and secured using API scopes and CORS.
To find your REST API endpoint in Cube Cloud, go to the Overview page, click API credentials, and choose the REST API tab.
Base path
By default, all REST API endpoints are prefixed with a base path of
/cubejs-api
, e.g., the /v1/load
endpoint will be available at
/cubejs-api/v1/load
.
Exception: /livez
and /readyz
endpoints are not prefixed with a base path.
You can set a desired base path using the basePath
configuration option.
API scopes
Each REST API endpoint belongs to an API scope, e.g., the /v1/load
endpoint
belongs to the data
scope. API scopes allow to secure access to API endpoints
by making them accessible to specific users only or disallowing access for
everyone. By default, API endpoints in all scopes, except for jobs
, are
accessible for everyone.
API scope | REST API endpoints | Accessible by default? |
---|---|---|
meta | /v1/meta | ✅ Yes |
data | /v1/load , /v1/sql | ✅ Yes |
graphql | /graphql | ✅ Yes |
jobs | /v1/pre-aggregations/jobs | ❌ No |
Exception: /livez
and /readyz
endpoints don't belong to any scope. Access to
these endpoints can't be controlled using API scopes.
You can set accessible API scopes for all requests using the
CUBEJS_DEFAULT_API_SCOPES
environment variable. For example, to disallow
access to the GraphQL API for everyone, set CUBEJS_DEFAULT_API_SCOPES
to
meta,data
.
You can also select accessible API scopes for each request using the
contextToApiScopes
configuration option, based
on the provided security context. For example, to
restrict access to the /v1/meta
endpoint to service accounts only, you can set
CUBEJS_DEFAULT_API_SCOPES
to data,graphql
and use the following
configuration in the cube.js
file, assuming that service accounts have
service: true
in their security context:
module.exports = {
contextToApiScopes: (securityContext, defaultScopes) => {
if (securityContext.service) {
return ["meta", ...defaultScopes];
}
return defaultScopes;
},
};
CORS
REST API supports Cross-Origin Resource Sharing (CORS) (opens in a new tab). By default,
requests from any origin (*
) are allowed.
You can configure CORS using the http.cors
configuration
option. For example, to allow requests from a specific domain only, use the
following configuration in the cube.js
file:
module.exports = {
http: {
cors: {
origin: "https://example.com",
},
},
};
Prerequisites
Authentication
Cube uses API tokens to authorize requests and also for passing additional
security context, which can be used in the
queryRewrite
property in your cube.js
configuration file.
The API Token is passed via the Authorization Header. The token itself is a JSON Web Token (opens in a new tab), the Security section describes how to generate it.
In the development environment the token is not required for authorization, but you can still use it to pass a security context.
Continue wait
If the request takes too long to be processed, Cube Backend responds with
{ "error": "Continue wait" }
and 200 status code. This is how the long polling
mechanism in Cube is implemented. Clients should continuously retry the same
query in a loop until they get a successful result. Subsequent calls to the Cube
endpoints are idempotent and don't lead to scheduling new database queries if
not required by the refresh_key
. Also,
receiving Continue wait
doesn't mean the database query has been canceled, and
it's actually still being processed by the Cube. Database queries that weren't
started and are no longer waited by the client's long polling loop will be
marked as orphaned and removed from the querying queue.
Possible reasons of Continue wait:
- The query requested is heavy, and it takes some time for the database to
process it. Clients should wait for its completion, continuously sending the
same REST API request.
continueWaitTimeout
can be adjusted in order to change the time Cube waits before returningContinue wait
message. - There are many queries requested and Cube backend queues them to save database from overloading.
Error Handling
Cube REST API has basic errors and HTTP Error codes for all requests.
Status | Error response | Description |
---|---|---|
400 | Error message | General error. It may be a database error, timeout, or other issue. Check error message for details. |
403 | Authorization header isn't set | You didn't provide an auth token. Provide a valid API Token or disable authorization. |
403 | Invalid token | The auth token provided is not valid. It may be expired or have invalid signature. |
500 | Error message | Cube internal server error. Check error message for details. |
Request Span Annotation
For monitoring tools such as Cube Cloud proper request span annotation should be
provided in x-request-id
header of a request. Each request id should consist
of two parts: spanId
and requestSequenceId
which define x-request-id
as
whole: ${spanId}-span-${requestSequenceId}
. Values of x-request-id
header
should be unique for each separate request. spanId
should define user
interaction span such us Continue wait
retry cycle and it's value shouldn't
change during one single interaction.
Pagination
Cube supports paginated requests for the /v1/load
endpoint by including
limit
and offset
parameters in the query. For
example, the following query will retrieve rows 101-200 from the Orders
cube:
{
"dimensions": ["Orders.status"],
"measures": ["Orders.count"],
"timeDimensions": [
{
"dimension": "Orders.createdAt",
"dateRange": "last year",
"granularity": "day"
}
],
"limit": 100,
"offset": 100
}