TapTallyTapTally
HomeUser GuideDeploymentArchitectureSourcesAdvanced
GitHub

Using Counters in Node.js

Send counter increments, decrements, and reads from a Node.js application using the TapTally HTTP API.

Overview

Every counter operation in TapTally is a plain HTTP request. This page shows how to fire increments, decrements, and reads from Node.js — no SDK required.

Prerequisites

  • A TapTally instance with a known base URL (e.g. http://localhost:8080)
  • An API key with at least write:counters scope — see Counter API Keys for how to create one
  • A counter that already exists (namespace + key pair) — see Counters

API at a glance

POST /v1/counters/{namespace}/{key}/incr
POST /v1/counters/{namespace}/{key}/decr
GET  /v1/counters/{namespace}/{key}

The request body for increment/decrement is optional. Omit it to step by 1, or pass { "by": N } to step by any integer:

{ "by": 5 }

Every response returns a counter object:

{
  "namespace": "blog",
  "key":       "post-views",
  "value":     42,
  "updated_at": "2025-07-07T10:30:00Z"
}

The X-API-Key header is required on every authenticated request.


Example

Uses the built-in fetch available in Node 18+. No extra dependencies needed.

const BASE_URL = process.env.TAPTALLY_URL ?? "http://localhost:8080";
const API_KEY  = process.env.TAPTALLY_API_KEY;

async function increment(namespace, key, by = 1) {
  const res = await fetch(
    `${BASE_URL}/v1/counters/${namespace}/${key}/incr`,
    {
      method: "POST",
      headers: {
        "X-API-Key":    API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ by }),
    }
  );
  if (!res.ok) throw new Error(`TapTally increment failed: ${res.status}`);
  return res.json();
}

async function decrement(namespace, key, by = 1) {
  const res = await fetch(
    `${BASE_URL}/v1/counters/${namespace}/${key}/decr`,
    {
      method: "POST",
      headers: {
        "X-API-Key":    API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ by }),
    }
  );
  if (!res.ok) throw new Error(`TapTally decrement failed: ${res.status}`);
  return res.json();
}

async function getCounter(namespace, key) {
  const res = await fetch(
    `${BASE_URL}/v1/counters/${namespace}/${key}`,
    { headers: { "X-API-Key": API_KEY } }
  );
  if (!res.ok) throw new Error(`TapTally read failed: ${res.status}`);
  return res.json();
}

// Example usage
const counter = await increment("blog", "post-views");
console.log("New value:", counter.value);

Error reference

Status Meaning
401 Missing or invalid API key
403 Key exists but lacks write:counters scope, or the key is scoped to a different counter
404 Counter (namespace / key pair) does not exist — create it first via the UI or the API
400 Malformed request body

Check res.ok after every request and throw early rather than silently dropping events.


Where to next


Found an issue in the docs? Open an issue on GitHub.

TapTally — You tap, we tally. Free & self-hosted · GPLv3

GitHubDocker HubSupport