Auth Setup
Configure your HuskyVoice AI environment by accessing your credentials and setting up communication channels. All settings mentioned below can be managed on the Integrations page of your Dashboard.
- API Keys
- Inbound Webhooks
- Outbound (Webhooks)
API Key Setup
API keys grant programmatic access to HuskyVoice services.
- Go to Integrations > API Key tab.
- Click Generate New Key.
- Copy the secret key immediately — it will not be shown again.
Usage:
Pass the key in the x-api-key header:
x-api-key: YOUR_API_KEY
Inbound Webhook URLs
Trigger AI actions (creating or cancelling calls) from third-party tools like Zapier or custom CRM workflows.
- Go to Integrations > Inbound Webhooks tab.
- Copy your unique Inbound URL.
- Use this URL as the destination for your POST requests.
Example Endpoint:
https://api.huskyvoice.ai/v1/hooks/{YOUR_SECRET_TOKEN}
Outbound Webhook Events
Outbound Webhooks allow HuskyVoice to send real-time data back to your server.
- Go to Integrations > Webhook (Outbound) tab.
- Enter your Endpoint URL.
- Select events (e.g.,
call.completed). - Copy the Webhook Secret for verification.
Signature Verification
Every outbound delivery includes two headers:
| Header | Description |
|---|---|
X-Webhook-Timestamp | Unix timestamp (seconds) when the payload was signed |
X-Webhook-Signature | Signature in the format v1=<base64-encoded HMAC-SHA256> |
The signature is computed as HMAC-SHA256(secret, "{timestamp}.{rawBody}"), encoded as base64 (not hex), and prefixed with v1=.
- cURL
- Python
- Node.js
- n8n
# Generate a signed test delivery to verify your endpoint
SECRET="YOUR_WEBHOOK_SECRET"
TIMESTAMP=$(date +%s)
PAYLOAD='{"event_id":"evt_123","event_type":"call.completed"}'
SIG="v1=$(printf '%s.%s' "$TIMESTAMP" "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64)"
curl -X POST https://your-server.com/webhook \
-H "Content-Type: application/json" \
-H "X-Webhook-Timestamp: $TIMESTAMP" \
-H "X-Webhook-Signature: $SIG" \
-d "$PAYLOAD"
import hmac
import hashlib
import base64
def verify_signature(secret: str, timestamp: str, raw_body: bytes, signature: str) -> bool:
message = f"{timestamp}.".encode() + raw_body
expected = base64.b64encode(
hmac.new(secret.encode(), message, hashlib.sha256).digest()
).decode()
return hmac.compare_digest(f"v1={expected}", signature)
const crypto = require("crypto");
function verifySignature(secret, timestamp, rawBody, signature) {
const message = `${timestamp}.${rawBody}`;
const expected = crypto
.createHmac("sha256", secret)
.update(message)
.digest("base64");
return crypto.timingSafeEqual(
Buffer.from(`v1=${expected}`),
Buffer.from(signature)
);
}
// n8n Code node — place after your Webhook trigger node
const crypto = require("crypto");
const secret = "YOUR_WEBHOOK_SECRET";
const timestamp = $input.first().json.headers["x-webhook-timestamp"];
const receivedSig = $input.first().json.headers["x-webhook-signature"];
const rawBody = JSON.stringify($input.first().json.body);
const expectedSig = "v1=" + crypto
.createHmac("sha256", secret)
.update(`${timestamp}.${rawBody}`)
.digest("base64");
const isValid = crypto.timingSafeEqual(
Buffer.from(receivedSig),
Buffer.from(expectedSig)
);
if (!isValid) {
throw new Error("Invalid webhook signature — request rejected");
}
return $input.all();
Technical Configuration Table
| Integration Point | Authentication Method | Primary Use Case |
|---|---|---|
| Call API | x-api-key Header | Complex backend logic & scheduling. |
| Inbound Webhooks | Unique URL ID | No-code tools & simple CRM triggers. |
| Outbound Webhooks | X-Webhook-Signature (HMAC-SHA256) | Real-time status sync & outcome logging. |
Never share your API keys or Webhook secrets in public repositories or client-side code. Always use environment variables on your server.