Learn how to authenticate outbound API calls to Knit using request headers, and how to verify the authenticity of inbound webhook requests from Knit
Overview
This page covers two aspects of authentication in Knit's API:
- API Authentication - how to authorize requests you make to Knit
- Webhook Verification - how to verify that incoming requests are genuinely from Knit
Authentication for APIs
Every request to Knit's API must include the following HTTP headers:
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Your API Key in Bearer format:Bearer <API_KEY> |
X-Knit-Integration-Id | Yes | The integration ID returned by the UI Auth Component, used to identify the source organization and the connected application |
Example request headers:
Authorization: Bearer <YOUR_API_KEY>
X-Knit-Integration-Id: <YOUR_INTEGRATION_ID>Where do I get these?
Your API Key is available on the API Keys page in the Knit dashboard. The Integration ID is returned as a callback when an integration is successful via the Auth flow UI.
Authenticating Webhooks
All POST requests sent by Knit to your server include anX-Knit-Signature key in the header. This signature allows you to verify that the request genuinely originated from Knit and was not tampered with in transit.
How the signature is generated:
Knit computes an HMAC-SHA256 hash of the request payload using your API Key as the secret, then Base64 URL-encodes it (without padding).
To verify a webhook request, follow these steps:
- Extract the raw request body (payload) as a string.
- Compute HMAC-SHA256 of the payload using your
API_KEYas the secret key. - Base64 URL-encode the result (without padding) to get the signature
- Compare the encoded value against the
X-Knit-Signature headerin the request. - If they match, the request is authentic.
import org.apache.commons.codec.binary.Hex
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
val API_KEY = "Your API Key here"
val payload = request.body
val hMacSHA256 = Mac.getInstance("HmacSHA256")
val secretKey = SecretKeySpec(API_KEY..toByteArray(Charsets.UTF_8), "HmacSHA256")
hMacSHA256.init(secretKey)
val encoded = Base64
.getUrlEncoder().withoutPadding()
.encodeToString(hMacSHA256.doFinal(toSign.toByteArray(Charsets.UTF_8)))
val isRequestValid = encoded == request.headers["X-Knit-Signature"]
const base64url = require('base64url');
var crypto = require('crypto');
const key = "Your API Key here"
const encoded = base64url(crypto.createHmac("sha256", key).update(request.body).digest());
isRequestValid = encoded == request.headers["X-Knit-Signature"]
import base64
import hashlib
import hmac
def verify_webhook(data, hmac_header, apikey):
digest = hmac.new(apikey.encode('utf-8'),
data.encode('utf-8'),
digestmod=hashlib.sha256).digest()
computed_hmac = base64.urlsafe_b64encode(digest).rstrip(b"=")
return hmac.compare_digest(computed_hmac, hmac_header.encode('utf-8'))Note : Always use the raw (unparsed) request body for signature verification. Parsing the body before verification can alter whitespace or key ordering and cause valid signatures to fail.

