Conga Product Documentation

Welcome to the new doc site. Some of your old bookmarks will no longer work. Please use the search bar to find your desired topic.

Securing Webhook Endpoint with HMAC and Basic Authentication

This guide explains how to secure your webhook endpoint when integrating with Conga for Advantage Platform.

Your webhook endpoint must validate Basic Authentication and HMAC signatures to ensure that requests are both authenticated and tamper-proof. When Conga triggers your webhook, it will send requests to the endpoint you configure.

Your implementation must:

  1. Validate Basic Authentication credentials

  2. Validate the HMAC signature

  3. Accept requests in the required structure

  4. Return responses in the required structure

Authentication and Security Requirements

Basic Authentication

Your endpoint must accept an Authorization header in the following format: Authorization: Basic <base64(username:password)>

The username and password should be configured in your appsettings.json file under WebhookSettings.BasicAuth.

Example appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"WebhookSettings": {
"HmacSecretKey": "your-hmac-key",
"BasicAuth": {
"Username": "your-username (ClientId)",
"Password": "your-password (ClientSecret)"
}
}
}
  • Username: The Client ID you received from Conga when creating your webhook.

  • Password: The Client Secret you received from Conga when creating your webhook.

Note: These are the same credentials you provided in the webhook creation request payload. They must also be used by your webhook for validating incoming requests.

HMAC Signature Validation

Requests from Conga include a header:

X-Signature: <base64_hmac_signature>

  • The signature is generated using:

    • Query parameters (for GET)

    • Query + body (for POST)

  • Your endpoint must recompute the HMAC using the secret key in: appsettings.json → WebhookSettings → HmacSecretKey

  • Compare your computed signature with the received one.

    • If they match → process the request.

    • If they don't match → reject the request.

Endpoints

GET /customer

Purpose: Retrieve customer data

Requirements:

  • Validate Basic Auth

  • Validate HMAC signature (query parameters)

Example Response
[
{
"date": "2025-09-17T14:15:22.123Z",
"json": "{ \"id\": 1, \"name\": \"Customer 1\" }"
}
]

POST /customer

Purpose: Process customer data

Requirements:

  • Validate Basic Auth

  • Validate HMAC signature (query + body)

  • Accept request body in the required CustomerRequest structure

Request Body Model:
public class CustomerRequest
{
public string Event { get; set; } = string.Empty;
public string DatasetId { get; set; } = string.Empty;
public string Timestamp { get; set; } = string.Empty;
}
Example Request Body:
{
"event": "DataRequest",
"datasetId": "12345",
"timestamp": "2025-09-17T14:15:22.123Z"
}
Response Model:
public class CustomerData
{
public string Date { get; set; } = string.Empty;
public string Json { get; set; }
}
Example Response:
[
{
"date": "2025-09-17T14:15:22.123Z",
"json": "{ \"id\": 1, \"name\": \"Customer 1\", \"city\": \"City1\" }"
}
]
You can return any JSON payload inside the JSON field as per their own use case.