> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dify.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy API Extensions Using Cloudflare Workers

## Procedure

Since Dify API extensions require a publicly accessible address as the API Endpoint, the API extension needs to be deployed to a public address.

Here we use Cloudflare Workers to deploy the API extension.

Clone the [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers). This repository contains a simple API extension that can be modified as a starting point.

```bash theme={null}
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 an API extension 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.

```toml theme={null}
name = "dify-extension-example"
compatibility_date = "2023-01-01"

[vars]
TOKEN = "bananaiscool"
```

This API extension will return a random Breaking Bad quote. You can modify the logic of this API extension in `src/index.ts`. This example demonstrates how to interact with third-party APIs.

```typescript theme={null}
// ⬇️ 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 API extension.

```bash theme={null}
npm install
npm run deploy
```

After successful deployment, you will get a public address that you can add in Dify as the API Endpoint. Please note not to omit the `endpoint` path. The specific definition of this path can be found in `src/index.ts`.

<Frame>
  ![Add API Endpoint in Dify](https://assets-docs.dify.ai/dify-enterprise-mintlify/zh_CN/guides/extension/api-based-extension/9433a486a441713ade6270e9dc6c0544.png)
</Frame>

Alternatively, you can use the `npm run dev` command to deploy locally for testing.

```bash theme={null}
npm install
npm run dev
```

Related output:

```bash theme={null}
$ 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

```typescript theme={null}
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

```typescript theme={null}
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

```bash theme={null}
wrangler tail
```

***

**Reference**:

* [Cloudflare Workers](https://workers.cloudflare.com/)
* [Cloudflare Workers CLI](https://developers.cloudflare.com/workers/cli-wrangler/install-update)
* [Example GitHub Repository](https://github.com/crazywoola/dify-extension-workers)
