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.