LiyaEngine Docs
Dashboard API

Custom Domains

Create, configure, and manage custom domains via the Dashboard API.

Dashboard

Custom domains are the production path for LiyaEngine tenants. Use them to define your own AI domains with custom intents, agents, workflows, prompt templates, and knowledge sources. All custom domain management is done through the /dashboard/custom-domains endpoints.

For a guided walkthrough see Custom Domain Walkthrough.


GET /dashboard/custom-domains

List all custom domains for your tenant.

GET https://api.liyaengine.ai/dashboard/custom-domains
Authorization: Bearer <jwt>

Response:

Each domain row is returned as stored (snake_case fields), together with its full intents and source_types arrays — there is no separate intentCount summary field.

{
  "success": true,
  "data": {
    "domains": [
      {
        "id": "cdom_01HZ...",
        "domain_key": "legal-contracts",
        "display_name": "Legal Contracts",
        "description": "AI assistant for contract review and clause extraction",
        "system_prompt": "You are a legal assistant specialised in contract analysis...",
        "is_active": true,
        "status": "active",
        "intents": [ { "id": "cint_01HZ...", "intent_key": "clause_extraction", "...": "..." } ],
        "source_types": [],
        "created_at": "2026-01-20T09:00:00Z",
        "updated_at": "2026-02-10T14:30:00Z"
      }
    ]
  }
}

Requires the admin role or higher (creating, updating, and deleting domains all require admin; listing is open to any dashboard role).


POST /dashboard/custom-domains

Create a new custom domain. Requires the admin role or higher.

POST https://api.liyaengine.ai/dashboard/custom-domains
Authorization: Bearer <jwt>
Content-Type: application/json

{
  "domainKey": "legal-contracts",
  "displayName": "Legal Contracts",
  "description": "AI assistant for contract review and clause extraction",
  "systemPrompt": "You are a legal assistant specialised in contract analysis. You help users review, summarise, and extract key clauses from contracts."
}

Request body:

FieldTypeRequiredDescription
domainKeystringYesUnique identifier used in API calls — lowercase letters, numbers, hyphens only
displayNamestringYesHuman-readable name shown in the dashboard
descriptionstringNoShort description of the domain's purpose
systemPromptstringNoBase system prompt applied to all intents in this domain

domainKey rules:

  • Lowercase letters, numbers, and hyphens only (^[a-z0-9-]+$) — underscores are rejected
  • Must be unique within your tenant
  • Cannot be changed after creation

Response:

{
  "success": true,
  "data": {
    "domain": {
      "id": "cdom_01HZ...",
      "domain_key": "legal-contracts",
      "display_name": "Legal Contracts",
      "is_active": true,
      "status": "active",
      "created_at": "2026-03-15T10:00:00Z"
    }
  }
}

Requires the account's enable_custom_domains feature flag (Growth plan and above) — returns 403 FEATURE_NOT_ENABLED otherwise.


PATCH /dashboard/custom-domains/:domainKey

Update a custom domain's display name, description, or system prompt. Requires the admin role or higher.

PATCH https://api.liyaengine.ai/dashboard/custom-domains/legal-contracts
Authorization: Bearer <jwt>
Content-Type: application/json

{
  "displayName": "Legal Contract Review",
  "systemPrompt": "Updated system prompt..."
}

Response:

{ "success": true, "data": { "updated": 1 } }

DELETE /dashboard/custom-domains/:domainKey

Requires the admin role or higher.

Soft-deletes the domain — sets is_active: false so it (and its intents) drop out of the default dashboard/execution view. This does not delete the domain's intents or any associated knowledge sources, and the underlying rows are not removed from the database.

DELETE https://api.liyaengine.ai/dashboard/custom-domains/legal-contracts
Authorization: Bearer <jwt>

Intents

GET /dashboard/custom-domains/:domainKey/intents

GET https://api.liyaengine.ai/dashboard/custom-domains/legal-contracts/intents
Authorization: Bearer <jwt>

Response:

{
  "success": true,
  "data": {
    "intents": [
      {
        "id": "cint_01HZ...",
        "intent_key": "clause_extraction",
        "display_name": "Clause Extraction",
        "description": "Extracts key clauses from a contract",
        "prompt_template": "Extract all {{clause_type}} clauses from the following contract:\n\n{{contract_text}}",
        "output_schema": null,
        "is_active": true
      }
    ]
  }
}

POST /dashboard/custom-domains/:domainKey/intents

Requires the admin role or higher.

POST https://api.liyaengine.ai/dashboard/custom-domains/legal-contracts/intents
Authorization: Bearer <jwt>
Content-Type: application/json

{
  "intentKey": "clause_extraction",
  "displayName": "Clause Extraction",
  "description": "Extracts key clauses from a contract",
  "promptTemplate": "Extract all {{clause_type}} clauses from the following contract:\n\n{{contract_text}}",
  "outputSchema": {
    "clauses": "array of extracted clause objects",
    "summary": "brief summary of findings"
  }
}
FieldTypeRequiredDescription
intentKeystringYesUsed in the API path
displayNamestringYesHuman-readable name
descriptionstringYesThe intent's goal — rejected with 400 INVALID_INPUT if blank
promptTemplatestringYesPrompt with {{variable}} placeholders for input fields
outputSchemaobjectNoDescribes expected output structure — used for documentation only
inputSchemaobjectNoJSON Schema the intent's input object is validated against at execution time
guardrailsConfigobjectNoPer-intent guardrails override

The response wraps the created row as stored (snake_case fields, same shape as the intents array above) under data.intent.

Variables in promptTemplate (e.g. {{contract_text}}) become required input fields when calling the intent via the v1 API.


Calling a custom domain intent

Once created, custom intents use the same runtime contract as the sample domains:

POST https://api.liyaengine.ai/v1/legal-contracts/clause_extraction
Authorization: Bearer liya_prod_...
Content-Type: application/json

{
  "input": {
    "clause_type": "termination",
    "contract_text": "This Agreement may be terminated by either party..."
  },
  "options": {
    "session_id": "sess_01HZ..."
  }
}

See Defining Intents for full details on prompt templates and variable mapping.

On this page