Skip to main content

Procedure

Since Dify custom endpoints require a publicly accessible address as the API Endpoint, the endpoint needs to be deployed to a public address. Here we use Cloudflare Workers to deploy the custom endpoint. Clone the Example GitHub Repository. This repository contains a simple custom endpoint that can be modified as a starting point.
git clone https://github.com/crazywoola/dify-extension-workers.git
cp wrangler.toml.example wrangler.toml
Open the wrangler.toml file and modify name and compatibility_date to your application name and compatibility date. The configuration we need to pay attention to here is the TOKEN in vars. When adding a custom endpoint in Dify, we need to fill in this Token. For security reasons, we recommend using a random string as the Token. You should not write the Token directly in the source code, but pass it through environment variables. Therefore, please do not commit wrangler.toml to your code repository.
name = "dify-extension-example"
compatibility_date = "2023-01-01"

[vars]
TOKEN = "bananaiscool"
This custom endpoint will return a random Breaking Bad quote. You can modify the logic of this custom endpoint in src/index.ts. This example demonstrates how to interact with third-party APIs.
// ⬇️ implement your logic here ⬇️
// point === "app.external_data_tool.query"
// https://api.breakingbadquotes.xyz/v1/quotes
const count = params?.inputs?.count ?? 1;
const url = `https://api.breakingbadquotes.xyz/v1/quotes/${count}`;
const result = await fetch(url).then(res => res.text())
// ⬆️ implement your logic here ⬆️
This repository simplifies all configurations except business logic. You can directly use npm commands to deploy your custom endpoint.
npm install
npm run deploy
After successful deployment, you will get a public address that you can add in Dify as the custom endpoint. Please note not to omit the endpoint path. The specific definition of this path can be found in src/index.ts.
Add Custom Endpoint in Dify
Alternatively, you can use the npm run dev command to deploy locally for testing.
npm install
npm run dev
Related output:
$ npm run dev
> dev
> wrangler dev src/index.ts

 ⛅️ wrangler 3.99.0
-------------------

Your worker has access to the following bindings:
- Vars:
  - TOKEN: "ban****ool"
 Starting local server...
[wrangler:inf] Ready on http://localhost:58445
After that, you can use tools like Postman for local interface debugging.

About Bearer Auth

import { bearerAuth } from "hono/bearer-auth";

(c, next) => {
    const auth = bearerAuth({ token: c.env.TOKEN });
    return auth(c, next);
},
Our Bearer validation logic is in the above code. We use the hono/bearer-auth package to implement Bearer validation. You can use c.env.TOKEN in src/index.ts to get the Token.

About Parameter Validation

import { z } from "zod";
import { zValidator } from "@hono/zod-validator";

const schema = z.object({
  point: z.union([
    z.literal("ping"),
    z.literal("app.external_data_tool.query"),
  ]), // Restricts 'point' to two specific values
  params: z
    .object({
      app_id: z.string().optional(),
      tool_variable: z.string().optional(),
      inputs: z.record(z.any()).optional(),
      query: z.any().optional(),  // string or null
    })
    .optional(),
});

We use zod to define parameter types here. You can use zValidator in src/index.ts to validate parameters. Use const { point, params } = c.req.valid("json"); to get the validated parameters. The point here has only two values, so we use z.union to define it. params is an optional parameter, so we use z.optional to define it. There will be an inputs parameter, which is a Record<string, any> type. This type represents an object with string keys and any values. This type can represent any object. You can use params?.inputs?.count in src/index.ts to get the count parameter.

Get Cloudflare Workers Logs

wrangler tail

Reference:
Last modified on June 25, 2026