Publish & API

Preview is for builders. Production usually means a Web App, the Service API (REST + per-app API keys), and optionally an MCP Server for Cursor-class clients (see MCP on this site). Official difyctl can run the same apps from a shell; see Installation.


Publish the Web App

In Studio, Publish, then enable the Web App. Typical extras: a public link, iframe / chat-bubble embed, light branding and access control (see current Web App Settings).

Good for: colleague trials, a helper on a marketing site. Bad for: stuffing an API key into the browser and calling that an integration. Humans use the Web App; your backend uses the Service API below.

Isolation: API conversations and Web App conversations do not share history. The same business user gets two conversation_id spaces.


Create an API key

Open API Access in the app (sidebar may say “API” or “Develop”):

  1. Read the generated docs for this app (chat vs workflow paths differ)
  2. Create an API Key; split dev / prod; do not share one secret
  3. Store it in server env vars; rotate by adding the new key first

Cloud examples use https://api.dify.ai/v1. Self-host is your site root plus /v1 (via nginx), e.g. http://localhost/v1. Auth header:

Authorization: Bearer {YOUR_API_KEY}

Official path: POST /v1/chat-messages

Chat-style apps (Chatflow, Chatbot, Agent, and “New Agent” in the spec) send messages to /chat-messages. With the versioned base that is /v1/chat-messages.

curl -X POST 'https://api.dify.ai/v1/chat-messages' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "inputs": {},
    "query": "Introduce yourself in one sentence.",
    "response_mode": "blocking",
    "conversation_id": "",
    "user": "user-42"
  }'

Self-host: http://localhost/v1/chat-messages (or https://your-host/v1/chat-messages).

FieldRole
queryThis turn’s user text
inputsStart variables; ignored on later turns once conversation_id is set
response_modeblocking JSON vs streaming SSE. Agent + blocking: check current docs
conversation_id"" starts a thread; send back the id to continue
userEnd-user id for stats and isolation; do not leave it blank

Single-run workflow apps use a separate workflow run endpoint (see that app’s API page). Do not post those jobs to chat-messages.


Minimal Python client

import os
import requests

BASE = os.environ.get("DIFY_API_BASE", "http://localhost/v1")
KEY = os.environ["DIFY_API_KEY"]

r = requests.post(
    f"{BASE}/chat-messages",
    headers={"Authorization": f"Bearer {KEY}"},
    json={
        "inputs": {},
        "query": "What is Dify?",
        "response_mode": "blocking",
        "user": "backend-demo",
    },
    timeout=60,
)
r.raise_for_status()
data = r.json()
print(data.get("answer") or data)
# Continue: send data["conversation_id"] on the next request

Add timeouts, retries, and logging in production (never log the raw key). A fuller wrapper is in Practical Examples.


Safety checklist

  • Treat keys as passwords; revoke on leak
  • One key per app and environment so you can kill a stolen secret
  • Browsers call your BFF; only the BFF holds the Dify key
  • Check log retention (Cloud vs self-host) for compliance

Next steps

评论