Deal Engine Webhook API Reference

This document describes the GraphQL API for managing webhook configurations in Deal Engine.

Deal Engine Webhook API Reference

This document describes the GraphQL API for managing webhook configurations in Deal Engine.

Overview

The Webhook API allows you to:

  • ✅ Configure webhook authentication settings
  • ✅ Choose between HMAC Signature or API Key authentication
  • ✅ Subscribe to event types with custom endpoint URLs
  • ✅ View webhook event delivery history
  • ✅ Manage webhook secrets

Configuration Methods

You can configure webhooks through two methods:

1. Dashboard UI (Recommended for Quick Setup)

  1. Navigate to SettingsWebhooks in the Deal Engine Dashboard
  2. Configure authentication:
    • Select authentication type: Choose HMAC Signature or API Key
    • Set your secret/key: Enter your own or click "Generate" to create one
    • Customize header name (optional): Use a custom header or keep defaults
  3. Add event subscriptions with your endpoint URLs
  4. View delivery history and debug failed webhooks

2. GraphQL API (For Programmatic Control)

Use the API operations described below for automated or programmatic webhook management.

Authentication Types

Deal Engine supports two authentication methods:

TypeBest ForSecurity LevelComplexity
HMACProduction environments⭐⭐⭐ HighModerate
API KeySimple integrations⭐⭐ MediumSimple

HMAC Signature Authentication

  • Each request is uniquely signed using HMAC SHA-256
  • Includes timestamp for replay attack protection
  • Header format: t={timestamp},s={signature}
  • Default header: X-DE-WEBHOOK-SIGNATURE

API Key Authentication

  • Static key sent with every request
  • Simpler to implement
  • Default header: X-API-KEY
💡

Recommendation: Use HMAC for production environments as it provides stronger security guarantees.

Authentication

All webhook API operations require authentication. Admin-level operations (marked with 🔐) require admin privileges.

GraphQL Schema

Types

WebhookAuthType

Authentication method for webhook requests.

enum WebhookAuthType {
    HMAC    # HMAC SHA-256 signature-based authentication
    APIKEY  # API key in header authentication
}
ValueDescription
HMACRequests are signed using HMAC SHA-256. The signature is computed from the timestamp and payload.
APIKEYA static API key is sent in the header for authentication.

WebhookApiConfig

API configuration for webhook authentication.

type WebhookApiConfig {
    headerName: String!      # Name of the authentication header
    secret: String           # Secret key reference (ARN or local)
    type: WebhookAuthType!   # Authentication type (HMAC or APIKEY)
}

WebhookEventItem

A configured webhook event subscription.

type WebhookEventItem {
    type: String!   # Event type identifier (e.g., "refund_request.status_updated")
    name: String!   # Human-readable display name
    url: String!    # Destination URL for webhook delivery
    uuid: String!   # Unique identifier for this subscription
}

WebhookFullConfig

Complete webhook configuration including authentication and subscriptions.

type WebhookFullConfig {
    apiConfig: WebhookApiConfig  # Authentication configuration
    events: [WebhookEventItem!]! # List of event subscriptions
}

WebhookEvent

A webhook event delivery record.

type WebhookEvent {
    pk: String!           # Partition key
    sk: String!           # Sort key
    clientId: Int!        # Client identifier
    timestamp: Float!     # Unix timestamp of the event
    payload: JSON         # Event payload data
    environment: String!  # Environment (production/staging)
    eventId: String!      # Unique event identifier
    webhookId: String!    # Subscription UUID
    eventType: String!    # Event type
    version: String       # API version
    status: String        # Delivery status
    responseCode: Int     # HTTP response code from your endpoint
    responseBody: String  # Response body from your endpoint
    error: String         # Error message if delivery failed
}

WebhookEventTypeDefinition

Available event type definition.

type WebhookEventTypeDefinition {
    type: String!  # Event type identifier
    name: String!  # Human-readable display name
}

Queries

Get Webhook Configuration

Retrieve the full webhook configuration for your account.

query WebhookFullConfig {
    webhookFullConfig {
        apiConfig {
            headerName
            type
        }
        events {
            type
            name
            url
            uuid
        }
    }
}

Response:

{
  "data": {
    "webhookFullConfig": {
      "apiConfig": {
        "headerName": "X-DE-WEBHOOK-SIGNATURE",
        "type": "HMAC"
      },
      "events": [
        {
          "type": "refund_request.status_updated",
          "name": "Quote updated",
          "url": "https://api.yourcompany.com/webhooks/deal-engine",
          "uuid": "550e8400-e29b-41d4-a716-446655440000"
        }
      ]
    }
  }
}

Get Available Event Types

List all available event types you can subscribe to.

query WebhookEventTypes {
    webhookEventTypes {
        type
        name
    }
}

Response:

{
  "data": {
    "webhookEventTypes": [
      {
        "type": "refund_request.status_updated",
        "name": "Quote updated"
      },
      {
        "type": "refund_candidate.status_updated",
        "name": "Request updated"
      }
    ]
  }
}

Possible status values per type

refund_request.status_updated

StatusDescription
NEWA quote was requested and is processing
TICKETS_FROM_PNR_INSERTEDA quote was created by PNR; each ticket from the PNR was inserted for its own quote
REFUND_CANDIDATE_READYThe quote was successfully created (ticket already existed in our DB)
ERROR_PROCESSING_REQUESTThere was an error creating the quote; no refund candidate was created
INSERTED_AND_CREATED_REFUND_CANDIDATE_READYThe quote was successfully created after first inserting the ticket into our DB

refund_candidate.status_updated

StatusDescription
REVIEWThe refund quote is complete and needs revision before it can be processed
REFUNDEDThe refund was successfully executed
ERRORThere was an error processing and fulfilling the refund
READYThe refund quote is ready to be processed

Status values are delivered uppercase, exactly as shown.

When each event fires:

  • refund_request.status_updated — during quoting: REFUND_CANDIDATE_READY when the quote completes, ERROR_PROCESSING_REQUEST when quoting fails.
  • refund_candidate.status_updatedREFUNDED and ERROR fire automatically when fulfillment finishes (both terminal outcomes always notify); READY and REVIEW fire on candidate status transitions.

Event payload (data field)

Default payload for both event types:

{
  "ticket_num": "0651234567890",
  "status": "REFUNDED",
  "pnr": "ABC123"
}
FieldMeaning
ticket_num13-digit ticket number the event refers to
statusNew status (see tables above)
pnrPassenger Name Record, when available

A customized payload can be configured per account instead, selecting any of: ticketNum, status, pnr, requestId (unique event request id), salesforcesId. Contact Deal Engine to enable a custom response shape.

Delivery notes:

  • Events triggered by Deal Engine internal operators are not delivered to client endpoints.
  • Delivery failures are logged and visible in the webhook event history (webhookEvents query below); they do not affect the refund itself.

Get Webhook Event History

Retrieve webhook delivery history with optional filtering.

query WebhookEvents($limit: Int, $nextToken: String, $filters: WebhookEventFilters) {
    webhookEvents(limit: $limit, nextToken: $nextToken, filters: $filters) {
        items {
            eventId
            eventType
            timestamp
            status
            responseCode
            payload
            error
        }
        nextToken
    }
}

Variables:

{
  "limit": 20,
  "filters": {
    "eventType": "refund_request.status_updated",
    "status": "delivered",
    "timestampFrom": 1700000000,
    "timestampTo": 1700100000
  }
}

Filter Options:

FieldTypeDescription
eventTypeStringFilter by event type
statusStringFilter by delivery status
timestampFromFloatStart of timestamp range (Unix)
timestampToFloatEnd of timestamp range (Unix)

Response:

{
  "data": {
    "webhookEvents": {
      "items": [
        {
          "eventId": "evt_abc123",
          "eventType": "refund_request.status_updated",
          "timestamp": 1700050000,
          "status": "delivered",
          "responseCode": 200,
          "payload": { "refundId": "ref_xyz" },
          "error": null
        }
      ],
      "nextToken": "eyJwayI6IkNMSUVOVC..."
    }
  }
}

Get Webhook Secret 🔐

Retrieve the plain-text webhook secret value (admin only).

query WebhookSecret($secretArn: String!) {
    webhookSecret(secretArn: $secretArn)
}
⚠️

Security Note: This query returns the actual secret value. Only use this when you need to configure your webhook verification. Never expose this in logs or client-side code.

Mutations

Update Webhook API Configuration 🔐

Configure authentication settings for your webhooks.

mutation UpdateWebhookApiConfig($apiConfig: WebhookApiConfigInput!) {
    updateWebhookApiConfig(apiConfig: $apiConfig)
}

Variables:

{
  "apiConfig": {
    "headerName": "X-DE-WEBHOOK-SIGNATURE",
    "type": "HMAC",
    "secret": "your-secret-key"
  }
}

Input Fields:

FieldTypeRequiredDescription
headerNameStringYesName of the authentication header (customizable)
typeWebhookAuthTypeYesHMAC or APIKEY
secretStringNoYour secret/API key (auto-generated if not provided)

Default Header Names:

Auth TypeDefault Header
HMACX-DE-WEBHOOK-SIGNATURE
APIKEYX-API-KEY
💡

You can use any custom header name that suits your needs.

Secret Handling Behavior:

  • Not provided + no existing secret: A secure random key is auto-generated (format: whsec_...)
  • Not provided + existing secret: The existing secret is preserved
  • Provided: Your secret is used (stored securely in AWS Secrets Manager)
🔐

Security: Plain-text secrets are automatically encrypted and stored in AWS Secrets Manager. You'll receive a reference (ARN) that can be used to retrieve the actual value.

Response:

{
  "data": {
    "updateWebhookApiConfig": true
  }
}

Roll Webhook Secret 🔐

Generate a new webhook secret. Use this to rotate your secret for security purposes.

mutation RollWebhookSecret {
    rollWebhookSecret
}

Response:

{
  "data": {
    "rollWebhookSecret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
  }
}
⚠️

Important: After rolling the secret, update your webhook verification code immediately. The previous secret will no longer work.

Add Webhook Event Subscription 🔐

Subscribe to a webhook event type.

mutation AddWebhookEvent($event: WebhookEventItemInput!) {
    addWebhookEvent(event: $event)
}

Variables:

{
  "event": {
    "type": "refund_request.status_updated",
    "url": "https://api.yourcompany.com/webhooks/deal-engine"
  }
}

Input Fields:

FieldTypeRequiredDescription
typeStringYesEvent type to subscribe to
urlStringYesHTTPS endpoint URL for delivery
uuidStringNoUUID for updating existing subscription

URL Requirements:

  • Must be a valid URL format
  • Should be accessible from the internet
  • HTTPS recommended for production

Response:

{
  "data": {
    "addWebhookEvent": true
  }
}

Delete Webhook Event Subscription 🔐

Remove a webhook event subscription.

mutation DeleteWebhookEvent($uuid: String!) {
    deleteWebhookEvent(uuid: $uuid)
}

Variables:

{
  "uuid": "550e8400-e29b-41d4-a716-446655440000"
}

Response:

{
  "data": {
    "deleteWebhookEvent": true
  }
}

Complete Setup Examples

Setup with HMAC Signature (Recommended)

Step 1: Configure HMAC Authentication

mutation UpdateWebhookApiConfig {
    updateWebhookApiConfig(apiConfig: {
        headerName: "X-DE-WEBHOOK-SIGNATURE"  # Or use your custom header name
        type: HMAC
        # secret: "your-custom-secret"  # Optional - omit to auto-generate
    })
}

Step 2: Get Your Secret

query WebhookFullConfig {
    webhookFullConfig {
        apiConfig {
            headerName
            type
            secret
        }
    }
}

Use the returned secret ARN to retrieve the actual secret value:

query WebhookSecret($secretArn: String!) {
    webhookSecret(secretArn: $secretArn)
}

Step 3: Subscribe to Events

mutation AddWebhookEvent {
    addWebhookEvent(event: {
        type: "refund_request.status_updated"
        url: "https://api.yourcompany.com/webhooks/quotes"
    })
}

Setup with API Key

Step 1: Configure API Key Authentication

mutation UpdateWebhookApiConfig {
    updateWebhookApiConfig(apiConfig: {
        headerName: "X-API-KEY"  # Or use your custom header name
        type: APIKEY
        secret: "your-api-key"  # Provide your key or omit to auto-generate
    })
}

Step 2: Get Your API Key

query WebhookFullConfig {
    webhookFullConfig {
        apiConfig {
            headerName
            type
            secret
        }
    }
}

If the secret is stored in AWS Secrets Manager, retrieve the actual value:

query WebhookSecret($secretArn: String!) {
    webhookSecret(secretArn: $secretArn)
}

Step 3: Subscribe to Events

mutation AddWebhookEvent {
    addWebhookEvent(event: {
        type: "refund_request.status_updated"
        url: "https://api.yourcompany.com/webhooks/deal-engine"
    })
}

Subscribe to All Event Types

mutation AddWebhookEvent {
    addWebhookEvent(event: {
        type: "refund_request.status_updated"
        url: "https://api.yourcompany.com/webhooks/quotes"
    })
}

mutation AddWebhookEvent {
    addWebhookEvent(event: {
        type: "refund_candidate.status_updated"
        url: "https://api.yourcompany.com/webhooks/requests"
    })
}

Verify Your Configuration

query WebhookFullConfig {
    webhookFullConfig {
        apiConfig {
            headerName
            type
        }
        events {
            type
            name
            url
            uuid
        }
    }
}

Error Handling

Common Errors

ErrorCauseSolution
Invalid URL formatURL doesn't match expected formatUse a valid URL starting with http:// or https://
Failed to update webhook API configServer error during config updateRetry the operation
Failed to fetch webhook secretInvalid secret ARNVerify the secret ARN exists

GraphQL Error Response Format

{
  "errors": [
    {
      "message": "Invalid URL format",
      "extensions": {
        "code": "BAD_REQUEST"
      }
    }
  ],
  "data": null
}

Rate Limits

The webhook API is subject to the same rate limits as other Deal Engine APIs. Contact support if you need higher limits.

Best Practices

  1. Use HMAC Authentication: HMAC provides better security than API keys as each request is uniquely signed
  2. Rotate Secrets Regularly: Use rollWebhookSecret periodically for security
  3. Monitor Delivery Status: Regularly check webhookEvents for failed deliveries
  4. Use Descriptive URLs: Include identifiers in your webhook URLs for easier debugging
  5. Test Before Production: Configure webhooks in staging environment first

Support

For webhook-related issues:

  1. Check the webhook events log using the webhookEvents query
  2. Verify your endpoint is accessible and returns 2xx status codes
  3. Review error messages in the delivery history
  4. Contact Deal Engine support with relevant eventId values

Did this page help you?