HomeBlogAboutPricingContact🌐 δΈ­ζ–‡
← Back to HomeDialogflow
Dialogflow Fulfillment and API Integration Complete Tutorial

Dialogflow Fulfillment and API Integration Complete Tutorial

πŸ“‘ Table of Contents

Dialogflow Fulfillment and API Integration Complete TutorialDialogflow Fulfillment and API Integration Complete Tutorial

Static responses can only make simple FAQ bots. To make a bot truly useful, you must connect to backend systems: check orders, check inventory, handle reservations.

Dialogflow uses Fulfillment (Webhook) to let your bot call external APIs for dynamic responses. This article teaches you from scratch how to develop Webhooks, deploy to Cloud Functions, and integrate third-party APIs.

If you're not yet familiar with Dialogflow basics, we recommend first reading the Dialogflow Complete Guide and Intent and Context Tutorial.



Fulfillment Basic Concepts

When Do You Need Fulfillment

Scenarios that don't need Fulfillment:

Scenarios that need Fulfillment:

How Webhooks Work

User β†’ Dialogflow β†’ Webhook β†’ Your Backend β†’ Webhook β†’ Dialogflow β†’ User
  β”‚          β”‚          β”‚          β”‚          β”‚          β”‚          β”‚
"Check order" Intent   Call API  Query DB   Return    Compose    "Your order..."
            matching                        result    response

Flow explanation:

  1. Dialogflow detects an Intent that needs Fulfillment
  2. Sends HTTP POST request to your configured Webhook URL
  3. Your Webhook processes the request, calls database or API
  4. Returns structured JSON to Dialogflow
  5. Dialogflow sends content to user

ES vs CX Fulfillment Differences

DifferenceESCX
Request formatv2 API formatv3 API format
Response formatfulfillmentText / messagesfulfillmentResponse
Context handlingoutputContextssessionInfo.parameters
Trigger methodIntent-level enablePage/Route-level enable
Official SDKdialogflow-fulfillmentNo official SDK

This article primarily uses ES as examples. For CX Webhook development, refer to Dialogflow CX Tutorial.



Creating Webhook Service

Google Cloud Functions is the simplest Webhook deployment methodβ€”serverless, auto-scaling.

Step 1: Create Cloud Function

  1. Go to Google Cloud Console
  2. Select your project (same as Dialogflow Agent)
  3. Search for "Cloud Functions" and enter
  4. Click "Create Function"

Basic settings:

Step 2: Write Code

Select Runtime: Node.js 20

package.json:

{
  "name": "dialogflow-webhook",
  "version": "1.0.0",
  "dependencies": {
    "dialogflow-fulfillment": "^0.6.1"
  }
}

index.js:

const { WebhookClient } = require('dialogflow-fulfillment');

exports.dialogflowWebhook = (request, response) => {
  const agent = new WebhookClient({ request, response });

  console.log('Intent: ' + agent.intent);
  console.log('Parameters: ' + JSON.stringify(agent.parameters));

  function welcome(agent) {
    agent.add('Welcome to our service! How can I help you?');
  }

  function fallback(agent) {
    agent.add('Sorry, I don\'t quite understand what you mean.');
  }

  function checkOrder(agent) {
    const orderId = agent.parameters.order_id;
    // Call your order system here
    agent.add(`Order ${orderId} status is: Processing, expected to ship tomorrow.`);
  }

  const intentMap = new Map();
  intentMap.set('Default Welcome Intent', welcome);
  intentMap.set('Default Fallback Intent', fallback);
  intentMap.set('check_order', checkOrder);

  agent.handleRequest(intentMap);
};

Step 3: Deploy

  1. Click "Deploy"
  2. Wait for deployment to complete (about 1-2 minutes)
  3. Copy the trigger URL

Step 4: Configure in Dialogflow

  1. Enter Dialogflow Console
  2. Click "Fulfillment" on the left
  3. Enable "Webhook"
  4. Paste the Cloud Functions URL
  5. Click "Save"

Step 5: Enable Intent's Fulfillment

  1. Enter the Intent that needs Fulfillment
  2. Scroll to the bottom
  3. Expand "Fulfillment" section
  4. Check "Enable webhook call for this intent"
  5. Save

Using Node.js + Express

If you want to deploy on your own server:

const express = require('express');
const { WebhookClient } = require('dialogflow-fulfillment');

const app = express();
app.use(express.json());

app.post('/webhook', (req, res) => {
  const agent = new WebhookClient({ request: req, response: res });

  function handleIntent(agent) {
    agent.add('This is a response from custom server');
  }

  const intentMap = new Map();
  intentMap.set('my_intent', handleIntent);

  agent.handleRequest(intentMap);
});

app.listen(3000, () => {
  console.log('Webhook server running on port 3000');
});

Note: Self-hosted servers require:

Using Python Flask

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
    req = request.get_json()

    intent_name = req['queryResult']['intent']['displayName']
    parameters = req['queryResult']['parameters']

    if intent_name == 'check_order':
        order_id = parameters.get('order_id')
        response_text = f'Order {order_id} status is: Processing'
    else:
        response_text = 'Message received'

    return jsonify({
        'fulfillmentText': response_text
    })

if __name__ == '__main__':
    app.run(port=5000)

Deployment and HTTPS Setup

Local testing with ngrok:

# Install ngrok
npm install -g ngrok

# Start local server
node server.js

# In another terminal
ngrok http 3000

# Copy the HTTPS URL from ngrok, paste into Dialogflow

Production deployment options:



Dialogflow API Calls

Besides passively receiving Webhooks, you can also actively call Dialogflow API.

DetectIntent API

DetectIntent API lets you send messages to Dialogflow from your own application.

Use cases:

Service Account and Authentication Setup

Step 1: Create Service Account

  1. Go to Google Cloud Console > IAM & Admin > Service Accounts
  2. Click "Create Service Account"
  3. Enter name (e.g., dialogflow-client)
  4. Grant role: "Dialogflow API Client"
  5. Create key (JSON format)
  6. Download and safely store the key file

Step 2: Set Environment Variable

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

Example Code

Node.js:

const dialogflow = require('@google-cloud/dialogflow');
const uuid = require('uuid');

async function detectIntent(projectId, text) {
  const sessionId = uuid.v4();
  const sessionClient = new dialogflow.SessionsClient();
  const sessionPath = sessionClient.projectAgentSessionPath(projectId, sessionId);

  const request = {
    session: sessionPath,
    queryInput: {
      text: {
        text: text,
        languageCode: 'en-US',
      },
    },
  };

  const [response] = await sessionClient.detectIntent(request);
  const result = response.queryResult;

  console.log('Intent:', result.intent.displayName);
  console.log('Response:', result.fulfillmentText);

  return result;
}

// Usage example
detectIntent('your-project-id', 'I want to make a reservation');

Python:

from google.cloud import dialogflow_v2 as dialogflow
import uuid

def detect_intent(project_id, text):
    session_client = dialogflow.SessionsClient()
    session_id = str(uuid.uuid4())
    session = session_client.session_path(project_id, session_id)

    text_input = dialogflow.TextInput(text=text, language_code='en-US')
    query_input = dialogflow.QueryInput(text=text_input)

    response = session_client.detect_intent(
        request={'session': session, 'query_input': query_input}
    )

    result = response.query_result
    print(f'Intent: {result.intent.display_name}')
    print(f'Response: {result.fulfillment_text}')

    return result

# Usage example
detect_intent('your-project-id', 'I want to make a reservation')


GitHub Example Projects

Official Example Repository Introduction

Google provides official example code:

Dialogflow ES:

Dialogflow CX:

ProjectLanguageFeatures
dialogflow-fulfillment-nodejsNode.jsOfficial Fulfillment library
flask-dialogflow-webhookPythonFlask Webhook template
dialogflow-angularTypeScriptAngular integration example

Quick Deployment Template

One-click deploy to Cloud Functions:

# Clone example project
git clone https://github.com/your-repo/dialogflow-webhook-template.git
cd dialogflow-webhook-template

# Deploy
gcloud functions deploy dialogflow-webhook \
  --runtime nodejs20 \
  --trigger-http \
  --allow-unauthenticated \
  --region asia-east1


Advanced Integration

Connecting to Database (Firestore / MySQL)

Firestore Example:

const { Firestore } = require('@google-cloud/firestore');
const firestore = new Firestore();

async function checkOrder(agent) {
  const orderId = agent.parameters.order_id;

  const doc = await firestore.collection('orders').doc(orderId).get();

  if (!doc.exists) {
    agent.add('Cannot find this order, please confirm the order number is correct.');
    return;
  }

  const order = doc.data();
  agent.add(`Order ${orderId} status is: ${order.status}, expected delivery on ${order.delivery_date}.`);
}

MySQL Example:

const mysql = require('mysql2/promise');

async function checkInventory(agent) {
  const productName = agent.parameters.product;

  const connection = await mysql.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME,
  });

  const [rows] = await connection.execute(
    'SELECT stock FROM products WHERE name = ?',
    [productName]
  );

  if (rows.length > 0) {
    agent.add(`${productName} current stock is ${rows[0].stock} units.`);
  } else {
    agent.add('Cannot find this product.');
  }

  await connection.end();
}

Calling Third-Party APIs

Weather API Example:

const axios = require('axios');

async function getWeather(agent) {
  const city = agent.parameters['geo-city'];

  try {
    const response = await axios.get(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${process.env.WEATHER_API_KEY}&units=metric`
    );

    const weather = response.data;
    agent.add(`Current weather in ${city}: ${weather.weather[0].description}, temperature ${weather.main.temp}Β°C.`);
  } catch (error) {
    agent.add('Sorry, unable to get weather information, please try again later.');
  }
}

Async Processing and Long-Running Tasks

Dialogflow Webhook has a 5-second timeout limit. If tasks take longer:

Method 1: Quick Response + Follow-up Notification

async function processLongTask(agent) {
  const taskId = generateTaskId();

  // Respond immediately
  agent.add(`Received your request, processing... We'll notify you when complete (Task ID: ${taskId})`);

  // Async processing (don't wait)
  processTaskInBackground(taskId);
}

async function processTaskInBackground(taskId) {
  // Execute long-running task
  const result = await someHeavyOperation();

  // Send notification after completion (via LINE Push, Email, etc.)
  await sendNotification(taskId, result);
}

Method 2: Using Cloud Tasks

Put tasks in a queue, processed by another service:

const { CloudTasksClient } = require('@google-cloud/tasks');

async function queueTask(agent) {
  const client = new CloudTasksClient();

  const task = {
    httpRequest: {
      httpMethod: 'POST',
      url: 'https://your-worker-service.com/process',
      body: Buffer.from(JSON.stringify({ data: agent.parameters })).toString('base64'),
    },
  };

  await client.createTask({ parent: queuePath, task });

  agent.add('Your request has been added to the processing queue, we\'ll notify you of results shortly.');
}

Error Handling and Retry Mechanism

async function robustApiCall(agent) {
  const maxRetries = 3;
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await callExternalApi();
      agent.add(`Query result: ${result}`);
      return;
    } catch (error) {
      lastError = error;
      console.error(`Attempt ${i + 1} failed:`, error.message);

      if (i < maxRetries - 1) {
        await sleep(1000 * (i + 1)); // Exponential backoff
      }
    }
  }

  // All retries failed
  console.error('All retries failed:', lastError);
  agent.add('System temporarily busy, please try again later. For urgent assistance, please call customer service.');
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Can't get integration working? Backend integration is the highest technical barrier, involving security, performance, and error handling. Book technical consultation to have experienced people help solve your integration challenges.



Deployment and Operations

Monitoring and Logging

Cloud Functions Logs:

  1. Go to Google Cloud Console > Cloud Functions
  2. Select your Function
  3. Click "Logs" tab

Setting Up Alerts:

  1. Go to Cloud Monitoring
  2. Create alert policy
  3. Set conditions: Error rate > 5%, latency > 2 seconds
  4. Set notification channels (Email, Slack)

Performance Optimization

1. Reduce Cold Start

// Initialize connections outside Function to avoid reconnecting every time
const firestore = new Firestore();

exports.webhook = async (req, res) => {
  // Use established connection
  const doc = await firestore.collection('orders').doc('123').get();
  // ...
};

2. Use Caching

const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 300 }); // 5-minute cache

async function getData(key) {
  let data = cache.get(key);

  if (!data) {
    data = await fetchFromDatabase(key);
    cache.set(key, data);
  }

  return data;
}

3. Set Minimum Instances

Avoid cold start latency:

gcloud functions deploy webhook \
  --min-instances 1 \
  --max-instances 10

Security Considerations

1. Verify Request Source

Confirm request actually comes from Dialogflow:

// Check User-Agent
if (!req.headers['user-agent'].includes('Google-Dialogflow')) {
  return res.status(403).send('Forbidden');
}

2. Environment Variable Management

Don't write sensitive information in code:

// ❌ Bad
const apiKey = 'sk-xxxxx';

// βœ“ Good
const apiKey = process.env.API_KEY;

3. Limit Access Scope

Service accounts should only have needed permissions, don't use Owner permissions.

If you need to integrate into mobile apps, refer to Dialogflow Mobile Development Integration Tutorial. For LINE Bot integration, refer to Dialogflow LINE Bot Integration Tutorial.



Next Steps

After mastering Fulfillment development, you can:

  1. Optimize Conversation Design: Dialogflow Intent and Context Complete Tutorial
  2. Learn CX Version: Dialogflow CX Tutorial: From Beginner to Advanced
  3. Integrate LINE Bot: Dialogflow LINE Bot Integration Tutorial
  4. Mobile App Integration: Dialogflow Mobile Development Integration Tutorial


Need Help with Backend Integration?

Good backend architecture makes systems stable, secure, and easy to extend. Poor architecture causes problems when traffic increases or becomes security vulnerabilities.

If you need:

Book architecture consultation to have experienced engineers help design robust backend architecture.

Consultation is completely free, we'll respond within 24 hours.


Need Professional Cloud Advice?

Whether you're evaluating cloud platforms, optimizing existing architecture, or looking for cost-saving solutions, we can help

Book Free Consultation

DialogflowAWSGCPAzureKubernetes
← Previous
Dialogflow Complete Guide 2026: From Beginner to Production AI Chatbot Development
Next β†’
Dialogflow CX vs ES Complete Comparison: 2026 Version Selection Guide