Dify custom endpoints for moderation and external data: what the integration does
A regulated team that wants its own moderation or retrieval service running inside Dify apps should use a custom endpoint, the contract Dify documents for calling an API you host. The endpoint is authenticated with a bearer key that Dify sends with each request, and Dify checks the endpoint with a ping before it is used. This is the method described in the Dify docs, so you do not need to write a bespoke plugin to get it.
Dify exposes two endpoint roles. A moderation endpoint receives content and returns a decision that an app can act on, such as blocking or flagging a message. An external data endpoint returns retrieved content that an app can use as context, which lets a team connect a document store or internal search service without first copying its contents into a Dify knowledge base. Each role has its own request and response shape, so confirm the exact fields against the current Dify docs for your version before you build against them.
Dify is released under the Dify Open Source License, so you run the platform in your own infrastructure and remain responsible for the services it calls. The custom endpoint sits inside an individual app's configuration, not in the platform core, which means your moderation or retrieval service is a dependency of that app. Confirm which apps will call it, what each call sends, and what happens when your service is slow or unavailable, because those answers decide how much of the app's behavior depends on the endpoint.
What you need before connecting a custom endpoint
A custom endpoint is only as dependable as the Dify deployment and the API behind it. The cards below cover the Dify version, the runtime, the network path, the credential and the people who answer for the moderation or data service.
A tested Dify version
Pin the Dify version you will run and test the endpoint against that exact release. The current lines on the releases page are 1.16.x and 1.17.x, and minor releases arrive about monthly, so a contract that worked on one patch may behave differently after an upgrade. Confirm the endpoint fields in the Dify docs for your version before you write code, rather than relying on memory or on an older blog post.
Docker Compose runtime
If you deploy with Docker Compose, the host needs Docker Compose 2.24.0 or later, and the stack must be running before you register anything. Check that the api and worker services can reach your endpoint, because the calls originate from the Dify API service, not from the browser. Record the Compose version in your change ticket so the test environment and production match.
Reachable API over TLS
The hosted moderation or data API must be reachable from the Dify API service over HTTPS with a certificate that the service trusts. Check DNS resolution, firewall rules and any egress proxy from inside the Dify container, not from your laptop. Note that outbound requests are also filtered by the SSRF proxy, so an endpoint on a private address may be blocked unless your configuration allows it.
Bearer key stored as a secret
Issue a dedicated bearer key for the Dify integration, separate from keys used by other clients, and store it in your secrets manager or the Dify credential store rather than in a workflow export or a shared note. Define who can rotate it and how a rotation reaches both Dify and the API. Your endpoint should validate the key on every request, and it should reject requests that carry no key or an unknown one.
Named owner for the API
Assign one accountable owner for the moderation or external data API, with a deputy. The owner decides what the service returns when it fails, how fast a policy change reaches production, and who approves changes to the contract. Without this owner, a timeout in a live chat app becomes a dispute between the AI team, security and the vendor of the API.
Fallback behavior agreed in advance
Before connecting the endpoint, agree whether a failed moderation or retrieval call should block the request, pass it through with a log entry or use a fallback response. Put that decision in writing with the risk owner. Test the failure path explicitly by stopping the service, returning errors and returning slow responses, because regulated teams are often asked how the application behaves when a control is unavailable.
How to configure a custom endpoint step by step
This sequence takes a custom endpoint from an unverified API to a tested hook in one non-production app. Each step ends with a check you can record, so the endpoint reaches production apps only after the ping and representative runs behave as expected.
Prepare the external API and bearer key
The engineering team that owns the moderation or external data service builds or confirms the API, then generates a bearer key and stores it in your secrets manager, not in app configuration or source control. Before connecting Dify, they call the service with curl from the network segment where Dify runs. A request without the key or with a wrong key must be refused, and a request with the correct key must succeed. Done when both results are recorded and the key has an owner and a rotation plan.
Expose and confirm the ping route
Expose the ping route that the custom endpoint contract defines. Confirm its exact path, request method and expected response in the current Dify documentation for custom endpoints, since those details must match the contract your version of Dify expects. Call the route with a valid key and check that it returns the success response the contract describes. Check the API-side logs to confirm the request arrived with the expected authorization header. No app should depend on the endpoint until this check passes.
Register the endpoint with base URL and key
A workspace administrator adds the endpoint in Dify's settings, entering the base URL and the bearer key. Use an HTTPS base URL with a stable internal DNS name rather than a raw IP address, so that a later host change does not require editing every app. After saving, reopen the entry and confirm that the key is masked and not displayed in plain text. Done when the endpoint appears in the list with the correct base URL and no visible key.
Test the ping check from the console
Run the ping check from the Dify console. Outbound calls from Dify pass through the SSRF proxy settings, which route requests through a proxy that blocks internal and private IP ranges. If the target host sits in a private range, confirm in the environment variable reference how your deployment's SSRF proxy rules treat that host before testing again. Done when the console reports success and the API-side log shows a matching request. If the ping fails, check the base URL, the key and the proxy rules, in that order.
Attach the endpoint to one test app
Open one non-production app and attach the endpoint at the hook that its type supports. Confirm which hook applies to your endpoint type in the Dify documentation, because the hook determines when the API receives input and when its output is used. Keep the test app isolated from production users and shared knowledge bases. Done when the app configuration shows the endpoint attached at the intended hook and a single preview run produces a request in the API-side logs.
Run representative inputs and outputs
Build a short test set that includes ordinary inputs, borderline inputs and inputs the API should block or flag, each with an expected result written down in advance. Run every case through the test app and record the response Dify returns and the request the API logged. Confirm that logs show the key-authenticated calls and that they do not store sensitive user content beyond your retention policy. Done when each case matches its expected result, or each mismatch has a documented fix before any wider rollout.
Where moderation and external data hooks run in a Dify app
Input moderation runs before the model receives the user's message. It is the point to screen prompts for policy violations, personal data or injection attempts, and to stop a request before any model tokens are spent. Confirm in the Dify app management docs for your version that your app type exposes this hook, and where it sits relative to knowledge retrieval and workflow nodes.
- What the request carries: the user input values and query text the endpoint must check, plus any app context that the contract defines for your version.
- What the response must return: a clear allow or flag decision and, when flagged, the preset reply the app shows instead of calling the model.
- When the endpoint fails: confirm whether Dify treats an error or timeout as a pass or a block. A fail-open setting sends unscreened input to the model.
- Timeouts: keep the response short, because every end-user message waits for this call before the model runs.
- Logging: decide whether flagged inputs are stored in your own logs and who may read them, since the raw text may contain personal data.
Check the exact field names, failure behavior and timeout value in the contract for your Dify version before you write the endpoint.
Output moderation screens what the model generated before the user sees it. It catches leaked data, unsafe content and answers that break policy even when the input was clean. Streaming responses complicate this hook, because text may reach the browser before the check finishes. Confirm whether your app type supports output moderation on streamed responses, and under which response mode it applies.
- What the request carries: the generated text and the context the contract provides for matching it to the original query.
- What the response must return: an allow or flag decision and, when flagged, the replacement text the app should display.
- Streaming: if chunks are sent before the check completes, a flag may arrive too late to stop them. Test this with the exact response mode your application uses.
- Failure policy: decide per app whether a failed check blocks the answer or lets it through. Regulated content usually needs a block, and the decision should be written down with its owner.
- Capacity: every generated answer adds one call, so size the endpoint for peak answer volume, not average traffic.
Test a flagged response end to end in a staging workspace, including the streamed view, before any team depends on this hook.
External data hooks fetch records from your own systems, such as a policy store, a CRM or an inventory service, and return them as context for a prompt or workflow. The lookup decides what the model can ground its answer in, so its scope and failure handling matter as much as its speed. Confirm in your version's docs which app types can call an external data source and how the result is inserted into the prompt.
- What the request carries: the inputs and query needed to scope the lookup. Send identifiers only where the lookup needs them.
- What the response must return: the context text or records in the shape the contract defines, kept short enough to fit the prompt budget.
- When the lookup fails: decide whether the prompt runs without context and says so, or stops. Empty context returned silently produces ungrounded answers that look sourced.
- Access control: the endpoint should enforce the end user's permissions, because Dify passes whatever it returns into the conversation.
- Network path: outbound requests from Dify pass through an SSRF proxy that blocks internal and private IP ranges. Confirm how your internal endpoint is allowed through in the environment settings for your deployment.
Confirm the response size limit, the timeout and whether the call runs for each message or once per session in your app version.
How app data maps to the endpoint request and response
This table lists the data Dify sends to your moderation or external data API and the fields your API returns for Dify to act on. Read each row as one exchange: what leaves the app, what your service must check, and what Dify does with the answer. Confirm every field name against the Dify version you run before you write the handler, because names can change between releases.
| Data or field | Sent by Dify to your API | Returned to Dify and how it is used |
|---|---|---|
| Hook type | A point value naming the hook, such as input moderation, output moderation, external data query or ping | Your service branches on it. Answer unrecognized points safely and log them. Confirm the point names for your version. |
| Bearer key | An Authorization header carrying the bearer key saved on the API extension | Validate the key before reading the body and reject mismatches. Dify does not use a key from the response body. |
| User input | The text the end user typed and the app input variables, for input moderation | A flagged result stops the run and returns your preset message. Confirm the exact input and query field names. |
| Model output | The generated text, sent to the output moderation hook before the user sees it | A flagged result replaces the output with your preset message. Confirm whether the flag and message fields match the docs. |
| App and conversation identifiers | App or conversation identifiers, only where the running version includes them | Use them for per-app policy and audit logs. Do not assume they are present in every call. |
| External data query | Tool variable names and the query the prompt or workflow needs context for | Return a result string that Dify inserts as context. Confirm the result field name and any size limits. |
| Ping check | A ping request Dify sends to test the endpoint and key | Return the success response the Dify docs specify. Dify uses this check to confirm the endpoint works before you rely on it. |
| Errors and timeouts | No response, a non-success status or a response past the timeout | Dify surfaces a failure in the app. Decide in advance whether your policy fails open or closed, and confirm how your version handles each status. |
Securing the bearer key and the endpoint
A custom endpoint for moderation or external data is a trust boundary: Dify sends content to it and acts on what comes back. The controls below cover where the bearer key lives, how it changes, which network path can reach the endpoint, how each request is checked, and how outbound calls are filtered.
Store the bearer key as a secret
Enter the bearer key in Dify's credential fields so it is held as a secret, not written into prompts, workflow descriptions or notes that teams copy around. Dify's app export is a YAML DSL file, and the docs state that exports exclude third-party API keys, so the key must be re-entered in each target instance when an app is imported. Check that no one has pasted the key into a shared template or a ticket. Confirm where your Dify instance stores encrypted values before you rely on that protection for audit purposes.
Plan key rotation and the change window
Rotate the bearer key on a schedule and before staff changes, and plan each rotation as a two-sided change: the endpoint must accept the new key while Dify still holds the old one, or the moderation step fails for every app that calls it. Pick a window when traffic is low and record which apps and workspaces reference the key. Do not use SECRET_KEY for this. The environment variable reference says changing SECRET_KEY after deployment logs out all users, so it is not a rotation tool for this key.
Restrict the endpoint to the Dify path
Expose the moderation or external data API only on the network segment that carries traffic from Dify's API and worker services, through a private address or a firewall rule. Confirm with your network team which hosts originate those calls in your Docker Compose or Kubernetes layout, since a load balancer or NAT address can change the source you allow. An endpoint reachable from the internet with only a bearer key is a single point of failure, so add a network rule even when the key is strong.
Validate the key on every request
Your endpoint should reject any request that lacks the expected bearer header or carries a wrong value, and it should do this on each call, not only during the ping check. The ping check confirms that the endpoint and key work at configuration time, but it does not protect later traffic. Return a clear error code for failed authentication and log the failure without logging the key or the moderated content. Test with an invalid key and a missing header before go-live.
Allow only the approved host through SSRF proxy
Dify routes outbound requests through the SSRF proxy, which the environment reference describes as blocking internal and private IP ranges. Your custom endpoint often sits on a private address, so it will need an explicit allowance for that one host, and nothing broader. Keep the allowlist to the single approved host and port, and confirm with a test call that other internal addresses remain blocked. Review the allowance whenever the endpoint moves.
How the ping check confirms the contract before go-live
Treat the ping check as a go-live gate, not a formality. Dify calls your custom endpoint's ping operation to confirm that the endpoint is reachable from the Dify API service and that it accepts the bearer key configured in the console. Until that call succeeds with the response Dify expects, the endpoint should not be attached to a moderation or external data step in a production app. A ping that passes once from a developer laptop proves little, because the call that matters is made from the Dify container network, through whatever egress path and SSRF proxy rules your deployment applies, using the key stored in your production configuration.
Ping alone does not show whether the endpoint can serve the app. Load test the moderation or retrieval call at the request volume and payload size you expect at peak, and record latency at the median and the tail, because a slow hook stalls every user message that passes through it. Then test failure behavior deliberately: stop the service, return a 500, return a 401 with a rotated key, and time out a request. For each case, record what the Dify app does, whether it blocks the message, passes it through, or returns a fallback, and what the end user sees. Those answers should match the behavior your risk owner signed off on. Confirm the exact ping request, the expected response and the handling of error codes against the Dify documentation for the version you run, since these details change between releases.
Common custom endpoint failures and how to fix them
This table pairs each common failure with its likely cause and fix when a custom moderation or external data endpoint misbehaves in a self-hosted Dify. Work through the rows in order of where the request fails, and check the Dify API and worker logs and the endpoint's own logs before changing configuration.
| Failure | Likely cause | Fix |
|---|---|---|
| Ping fails with 401 or 403 | The API key entered in Dify does not match the key the endpoint validates, or the bearer header is missing or malformed. | Re-enter the key exactly, confirm the endpoint reads the Authorization bearer header, and compare the value in the endpoint's logs with what Dify sent. |
| Endpoint unreachable from the Dify API container | The URL uses localhost or a host name that resolves only on the host, not inside the container network, or a firewall blocks the port. | Use an address the API container can reach, test it from inside the container with a simple request, and open the port between the Dify network and the endpoint. |
| SSRF proxy blocks the target host | The SSRF proxy blocks internal and private IP ranges, so an endpoint on a private address is refused even though it is reachable. | Confirm with your platform team whether the endpoint should be reached through the proxy, then adjust the allowlist settings your deployment uses rather than disabling the proxy. |
| Response shape does not match what Dify expects | The endpoint returns fields with different names, nesting or types than the contract specifies, so Dify cannot read the decision or data. | Compare the raw response with the documented contract, correct field names and types, and return the same structure for both successful and error cases. |
| Timeouts on slow moderation calls | The classifier or downstream service takes longer than the time Dify waits, often under load or when it calls another model. | Measure response time at the endpoint, reduce the work per call, cache repeated results where policy allows, and scale the endpoint before raising limits. |
| Hook does not fire | The hook was attached to an app type or stage where it does not run, or it was configured in a different app than the one under test. | Confirm the app type and stage named in the Dify docs, reopen the target app, and test in that app's preview with logs open. |
| Intermittent failures with no clear error | Errors appear only under concurrent use, or the endpoint rejects some requests after a key or certificate rotation. | Correlate timestamps across the Dify API and worker logs and the endpoint logs, and check that every running instance uses the current key. |
Questions teams ask before building a custom endpoint
How much effort does a custom moderation or external data endpoint take to build?
The effort depends mostly on the contract you must satisfy, how many hooks you expose, the latency your app can tolerate, and how ready the external system already is. A single moderation hook that wraps an existing classifier with a bearer key check and a ping response is a small piece of code. Effort grows when you add several hooks, need strict response times, or must map results from a system that has no stable API. Ask for each hook's input and output schema, the expected error handling, and a test plan covering timeouts and malformed responses. The external system's own readiness is often the largest unknown, so confirm its owner, documentation and change process before estimating build work.
Can an internal team build a custom endpoint alone, and what skills does it need?
An internal team can build the endpoint alone if it has an engineer comfortable with HTTP APIs, authentication headers, JSON contracts and basic service hosting, and if someone knows how the Dify app flow will call the hook. The work needs an API developer for the endpoint, a platform engineer who can place it on the network and manage secrets, and a reviewer who understands the safety policy the moderation hook enforces. Teams without that mix usually struggle with timeouts and failure modes, which show up only under real traffic. Most teams that build this in-house start by running the ping check and a few test prompts against a staging Dify instance before connecting production apps.
How long does a custom endpoint take, and what does the timeline depend on?
No duration is fixed by the Dify contract itself, so the timeline depends on the work around the endpoint. The main drivers are how quickly the external system's API owner can confirm behavior, how many hooks and apps are involved, whether test data exists, and how long network and security approvals take inside your organization. Each hook also needs testing against failure cases, such as a slow external service or an unexpected response shape. Ask for a written plan with milestones for contract agreement, endpoint build, staging validation and production rollout, and check which of those steps depends on people outside your team.
Is a custom endpoint the right choice compared with a plugin or an OpenAPI tool?
A custom endpoint suits cases where Dify needs to call your service at defined points in an app, such as checking content or fetching external data, and where you want to keep that logic outside Dify. An OpenAPI tool fits when a workflow step or agent should call a REST API on demand, and a plugin fits when you need a reusable package with its own configuration screens, versioning and distribution. Pick the option that matches who calls the service and when. Writing a plugin adds packaging, signing and daemon operations, so teams with one hook and one consumer often start with the endpoint. Confirm the choice against the plugin type guidance before committing, because moving later means rewriting the integration.
What does the work need from our organization?
Expect to provide an API owner for the external system, a named custodian for the bearer key, sample inputs and outputs that represent real traffic, and approval for the network path from Dify to your endpoint. The key custody question matters: decide who generates, rotates and stores the key, and where it lives in your secrets management. Test data should include benign content, edge cases and content that must be blocked, with the expected result for each. Network approval often takes the longest, because the Dify outbound path may pass through the SSRF proxy, which blocks internal and private IP ranges by design. Confirm early which route your endpoint will use so the approval request is specific.
Does a custom endpoint change Dify's license or support position?
Building a custom endpoint does not change the Dify Open Source License, which is a modified Apache License 2.0. The license restricts operating the source code as a multi-tenant environment without written authorization and requires keeping the logo and copyright information in the console. Calling your own service from Dify does not alter those terms. Support is a separate question: the Community edition is limited to a single workspace, and the Enterprise edition adds professional support, so the vendor's support scope for your deployment depends on the edition you run. Confirm the edition and support terms with Dify before production, and review the license text with your legal team.
How DeployOpen scopes and delivers custom endpoint work
DeployOpen plans, implements, integrates and documents self-hosted platforms inside the client's own infrastructure, including the custom endpoint work described here. Most engagements are fixed-scope: the scope, deliverables and timeline are agreed in writing before any build starts. For a custom endpoint project, that written scope should name the moderation or external data use case, the Dify apps and hook points involved, the hosts the endpoint runs on, who owns the bearer keys, and which environments are covered. Ask for those items to appear explicitly in the scope document, because they are the inputs that decide the work.
The handover is built around what your team needs to operate the endpoint after the engagement ends. It typically includes endpoint contract tests that exercise the bearer key check and the ping check, hook configuration notes that record which app settings call the endpoint and what each call expects back, a key handling runbook covering issuance, storage, rotation and revocation, and a verification checklist your staff can rerun after a Dify upgrade. Confirm the exact list of artifacts, their format and who keeps them current before signing, since the contents should be agreed in the scope rather than assumed.
Ongoing support, upgrades and continuous testing are available as retainers, which suits teams that expect the endpoint to change as Dify releases arrive. DeployOpen does not publish prices. After the scope is agreed, your team receives a written quote that follows from that scope, so the quote reflects the hook count, environments, integration effort and handover items you chose. Ask the quote to separate one-time build work from any recurring retainer, and to state what happens to the artifacts if you end the retainer.

