Authentication

Happa plugins use one secret for incoming webhooks and one API token per installation for outgoing API calls.

Credential types

Credential Format Purpose
Webhook secret whsec_... Verifies signatures on every incoming webhook request.
Client ID hpk_... Public identifier for your plugin. Safe to display and log.
Installation API token hpt_... Authorizes REST API calls for one user who installed your plugin.

Where the credentials come from

When you register a plugin draft in the Developer Portal, Happa immediately creates the plugin's clientId and webhookSecret. Save the secret right away and load it from an environment variable in your backend.

Do not ship secrets in frontend code. Your webhook secret and installation API tokens belong only in your server environment and secure storage.

How installation API tokens are stored

Installation tokens are generated when a user installs your plugin. They are not included in webhook deliveries. Your plugin onboarding flow should send the token to your backend and associate it with the installation.

app.post("/happa/install", express.json(), async (req, res) => {
  const {
    installationId,
    userId,
    apiToken,
    grantedScopes
  } = req.body;

  await db.installations.upsert({
    installationId,
    userId,
    apiToken,
    grantedScopes,
    installedAt: new Date().toISOString()
  });

  res.json({ stored: true });
});

Using the token in API requests

const installation = await db.installations.findByUserId(userId);

const response = await fetch(
  "https://us-central1-happa-1aff4.cloudfunctions.net/pluginApi/profile",
  {
    headers: {
      Authorization: `Bearer ${installation.apiToken}`
    }
  }
);

const profile = await response.json();

Webhook signature verification

const crypto = require("crypto");

function isValidSignature(rawBody, signatureHeader, secret) {
  const expected = "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");

  try {
    return crypto.timingSafeEqual(
      Buffer.from(signatureHeader || "", "utf8"),
      Buffer.from(expected, "utf8")
    );
  } catch {
    return false;
  }
}

Credential rotation

You can rotate plugin credentials from the developer portal. Rotation generates a new clientId and a new webhookSecret immediately. Update your server before you send another test or expect live traffic, because old signatures will stop validating as soon as the secret changes.

Portal sign-in

The Developer Portal uses Firebase Authentication. Sign in there to manage plugin drafts, review credentials, test webhooks, and inspect API and webhook logs.

Security checklist: keep tokens encrypted at rest, rotate secrets when teammates change, and log only the first few characters of tokens when you need operational traces.