Configure GCP Dialogflow CX Webhooks

The gcp:diagflow/cxWebhook:CxWebhook resource, part of the Pulumi GCP provider, defines webhooks that connect Dialogflow CX agents to external APIs for dynamic responses, validation, and backend actions. This guide focuses on three capabilities: standard webhook format with OAuth, flexible webhook format with custom requests, and Service Directory routing for private services.

Webhooks belong to Dialogflow CX agents and reference Secret Manager secrets for authentication. The examples are intentionally small. Combine them with your own agents, secrets, and backend services.

Connect to external APIs with standard webhook format

Dialogflow CX agents call external APIs to validate input, fetch data, or trigger backend actions. Standard webhooks provide structured request/response format with built-in authentication.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const agent = new gcp.diagflow.CxAgent("agent", {
    displayName: "dialogflowcx-agent",
    location: "global",
    defaultLanguageCode: "en",
    supportedLanguageCodes: [
        "it",
        "de",
        "es",
    ],
    timeZone: "America/New_York",
    description: "Example description.",
    avatarUri: "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enableStackdriverLogging: true,
    enableSpellCorrection: true,
    speechToTextSettings: {
        enableSpeechAdaptation: true,
    },
});
const standardWebhook = new gcp.diagflow.CxWebhook("standard_webhook", {
    parent: agent.id,
    displayName: "MyFlow",
    genericWebService: {
        allowedCaCerts: ["BQA="],
        uri: "https://example.com",
        requestHeaders: {
            "example-key": "example-value",
        },
        webhookType: "STANDARD",
        oauthConfig: {
            clientId: "example-client-id",
            secretVersionForClientSecret: "projects/example-proj/secrets/example-secret/versions/example-version",
            tokenEndpoint: "https://example.com",
            scopes: ["example-scope"],
        },
        serviceAgentAuth: "NONE",
        secretVersionForUsernamePassword: "projects/example-proj/secrets/example-secret/versions/example-version",
        secretVersionsForRequestHeaders: [
            {
                key: "example-key-1",
                secretVersion: "projects/example-proj/secrets/example-secret/versions/example-version",
            },
            {
                key: "example-key-2",
                secretVersion: "projects/example-proj/secrets/example-secret/versions/example-version-2",
            },
        ],
    },
});
import pulumi
import pulumi_gcp as gcp

agent = gcp.diagflow.CxAgent("agent",
    display_name="dialogflowcx-agent",
    location="global",
    default_language_code="en",
    supported_language_codes=[
        "it",
        "de",
        "es",
    ],
    time_zone="America/New_York",
    description="Example description.",
    avatar_uri="https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enable_stackdriver_logging=True,
    enable_spell_correction=True,
    speech_to_text_settings={
        "enable_speech_adaptation": True,
    })
standard_webhook = gcp.diagflow.CxWebhook("standard_webhook",
    parent=agent.id,
    display_name="MyFlow",
    generic_web_service={
        "allowed_ca_certs": ["BQA="],
        "uri": "https://example.com",
        "request_headers": {
            "example-key": "example-value",
        },
        "webhook_type": "STANDARD",
        "oauth_config": {
            "client_id": "example-client-id",
            "secret_version_for_client_secret": "projects/example-proj/secrets/example-secret/versions/example-version",
            "token_endpoint": "https://example.com",
            "scopes": ["example-scope"],
        },
        "service_agent_auth": "NONE",
        "secret_version_for_username_password": "projects/example-proj/secrets/example-secret/versions/example-version",
        "secret_versions_for_request_headers": [
            {
                "key": "example-key-1",
                "secret_version": "projects/example-proj/secrets/example-secret/versions/example-version",
            },
            {
                "key": "example-key-2",
                "secret_version": "projects/example-proj/secrets/example-secret/versions/example-version-2",
            },
        ],
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/diagflow"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		agent, err := diagflow.NewCxAgent(ctx, "agent", &diagflow.CxAgentArgs{
			DisplayName:         pulumi.String("dialogflowcx-agent"),
			Location:            pulumi.String("global"),
			DefaultLanguageCode: pulumi.String("en"),
			SupportedLanguageCodes: pulumi.StringArray{
				pulumi.String("it"),
				pulumi.String("de"),
				pulumi.String("es"),
			},
			TimeZone:                 pulumi.String("America/New_York"),
			Description:              pulumi.String("Example description."),
			AvatarUri:                pulumi.String("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png"),
			EnableStackdriverLogging: pulumi.Bool(true),
			EnableSpellCorrection:    pulumi.Bool(true),
			SpeechToTextSettings: &diagflow.CxAgentSpeechToTextSettingsArgs{
				EnableSpeechAdaptation: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		_, err = diagflow.NewCxWebhook(ctx, "standard_webhook", &diagflow.CxWebhookArgs{
			Parent:      agent.ID(),
			DisplayName: pulumi.String("MyFlow"),
			GenericWebService: &diagflow.CxWebhookGenericWebServiceArgs{
				AllowedCaCerts: pulumi.StringArray{
					pulumi.String("BQA="),
				},
				Uri: pulumi.String("https://example.com"),
				RequestHeaders: pulumi.StringMap{
					"example-key": pulumi.String("example-value"),
				},
				WebhookType: pulumi.String("STANDARD"),
				OauthConfig: &diagflow.CxWebhookGenericWebServiceOauthConfigArgs{
					ClientId:                     pulumi.String("example-client-id"),
					SecretVersionForClientSecret: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
					TokenEndpoint:                pulumi.String("https://example.com"),
					Scopes: pulumi.StringArray{
						pulumi.String("example-scope"),
					},
				},
				ServiceAgentAuth:                 pulumi.String("NONE"),
				SecretVersionForUsernamePassword: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
				SecretVersionsForRequestHeaders: diagflow.CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArray{
					&diagflow.CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs{
						Key:           pulumi.String("example-key-1"),
						SecretVersion: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
					},
					&diagflow.CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs{
						Key:           pulumi.String("example-key-2"),
						SecretVersion: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version-2"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var agent = new Gcp.Diagflow.CxAgent("agent", new()
    {
        DisplayName = "dialogflowcx-agent",
        Location = "global",
        DefaultLanguageCode = "en",
        SupportedLanguageCodes = new[]
        {
            "it",
            "de",
            "es",
        },
        TimeZone = "America/New_York",
        Description = "Example description.",
        AvatarUri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
        EnableStackdriverLogging = true,
        EnableSpellCorrection = true,
        SpeechToTextSettings = new Gcp.Diagflow.Inputs.CxAgentSpeechToTextSettingsArgs
        {
            EnableSpeechAdaptation = true,
        },
    });

    var standardWebhook = new Gcp.Diagflow.CxWebhook("standard_webhook", new()
    {
        Parent = agent.Id,
        DisplayName = "MyFlow",
        GenericWebService = new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceArgs
        {
            AllowedCaCerts = new[]
            {
                "BQA=",
            },
            Uri = "https://example.com",
            RequestHeaders = 
            {
                { "example-key", "example-value" },
            },
            WebhookType = "STANDARD",
            OauthConfig = new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceOauthConfigArgs
            {
                ClientId = "example-client-id",
                SecretVersionForClientSecret = "projects/example-proj/secrets/example-secret/versions/example-version",
                TokenEndpoint = "https://example.com",
                Scopes = new[]
                {
                    "example-scope",
                },
            },
            ServiceAgentAuth = "NONE",
            SecretVersionForUsernamePassword = "projects/example-proj/secrets/example-secret/versions/example-version",
            SecretVersionsForRequestHeaders = new[]
            {
                new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs
                {
                    Key = "example-key-1",
                    SecretVersion = "projects/example-proj/secrets/example-secret/versions/example-version",
                },
                new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs
                {
                    Key = "example-key-2",
                    SecretVersion = "projects/example-proj/secrets/example-secret/versions/example-version-2",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.diagflow.CxAgent;
import com.pulumi.gcp.diagflow.CxAgentArgs;
import com.pulumi.gcp.diagflow.inputs.CxAgentSpeechToTextSettingsArgs;
import com.pulumi.gcp.diagflow.CxWebhook;
import com.pulumi.gcp.diagflow.CxWebhookArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookGenericWebServiceArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookGenericWebServiceOauthConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var agent = new CxAgent("agent", CxAgentArgs.builder()
            .displayName("dialogflowcx-agent")
            .location("global")
            .defaultLanguageCode("en")
            .supportedLanguageCodes(            
                "it",
                "de",
                "es")
            .timeZone("America/New_York")
            .description("Example description.")
            .avatarUri("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png")
            .enableStackdriverLogging(true)
            .enableSpellCorrection(true)
            .speechToTextSettings(CxAgentSpeechToTextSettingsArgs.builder()
                .enableSpeechAdaptation(true)
                .build())
            .build());

        var standardWebhook = new CxWebhook("standardWebhook", CxWebhookArgs.builder()
            .parent(agent.id())
            .displayName("MyFlow")
            .genericWebService(CxWebhookGenericWebServiceArgs.builder()
                .allowedCaCerts("BQA=")
                .uri("https://example.com")
                .requestHeaders(Map.of("example-key", "example-value"))
                .webhookType("STANDARD")
                .oauthConfig(CxWebhookGenericWebServiceOauthConfigArgs.builder()
                    .clientId("example-client-id")
                    .secretVersionForClientSecret("projects/example-proj/secrets/example-secret/versions/example-version")
                    .tokenEndpoint("https://example.com")
                    .scopes("example-scope")
                    .build())
                .serviceAgentAuth("NONE")
                .secretVersionForUsernamePassword("projects/example-proj/secrets/example-secret/versions/example-version")
                .secretVersionsForRequestHeaders(                
                    CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs.builder()
                        .key("example-key-1")
                        .secretVersion("projects/example-proj/secrets/example-secret/versions/example-version")
                        .build(),
                    CxWebhookGenericWebServiceSecretVersionsForRequestHeaderArgs.builder()
                        .key("example-key-2")
                        .secretVersion("projects/example-proj/secrets/example-secret/versions/example-version-2")
                        .build())
                .build())
            .build());

    }
}
resources:
  agent:
    type: gcp:diagflow:CxAgent
    properties:
      displayName: dialogflowcx-agent
      location: global
      defaultLanguageCode: en
      supportedLanguageCodes:
        - it
        - de
        - es
      timeZone: America/New_York
      description: Example description.
      avatarUri: https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png
      enableStackdriverLogging: true
      enableSpellCorrection: true
      speechToTextSettings:
        enableSpeechAdaptation: true
  standardWebhook:
    type: gcp:diagflow:CxWebhook
    name: standard_webhook
    properties:
      parent: ${agent.id}
      displayName: MyFlow
      genericWebService:
        allowedCaCerts:
          - BQA=
        uri: https://example.com
        requestHeaders:
          example-key: example-value
        webhookType: STANDARD
        oauthConfig:
          clientId: example-client-id
          secretVersionForClientSecret: projects/example-proj/secrets/example-secret/versions/example-version
          tokenEndpoint: https://example.com
          scopes:
            - example-scope
        serviceAgentAuth: NONE
        secretVersionForUsernamePassword: projects/example-proj/secrets/example-secret/versions/example-version
        secretVersionsForRequestHeaders:
          - key: example-key-1
            secretVersion: projects/example-proj/secrets/example-secret/versions/example-version
          - key: example-key-2
            secretVersion: projects/example-proj/secrets/example-secret/versions/example-version-2

The genericWebService property defines the webhook endpoint. The uri points to your API, while webhookType set to “STANDARD” uses Dialogflow’s structured request format. The oauthConfig block handles OAuth authentication: clientId identifies your application, secretVersionForClientSecret references a Secret Manager secret containing your client secret, and tokenEndpoint specifies where to obtain access tokens. Custom requestHeaders pass additional metadata to your API.

Customize request format with flexible webhooks

Some backend services require custom request formats that don’t match Dialogflow’s standard structure. Flexible webhooks let you control HTTP method, body, and parameter mapping.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const agent = new gcp.diagflow.CxAgent("agent", {
    displayName: "dialogflowcx-agent",
    location: "global",
    defaultLanguageCode: "en",
    supportedLanguageCodes: [
        "it",
        "de",
        "es",
    ],
    timeZone: "America/New_York",
    description: "Example description.",
    avatarUri: "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enableStackdriverLogging: true,
    enableSpellCorrection: true,
    speechToTextSettings: {
        enableSpeechAdaptation: true,
    },
});
const flexibleWebhook = new gcp.diagflow.CxWebhook("flexible_webhook", {
    parent: agent.id,
    displayName: "MyFlow",
    genericWebService: {
        uri: "https://example.com",
        requestHeaders: {
            "example-key": "example-value",
        },
        webhookType: "FLEXIBLE",
        oauthConfig: {
            clientId: "example-client-id",
            clientSecret: "projects/example-proj/secrets/example-secret/versions/example-version",
            tokenEndpoint: "https://example.com",
        },
        serviceAgentAuth: "NONE",
        httpMethod: "POST",
        requestBody: "{\"example-key\": \"example-value\"}",
        parameterMapping: {
            "example-parameter": "examplePath",
        },
    },
});
import pulumi
import pulumi_gcp as gcp

agent = gcp.diagflow.CxAgent("agent",
    display_name="dialogflowcx-agent",
    location="global",
    default_language_code="en",
    supported_language_codes=[
        "it",
        "de",
        "es",
    ],
    time_zone="America/New_York",
    description="Example description.",
    avatar_uri="https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enable_stackdriver_logging=True,
    enable_spell_correction=True,
    speech_to_text_settings={
        "enable_speech_adaptation": True,
    })
flexible_webhook = gcp.diagflow.CxWebhook("flexible_webhook",
    parent=agent.id,
    display_name="MyFlow",
    generic_web_service={
        "uri": "https://example.com",
        "request_headers": {
            "example-key": "example-value",
        },
        "webhook_type": "FLEXIBLE",
        "oauth_config": {
            "client_id": "example-client-id",
            "client_secret": "projects/example-proj/secrets/example-secret/versions/example-version",
            "token_endpoint": "https://example.com",
        },
        "service_agent_auth": "NONE",
        "http_method": "POST",
        "request_body": "{\"example-key\": \"example-value\"}",
        "parameter_mapping": {
            "example-parameter": "examplePath",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/diagflow"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		agent, err := diagflow.NewCxAgent(ctx, "agent", &diagflow.CxAgentArgs{
			DisplayName:         pulumi.String("dialogflowcx-agent"),
			Location:            pulumi.String("global"),
			DefaultLanguageCode: pulumi.String("en"),
			SupportedLanguageCodes: pulumi.StringArray{
				pulumi.String("it"),
				pulumi.String("de"),
				pulumi.String("es"),
			},
			TimeZone:                 pulumi.String("America/New_York"),
			Description:              pulumi.String("Example description."),
			AvatarUri:                pulumi.String("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png"),
			EnableStackdriverLogging: pulumi.Bool(true),
			EnableSpellCorrection:    pulumi.Bool(true),
			SpeechToTextSettings: &diagflow.CxAgentSpeechToTextSettingsArgs{
				EnableSpeechAdaptation: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		_, err = diagflow.NewCxWebhook(ctx, "flexible_webhook", &diagflow.CxWebhookArgs{
			Parent:      agent.ID(),
			DisplayName: pulumi.String("MyFlow"),
			GenericWebService: &diagflow.CxWebhookGenericWebServiceArgs{
				Uri: pulumi.String("https://example.com"),
				RequestHeaders: pulumi.StringMap{
					"example-key": pulumi.String("example-value"),
				},
				WebhookType: pulumi.String("FLEXIBLE"),
				OauthConfig: &diagflow.CxWebhookGenericWebServiceOauthConfigArgs{
					ClientId:      pulumi.String("example-client-id"),
					ClientSecret:  pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
					TokenEndpoint: pulumi.String("https://example.com"),
				},
				ServiceAgentAuth: pulumi.String("NONE"),
				HttpMethod:       pulumi.String("POST"),
				RequestBody:      pulumi.String("{\"example-key\": \"example-value\"}"),
				ParameterMapping: pulumi.StringMap{
					"example-parameter": pulumi.String("examplePath"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var agent = new Gcp.Diagflow.CxAgent("agent", new()
    {
        DisplayName = "dialogflowcx-agent",
        Location = "global",
        DefaultLanguageCode = "en",
        SupportedLanguageCodes = new[]
        {
            "it",
            "de",
            "es",
        },
        TimeZone = "America/New_York",
        Description = "Example description.",
        AvatarUri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
        EnableStackdriverLogging = true,
        EnableSpellCorrection = true,
        SpeechToTextSettings = new Gcp.Diagflow.Inputs.CxAgentSpeechToTextSettingsArgs
        {
            EnableSpeechAdaptation = true,
        },
    });

    var flexibleWebhook = new Gcp.Diagflow.CxWebhook("flexible_webhook", new()
    {
        Parent = agent.Id,
        DisplayName = "MyFlow",
        GenericWebService = new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceArgs
        {
            Uri = "https://example.com",
            RequestHeaders = 
            {
                { "example-key", "example-value" },
            },
            WebhookType = "FLEXIBLE",
            OauthConfig = new Gcp.Diagflow.Inputs.CxWebhookGenericWebServiceOauthConfigArgs
            {
                ClientId = "example-client-id",
                ClientSecret = "projects/example-proj/secrets/example-secret/versions/example-version",
                TokenEndpoint = "https://example.com",
            },
            ServiceAgentAuth = "NONE",
            HttpMethod = "POST",
            RequestBody = "{\"example-key\": \"example-value\"}",
            ParameterMapping = 
            {
                { "example-parameter", "examplePath" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.diagflow.CxAgent;
import com.pulumi.gcp.diagflow.CxAgentArgs;
import com.pulumi.gcp.diagflow.inputs.CxAgentSpeechToTextSettingsArgs;
import com.pulumi.gcp.diagflow.CxWebhook;
import com.pulumi.gcp.diagflow.CxWebhookArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookGenericWebServiceArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookGenericWebServiceOauthConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var agent = new CxAgent("agent", CxAgentArgs.builder()
            .displayName("dialogflowcx-agent")
            .location("global")
            .defaultLanguageCode("en")
            .supportedLanguageCodes(            
                "it",
                "de",
                "es")
            .timeZone("America/New_York")
            .description("Example description.")
            .avatarUri("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png")
            .enableStackdriverLogging(true)
            .enableSpellCorrection(true)
            .speechToTextSettings(CxAgentSpeechToTextSettingsArgs.builder()
                .enableSpeechAdaptation(true)
                .build())
            .build());

        var flexibleWebhook = new CxWebhook("flexibleWebhook", CxWebhookArgs.builder()
            .parent(agent.id())
            .displayName("MyFlow")
            .genericWebService(CxWebhookGenericWebServiceArgs.builder()
                .uri("https://example.com")
                .requestHeaders(Map.of("example-key", "example-value"))
                .webhookType("FLEXIBLE")
                .oauthConfig(CxWebhookGenericWebServiceOauthConfigArgs.builder()
                    .clientId("example-client-id")
                    .clientSecret("projects/example-proj/secrets/example-secret/versions/example-version")
                    .tokenEndpoint("https://example.com")
                    .build())
                .serviceAgentAuth("NONE")
                .httpMethod("POST")
                .requestBody("{\"example-key\": \"example-value\"}")
                .parameterMapping(Map.of("example-parameter", "examplePath"))
                .build())
            .build());

    }
}
resources:
  agent:
    type: gcp:diagflow:CxAgent
    properties:
      displayName: dialogflowcx-agent
      location: global
      defaultLanguageCode: en
      supportedLanguageCodes:
        - it
        - de
        - es
      timeZone: America/New_York
      description: Example description.
      avatarUri: https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png
      enableStackdriverLogging: true
      enableSpellCorrection: true
      speechToTextSettings:
        enableSpeechAdaptation: true
  flexibleWebhook:
    type: gcp:diagflow:CxWebhook
    name: flexible_webhook
    properties:
      parent: ${agent.id}
      displayName: MyFlow
      genericWebService:
        uri: https://example.com
        requestHeaders:
          example-key: example-value
        webhookType: FLEXIBLE
        oauthConfig:
          clientId: example-client-id
          clientSecret: projects/example-proj/secrets/example-secret/versions/example-version
          tokenEndpoint: https://example.com
        serviceAgentAuth: NONE
        httpMethod: POST
        requestBody: '{"example-key": "example-value"}'
        parameterMapping:
          example-parameter: examplePath

Setting webhookType to “FLEXIBLE” enables custom formatting. The httpMethod property specifies the HTTP verb (POST, GET, etc.), while requestBody defines the exact JSON payload sent to your API. The parameterMapping object extracts values from Dialogflow’s session parameters and maps them to your API’s expected structure. This gives you full control over request format when integrating with APIs that have specific requirements.

Route through Service Directory for private services

Backend services in private networks need Service Directory integration to avoid public exposure. Service Directory provides service discovery and routing for internal services.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const agent = new gcp.diagflow.CxAgent("agent", {
    displayName: "dialogflowcx-agent",
    location: "us-central1",
    defaultLanguageCode: "en",
    supportedLanguageCodes: [
        "it",
        "de",
        "es",
    ],
    timeZone: "America/New_York",
    description: "Example description.",
    avatarUri: "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enableStackdriverLogging: true,
    enableSpellCorrection: true,
    speechToTextSettings: {
        enableSpeechAdaptation: true,
    },
});
const standardWebhook = new gcp.diagflow.CxWebhook("standard_webhook", {
    parent: agent.id,
    displayName: "MyFlow",
    serviceDirectory: {
        service: "projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service",
        genericWebService: {
            allowedCaCerts: ["BQA="],
            uri: "https://example.com",
            requestHeaders: {
                "example-key": "example-value",
            },
            webhookType: "STANDARD",
            oauthConfig: {
                clientId: "example-client-id",
                secretVersionForClientSecret: "projects/example-proj/secrets/example-secret/versions/example-version",
                tokenEndpoint: "https://example.com",
                scopes: ["example-scope"],
            },
            serviceAgentAuth: "NONE",
            secretVersionForUsernamePassword: "projects/example-proj/secrets/example-secret/versions/example-version",
            secretVersionsForRequestHeaders: [
                {
                    key: "example-key-1",
                    secretVersion: "projects/example-proj/secrets/example-secret/versions/example-version",
                },
                {
                    key: "example-key-2",
                    secretVersion: "projects/example-proj/secrets/example-secret/versions/example-version-2",
                },
            ],
        },
    },
});
import pulumi
import pulumi_gcp as gcp

agent = gcp.diagflow.CxAgent("agent",
    display_name="dialogflowcx-agent",
    location="us-central1",
    default_language_code="en",
    supported_language_codes=[
        "it",
        "de",
        "es",
    ],
    time_zone="America/New_York",
    description="Example description.",
    avatar_uri="https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
    enable_stackdriver_logging=True,
    enable_spell_correction=True,
    speech_to_text_settings={
        "enable_speech_adaptation": True,
    })
standard_webhook = gcp.diagflow.CxWebhook("standard_webhook",
    parent=agent.id,
    display_name="MyFlow",
    service_directory={
        "service": "projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service",
        "generic_web_service": {
            "allowed_ca_certs": ["BQA="],
            "uri": "https://example.com",
            "request_headers": {
                "example-key": "example-value",
            },
            "webhook_type": "STANDARD",
            "oauth_config": {
                "client_id": "example-client-id",
                "secret_version_for_client_secret": "projects/example-proj/secrets/example-secret/versions/example-version",
                "token_endpoint": "https://example.com",
                "scopes": ["example-scope"],
            },
            "service_agent_auth": "NONE",
            "secret_version_for_username_password": "projects/example-proj/secrets/example-secret/versions/example-version",
            "secret_versions_for_request_headers": [
                {
                    "key": "example-key-1",
                    "secret_version": "projects/example-proj/secrets/example-secret/versions/example-version",
                },
                {
                    "key": "example-key-2",
                    "secret_version": "projects/example-proj/secrets/example-secret/versions/example-version-2",
                },
            ],
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/diagflow"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		agent, err := diagflow.NewCxAgent(ctx, "agent", &diagflow.CxAgentArgs{
			DisplayName:         pulumi.String("dialogflowcx-agent"),
			Location:            pulumi.String("us-central1"),
			DefaultLanguageCode: pulumi.String("en"),
			SupportedLanguageCodes: pulumi.StringArray{
				pulumi.String("it"),
				pulumi.String("de"),
				pulumi.String("es"),
			},
			TimeZone:                 pulumi.String("America/New_York"),
			Description:              pulumi.String("Example description."),
			AvatarUri:                pulumi.String("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png"),
			EnableStackdriverLogging: pulumi.Bool(true),
			EnableSpellCorrection:    pulumi.Bool(true),
			SpeechToTextSettings: &diagflow.CxAgentSpeechToTextSettingsArgs{
				EnableSpeechAdaptation: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		_, err = diagflow.NewCxWebhook(ctx, "standard_webhook", &diagflow.CxWebhookArgs{
			Parent:      agent.ID(),
			DisplayName: pulumi.String("MyFlow"),
			ServiceDirectory: &diagflow.CxWebhookServiceDirectoryArgs{
				Service: pulumi.String("projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service"),
				GenericWebService: &diagflow.CxWebhookServiceDirectoryGenericWebServiceArgs{
					AllowedCaCerts: pulumi.StringArray{
						pulumi.String("BQA="),
					},
					Uri: pulumi.String("https://example.com"),
					RequestHeaders: pulumi.StringMap{
						"example-key": pulumi.String("example-value"),
					},
					WebhookType: pulumi.String("STANDARD"),
					OauthConfig: &diagflow.CxWebhookServiceDirectoryGenericWebServiceOauthConfigArgs{
						ClientId:                     pulumi.String("example-client-id"),
						SecretVersionForClientSecret: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
						TokenEndpoint:                pulumi.String("https://example.com"),
						Scopes: pulumi.StringArray{
							pulumi.String("example-scope"),
						},
					},
					ServiceAgentAuth:                 pulumi.String("NONE"),
					SecretVersionForUsernamePassword: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
					SecretVersionsForRequestHeaders: diagflow.CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArray{
						&diagflow.CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs{
							Key:           pulumi.String("example-key-1"),
							SecretVersion: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version"),
						},
						&diagflow.CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs{
							Key:           pulumi.String("example-key-2"),
							SecretVersion: pulumi.String("projects/example-proj/secrets/example-secret/versions/example-version-2"),
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var agent = new Gcp.Diagflow.CxAgent("agent", new()
    {
        DisplayName = "dialogflowcx-agent",
        Location = "us-central1",
        DefaultLanguageCode = "en",
        SupportedLanguageCodes = new[]
        {
            "it",
            "de",
            "es",
        },
        TimeZone = "America/New_York",
        Description = "Example description.",
        AvatarUri = "https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png",
        EnableStackdriverLogging = true,
        EnableSpellCorrection = true,
        SpeechToTextSettings = new Gcp.Diagflow.Inputs.CxAgentSpeechToTextSettingsArgs
        {
            EnableSpeechAdaptation = true,
        },
    });

    var standardWebhook = new Gcp.Diagflow.CxWebhook("standard_webhook", new()
    {
        Parent = agent.Id,
        DisplayName = "MyFlow",
        ServiceDirectory = new Gcp.Diagflow.Inputs.CxWebhookServiceDirectoryArgs
        {
            Service = "projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service",
            GenericWebService = new Gcp.Diagflow.Inputs.CxWebhookServiceDirectoryGenericWebServiceArgs
            {
                AllowedCaCerts = new[]
                {
                    "BQA=",
                },
                Uri = "https://example.com",
                RequestHeaders = 
                {
                    { "example-key", "example-value" },
                },
                WebhookType = "STANDARD",
                OauthConfig = new Gcp.Diagflow.Inputs.CxWebhookServiceDirectoryGenericWebServiceOauthConfigArgs
                {
                    ClientId = "example-client-id",
                    SecretVersionForClientSecret = "projects/example-proj/secrets/example-secret/versions/example-version",
                    TokenEndpoint = "https://example.com",
                    Scopes = new[]
                    {
                        "example-scope",
                    },
                },
                ServiceAgentAuth = "NONE",
                SecretVersionForUsernamePassword = "projects/example-proj/secrets/example-secret/versions/example-version",
                SecretVersionsForRequestHeaders = new[]
                {
                    new Gcp.Diagflow.Inputs.CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs
                    {
                        Key = "example-key-1",
                        SecretVersion = "projects/example-proj/secrets/example-secret/versions/example-version",
                    },
                    new Gcp.Diagflow.Inputs.CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs
                    {
                        Key = "example-key-2",
                        SecretVersion = "projects/example-proj/secrets/example-secret/versions/example-version-2",
                    },
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.diagflow.CxAgent;
import com.pulumi.gcp.diagflow.CxAgentArgs;
import com.pulumi.gcp.diagflow.inputs.CxAgentSpeechToTextSettingsArgs;
import com.pulumi.gcp.diagflow.CxWebhook;
import com.pulumi.gcp.diagflow.CxWebhookArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookServiceDirectoryArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookServiceDirectoryGenericWebServiceArgs;
import com.pulumi.gcp.diagflow.inputs.CxWebhookServiceDirectoryGenericWebServiceOauthConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var agent = new CxAgent("agent", CxAgentArgs.builder()
            .displayName("dialogflowcx-agent")
            .location("us-central1")
            .defaultLanguageCode("en")
            .supportedLanguageCodes(            
                "it",
                "de",
                "es")
            .timeZone("America/New_York")
            .description("Example description.")
            .avatarUri("https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png")
            .enableStackdriverLogging(true)
            .enableSpellCorrection(true)
            .speechToTextSettings(CxAgentSpeechToTextSettingsArgs.builder()
                .enableSpeechAdaptation(true)
                .build())
            .build());

        var standardWebhook = new CxWebhook("standardWebhook", CxWebhookArgs.builder()
            .parent(agent.id())
            .displayName("MyFlow")
            .serviceDirectory(CxWebhookServiceDirectoryArgs.builder()
                .service("projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service")
                .genericWebService(CxWebhookServiceDirectoryGenericWebServiceArgs.builder()
                    .allowedCaCerts("BQA=")
                    .uri("https://example.com")
                    .requestHeaders(Map.of("example-key", "example-value"))
                    .webhookType("STANDARD")
                    .oauthConfig(CxWebhookServiceDirectoryGenericWebServiceOauthConfigArgs.builder()
                        .clientId("example-client-id")
                        .secretVersionForClientSecret("projects/example-proj/secrets/example-secret/versions/example-version")
                        .tokenEndpoint("https://example.com")
                        .scopes("example-scope")
                        .build())
                    .serviceAgentAuth("NONE")
                    .secretVersionForUsernamePassword("projects/example-proj/secrets/example-secret/versions/example-version")
                    .secretVersionsForRequestHeaders(                    
                        CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs.builder()
                            .key("example-key-1")
                            .secretVersion("projects/example-proj/secrets/example-secret/versions/example-version")
                            .build(),
                        CxWebhookServiceDirectoryGenericWebServiceSecretVersionsForRequestHeaderArgs.builder()
                            .key("example-key-2")
                            .secretVersion("projects/example-proj/secrets/example-secret/versions/example-version-2")
                            .build())
                    .build())
                .build())
            .build());

    }
}
resources:
  agent:
    type: gcp:diagflow:CxAgent
    properties:
      displayName: dialogflowcx-agent
      location: us-central1
      defaultLanguageCode: en
      supportedLanguageCodes:
        - it
        - de
        - es
      timeZone: America/New_York
      description: Example description.
      avatarUri: https://cloud.google.com/_static/images/cloud/icons/favicons/onecloud/super_cloud.png
      enableStackdriverLogging: true
      enableSpellCorrection: true
      speechToTextSettings:
        enableSpeechAdaptation: true
  standardWebhook:
    type: gcp:diagflow:CxWebhook
    name: standard_webhook
    properties:
      parent: ${agent.id}
      displayName: MyFlow
      serviceDirectory:
        service: projects/example-proj/locations/us-central1/namespaces/example-namespace/services/example-service
        genericWebService:
          allowedCaCerts:
            - BQA=
          uri: https://example.com
          requestHeaders:
            example-key: example-value
          webhookType: STANDARD
          oauthConfig:
            clientId: example-client-id
            secretVersionForClientSecret: projects/example-proj/secrets/example-secret/versions/example-version
            tokenEndpoint: https://example.com
            scopes:
              - example-scope
          serviceAgentAuth: NONE
          secretVersionForUsernamePassword: projects/example-proj/secrets/example-secret/versions/example-version
          secretVersionsForRequestHeaders:
            - key: example-key-1
              secretVersion: projects/example-proj/secrets/example-secret/versions/example-version
            - key: example-key-2
              secretVersion: projects/example-proj/secrets/example-secret/versions/example-version-2

The serviceDirectory property wraps the genericWebService configuration and adds a service reference pointing to your Service Directory service. This routes webhook calls through Service Directory’s internal networking rather than the public internet. Note that the agent must be in a regional location (like us-central1) rather than global for Service Directory integration to work. This extends the standard webhook pattern from earlier with private network routing.

Beyond these examples

These snippets focus on specific webhook features: standard and flexible webhook formats, OAuth and basic authentication, and Service Directory integration for private services. They’re intentionally minimal rather than full conversational AI applications.

The examples reference pre-existing infrastructure such as Dialogflow CX agents, Secret Manager secrets for credentials, and Service Directory services for private routing. They focus on webhook configuration rather than provisioning the surrounding infrastructure.

To keep things focused, common webhook patterns are omitted, including:

  • Webhook timeout configuration (timeout)
  • Webhook disabling (disabled)
  • CA certificate validation (allowedCaCerts)
  • Service agent authentication (serviceAgentAuth options)

These omissions are intentional: the goal is to illustrate how each webhook feature is wired, not provide drop-in integration modules. See the Dialogflow CX Webhook resource reference for all available configuration options.

Let's configure GCP Dialogflow CX Webhooks

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Webhook Types & Configuration
What's the difference between STANDARD and FLEXIBLE webhook types?
STANDARD webhooks use secret version references like secretVersionForClientSecret, while FLEXIBLE webhooks support direct secrets (clientSecret), custom HTTP methods (httpMethod), request bodies (requestBody), and parameter mapping (parameterMapping).
How do I configure OAuth authentication for my webhook?
Configure oauthConfig within genericWebService. For STANDARD webhooks, use secretVersionForClientSecret with clientId, tokenEndpoint, and scopes. For FLEXIBLE webhooks, use clientSecret directly with clientId and tokenEndpoint.
How do STANDARD and FLEXIBLE webhooks handle secrets differently?
STANDARD webhooks reference secrets using secretVersionForClientSecret and secretVersionsForRequestHeaders (pointing to Secret Manager versions). FLEXIBLE webhooks can use clientSecret directly as a string value.
Deployment Options
Should I use Service Directory or a direct URI for my webhook?
Use genericWebService with a direct uri for simple deployments. Use serviceDirectory with a service reference when integrating with Service Directory for service discovery and management.
How do I deploy a webhook using Service Directory?
Configure the serviceDirectory property with a service reference (format: projects/<Project ID>/locations/<Location ID>/namespaces/<namespace>/services/<service>), then nest your genericWebService configuration inside it.
Resource Management
Can I change which agent a webhook belongs to after creation?
No, the parent property is immutable. You must recreate the webhook if you need to change its parent agent.
Which webhook properties are deprecated?
Avoid enableSpellCorrection, enableStackdriverLogging, securitySettings, and startFlow. These properties are deprecated and should not be used in new configurations.

Using a different cloud?

Explore integration guides for other cloud providers: