umami-api-js
    Preparing search index...

    umami-api-js

    umami-api-js

    release automated testing ko-fi

    A package to interact with the API of self-hosted instances of Umami.

    The documentation for the latest version of this package can be found at any time on umami-api-js.taevas.xyz!

    Please note: It has not been made to work on Umami Cloud (the instance of Umami hosted by its creators) and is therefore not expected to work there.

    Before installing, if using Node.js, check if you're running version 20 or above:

    node -v # displays your version of node.js
    

    Then to install the package, use a command from your package manager:

    npm i umami-api-js # if using npm
    yarn add umami-api-js # if using yarn
    pnpm add umami-api-js # if using pnpm
    bun a umami-api-js # if using bun

    Finally, you will want to create an API object, which you will use for essentially all of your requests. You can do something like that:

    // TypeScript
    import * as umami from "umami-api-js";

    // The API of self-hosted Umami instances authenticates with the credentials of actual accounts
    const api = new umami.API(
    "https://visitors.taevas.xyz/api",
    "<username>",
    "<password>",
    ); // first argument being the API route of a self-hosted Umami instance

    // The website_id is featured in multiple places, like where you'd see the analytics script or the settings interface
    async function displayStats(website_id: string) {
    const now = new Date();
    const sevendaysago = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
    const stats = await api.getWebsiteStats(website_id, {
    startAt: sevendaysago,
    endAt: now,
    timezone: "UTC",
    });

    console.log(
    `This website recently had ${stats.visits} visits from ${stats.visitors} visitors!`,
    );
    }

    displayStats("f196d626-e609-4841-9a80-0dc60f523ed5");

    Your api object has many properties (listed as Accessors in the documentation) which you can modify in order to change its behaviour. There are two ways to do that, the first of which is to do it at any point after you've created your object:

    const api = new umami.API("<api_endpoint>", "<username>", "<password>");
    // Log all requests made by this api object
    api.verbose = "all";
    // Change the amount of seconds it takes for requests to timeout
    api.timeout = 10;

    The other way would be at the same time you're creating your api object, like that:

    // Same as above, in one line as the api object gets created
    const api = new umami.API("<api_endpoint>", "<username>", "<password>", {
    verbose: "all",
    timeout: 10,
    });

    An access_token is required to access the API, and should be valid for 24 hours. When you first create your api object, that token is automatically set before any request is made, so you don't have to worry about that! But how about after those 24 hours?

    Once an access_token has become invalid, the server will no longer respond correctly to requests made with it, instead responding with 401. Thankfully, there are solutions to get and set new access_tokens in a convenient way, so there is no need to create a new api object every day!

    • If you'd like to manually get a new access_token, calling setNewToken() will replace your previous token with a new one
    • Keep the set_token_on_expires option to true if you'd like the object to call it automatically as soon as the token expires
    • By default, the set_token_on_401 option is set to true, which (as its name indicates) will do that upon encountering a 401
    • When that happens, if retry_on_new_token is set to true as it is by default, it will retry the request it has encountered a 401 on, with the new token! (note that loops are prevented, it won't retry or get another token if the same request with the new token gets a 401)

    At any point in time, you can see when the current access_token is set to expire through the expires property of the API.

    Your api object has a configurable behaviour when it comes to handling requests that have failed for certain reasons. It may "retry" a request, meaning not throwing and making the request again as if it hasn't failed under the following circumstances:

    NOTE: retry_maximum_amount must be above 0 for any retry to happen in the first place!

    You can further configure retries through retry_delay and the aforementioned retry_maximum_amount.

    This package's functions can be accessed both through the api object and through namespaces! It essentially means that for convenience's sake, there are two ways to do anything:

    // Obtaining a match, assuming an `api` object already exists and everything from the package is imported as `umami`
    const team_1 = await api.getTeam("<team_id>"); // through the api object
    const team_2 = await umami.Teams.get_TEAMID.call(api, "<team_id>"); // through the namespaces
    // `team_1` and `team_2` are the same, because they're essentially using the same function!

    // The same, but for obtaining the authenticated user
    const me_1 = await api.getMyself();
    const me_2 = await umami.Me.get.call(api);
    // `me_1` and `me_2` are also the same!

    As you may have noticed, when calling the functions through the namespaces, instead of doing something like get(), we instead do get.call() and use the call() method in order to provide a this value; the api object!

    Of course, using the apply() method would also work, so just do things the way you prefer or the way that is more intuitive to you!