{
  "openapi": "3.1.1",
  "info": {
    "title": "Landbot AI Agents",
    "version": "3.0.0",
    "description": "The AI agent an `ai_agent` block runs. Make one, read it, change it, copy it.\n\n**Two addresses, and nothing below them.** The collection, and one agent by id. Anything deeper —\nan agent's threads, its REST actions — answers `404` here.\n\n**The bodies are not in this document.** `GET /ai-agents/schema` serves them. Read that before\nyou send anything: it lists more paths than you can reach from here, and only the ones below are\nyours to call.\n\n**What an agent knows is under `/knowledge`.** An agent answers `knowledge.repository_id`: that is\nthe `knowledge_id` its sources are listed and added under. Unlike the agent, those bodies are\ndescribed here.\n"
  },
  "servers": [
    {
      "url": "https://api.landbot.io/v3",
      "description": "Public"
    },
    {
      "url": "/api/v3",
      "description": "Same-origin, as used by the builder"
    }
  ],
  "tags": [
    {
      "name": "Agents",
      "description": "The agent a block runs"
    },
    {
      "name": "Knowledge",
      "description": "What an agent knows, source by source"
    }
  ],
  "security": [
    {
      "sessionCookie": []
    },
    {
      "bearerToken": []
    },
    {
      "agentToken": []
    }
  ],
  "paths": {
    "/ai-agents": {
      "post": {
        "tags": [
          "Agents"
        ],
        "summary": "Make an agent",
        "operationId": "createAgent",
        "x-implemented": true,
        "description": "Creates an agent and answers it.\n\nNeeds the permission to edit bots. Counts against your brand's write limit.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentPayload"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "default": {
            "$ref": "#/components/responses/CarriedOn"
          }
        }
      }
    },
    "/ai-agents/{agent_id}": {
      "parameters": [
        {
          "name": "agent_id",
          "in": "path",
          "required": true,
          "description": "The agent, as `assistantId` names it in an `ai_agent` block.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "Read an agent",
        "operationId": "getAgent",
        "x-implemented": true,
        "description": "Answers the agent.\n\nNeeds the permission to view bots. Does not count against your brand's write limit.\n",
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "default": {
            "$ref": "#/components/responses/CarriedOn"
          }
        }
      },
      "put": {
        "tags": [
          "Agents"
        ],
        "summary": "Replace an agent",
        "operationId": "replaceAgent",
        "x-implemented": true,
        "description": "Replaces the agent **whole**. Anything the body leaves out goes back to its default, so send\nthe fields you want kept.\n\nNeeds the permission to edit bots. Counts against your brand's write limit.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentPayload"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "default": {
            "$ref": "#/components/responses/CarriedOn"
          }
        }
      },
      "post": {
        "tags": [
          "Agents"
        ],
        "summary": "Copy an agent",
        "operationId": "copyAgent",
        "x-implemented": true,
        "description": "Makes a copy of this agent and answers the copy.\n\nNeeds the permission to edit bots. Counts against your brand's write limit.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentPayload"
              }
            }
          }
        },
        "responses": {
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "default": {
            "$ref": "#/components/responses/CarriedOn"
          }
        }
      }
    },
    "/ai-agents/schema": {
      "get": {
        "tags": [
          "Agents"
        ],
        "summary": "The bodies the operations above take",
        "operationId": "getAgentsSchema",
        "x-implemented": true,
        "description": "The OpenAPI document of the API that owns agents, as it generates it.\n\nIts paths are its own, and it lists more than you can reach from here. Read it for the shape\nof a body; read this document for what you may call.\n",
        "responses": {
          "200": {
            "description": "An OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          }
        }
      }
    },
    "/knowledge/{knowledge_id}/sources": {
      "parameters": [
        {
          "name": "knowledge_id",
          "in": "path",
          "required": true,
          "description": "The agent's knowledge, as it answers `knowledge.repository_id`.",
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "tags": [
          "Knowledge"
        ],
        "summary": "List what an agent knows",
        "operationId": "listKnowledgeSources",
        "x-implemented": true,
        "description": "Answers every source of the knowledge, with how far it has been read. A source starts\n`pending`, and the agent answers from it once it is `finished`. `failed` carries\n`fail_reason`. There is no push: list again every few seconds until nothing is `pending` or\n`updating`.\n\nNeeds the permission to view bots. Does not count against your brand's write limit.\n",
        "responses": {
          "200": {
            "description": "The sources",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceListResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NoSuchKnowledge"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "502": {
            "$ref": "#/components/responses/KnowledgeFailed"
          }
        }
      },
      "post": {
        "tags": [
          "Knowledge"
        ],
        "summary": "Teach an agent something",
        "operationId": "addKnowledgeSource",
        "x-implemented": true,
        "description": "Adds a source, and answers it `pending`: it is read in the background, so list the sources\nuntil it is `finished` or `failed`. It is live as soon as it is read. Knowledge has no draft,\nso an agent that is already published answers from it too.\n\n`text` is a text you write, up to 200,000 characters. `website` is a page the agent reads from\n`url`. A link to a document served as PDF, Word, Markdown, RTF, plain text or HTML is read the\nsame way, for what it says. `document` is a file you upload, sent as `multipart/form-data`:\na `.pdf`, `.docx`, `.txt`, `.md`, `.rtf` or `.html` of up to 5 MB, named after the file unless\nyou give it a `name`.\n\nNeeds the permission to edit bots. Counts against your brand's write limit.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NewKnowledgeSource"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/NewKnowledgeDocument"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The source, waiting to be read",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeSourceResponse"
                }
              }
            }
          },
          "400": {
            "description": "The body could not be read. Keyed by the field at fault.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NoSuchKnowledge"
          },
          "422": {
            "$ref": "#/components/responses/SourceNotAccepted"
          },
          "429": {
            "$ref": "#/components/responses/RateExceeded"
          },
          "502": {
            "$ref": "#/components/responses/KnowledgeFailed"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "sessionid",
        "description": "Same-origin session, used by the builder."
      },
      "bearerToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "An OAuth token."
      },
      "agentToken": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Your agent token, sent as `Token <value>`. This is how the public API is reached."
      }
    },
    "responses": {
      "CarriedOn": {
        "description": "What the API that owns agents answered: its status and its body, unchanged.\n",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "Unauthorized": {
        "description": "No credentials, or credentials that name nobody.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DetailError"
            }
          }
        }
      },
      "Forbidden": {
        "description": "You are signed in and may not do this. Reading needs the permission to view bots, every write\nthe one to edit them. A brand that is disabled or locked is refused either way, and an expired\none on a write.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DetailError"
            }
          }
        }
      },
      "RateExceeded": {
        "description": "Too many requests. Two limits apply: one on how fast you call, which counts every request,\nand one on how many writes your brand makes in its window. Reading can only hit the first.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/DetailError"
            }
          }
        }
      },
      "NoSuchKnowledge": {
        "description": "No such knowledge, or not yours. Both answer identically, with the code `knowledge_not_found`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "SourceNotAccepted": {
        "description": "We understood you and refused the source, with the code `knowledge_source_not_accepted`. The\nmessage says why: a type that cannot be added, a field the type needs, a text that is blank or\nover 200,000 characters, a URL that is not one, a `refresh_interval` that is not one of the\nfive, a document of a type that is not read or over 5 MB, a `file` sent with any type but\n`document`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "KnowledgeFailed": {
        "description": "The service that keeps knowledge failed, with the code `knowledge_failed`. Retrying is\nreasonable, but a source being added may have been added anyway: list the sources before you\nadd it again.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "schemas": {
      "NewKnowledgeSource": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "text",
              "website"
            ]
          },
          "name": {
            "type": "string",
            "description": "What the source is called. Needed for `text`; a `website` without one is named after its\nURL.\n"
          },
          "text": {
            "type": "string",
            "description": "The text, for `text`."
          },
          "url": {
            "type": "string",
            "description": "The page or the document, for `website`."
          },
          "refresh_interval": {
            "type": "string",
            "enum": [
              "never",
              "daily",
              "weekly",
              "biweekly",
              "monthly"
            ],
            "default": "never",
            "description": "How often a `website` is read again."
          }
        }
      },
      "NewKnowledgeDocument": {
        "type": "object",
        "required": [
          "type",
          "file"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "document"
            ]
          },
          "file": {
            "contentMediaType": "application/octet-stream",
            "description": "The document, as a part that carries its file name. Its extension says what it is. Only a\n`document` takes one: a `file` sent with another type is refused.\n"
          },
          "name": {
            "type": "string",
            "description": "What the source is called. The file's name without its extension when left out."
          }
        }
      },
      "KnowledgeSourceResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/KnowledgeSource"
          }
        }
      },
      "KnowledgeSourceListResponse": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeSource"
            }
          }
        }
      },
      "KnowledgeSource": {
        "type": "object",
        "required": [
          "id",
          "type",
          "name",
          "status",
          "refresh_interval",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "website",
              "document"
            ]
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "updating",
              "finished",
              "failed"
            ]
          },
          "fail_reason": {
            "type": "string",
            "description": "Why reading it failed. Only on a `failed` source.",
            "examples": [
              "crawl_error"
            ]
          },
          "refresh_interval": {
            "type": "string",
            "enum": [
              "never",
              "daily",
              "weekly",
              "biweekly",
              "monthly"
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "Timestamp": {
        "type": "string",
        "description": "A moment, in UTC, written as `YYYY-MM-DDTHH:MM:SS`. It carries no offset and no fraction of a\nsecond, so a client that reads it as local time is wrong by whatever its own offset is.\n",
        "examples": [
          "2026-10-08T14:57:40"
        ]
      },
      "ErrorResponse": {
        "type": "object",
        "description": "A refusal with a code to branch on.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "AgentPayload": {
        "type": "object",
        "additionalProperties": true,
        "description": "Whatever the agents API takes. `GET /ai-agents/schema` describes it."
      },
      "DetailError": {
        "type": "object",
        "description": "A refusal. It carries a message and nothing to branch on: the status is the whole of it.\n",
        "required": [
          "detail"
        ],
        "properties": {
          "detail": {
            "type": "string",
            "examples": [
              "Authentication credentials were not provided."
            ]
          }
        }
      }
    }
  },
  "x-ext-urls": {}
}