Knowledge bases

A knowledge base is a set of documents an AI agent searches while it talks: hours, prices, service areas, policies. The agent answers from it instead of guessing.

An id that belongs to another account answers 404, the same as one that doesn't exist.

Routes

Method Route Scope What it does
GET /document/public/knowledge-bases agents:read List knowledge bases
POST /document/public/knowledge-bases agents:write Create a knowledge base
GET /document/public/knowledge-bases/{knowledge_base_id} agents:read Get a knowledge base
POST /document/public/knowledge-bases/{knowledge_base_id} agents:write Update a knowledge base
POST /document/public/knowledge-bases/{knowledge_base_id}/documents agents:write Add a document
POST /document/public/knowledge-bases/{knowledge_base_id}/documents/{knowledge_document_id}/uploaded agents:write Confirm an upload
POST /document/public/knowledge-bases/{knowledge_base_id}/documents/{knowledge_document_id}/upload-url agents:write Get a new upload URL
GET /document/public/knowledge-bases/{knowledge_base_id}/documents agents:read List documents
POST /document/public/knowledge-bases/{knowledge_base_id}/query agents:read Search a knowledge base
DELETE /document/public/knowledge-bases/{knowledge_base_id}/documents/{knowledge_document_id} agents:write Delete a document
DELETE /document/public/knowledge-bases/{knowledge_base_id} agents:write Delete a knowledge base

List knowledge bases

Field Type Required Description
search string No Matches the name.
ai_audience string No public or internal.
status string No active (the default) or archived.
sort_by string No name, created_at or updated_at. Default updated_at.
sort_order string No asc or desc. Default desc.
limit integer No Page size, 1 to 100. Default 25.
offset integer No Items to skip. Default 0.
curl "https://api-v2.dropcowboy.com/document/public/knowledge-bases?search=faq" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

data is an array of knowledge bases, shaped as below. meta.total, meta.limit and meta.offset describe the page (see Pagination).

Create a knowledge base

Field Type Required Description
name string Yes Up to 200 characters.
description string No Up to 2000 characters.
ai_audience string No public for content that may be read to callers. internal for agents that help your staff. Default internal.

Set ai_audience to public for a knowledge base a receptionist or an AI call answers from. Agents search public knowledge bases unless you tell them otherwise (see Attach to an agent).

curl -X POST https://api-v2.dropcowboy.com/document/public/knowledge-bases \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{
    "name": "Customer FAQ",
    "description": "Hours, pricing and service area for callers.",
    "ai_audience": "public"
  }'

The route answers 201:

{
  "data": {
    "knowledge_base_id": "9d3f6a2c-4e8b-4b1d-a7c5-2f6e9b3d8a14",
    "name": "Customer FAQ",
    "description": "Hours, pricing and service area for callers.",
    "ai_audience": "public",
    "status": "active",
    "stats": { "document_count": 0, "ready_count": 0, "failed_count": 0, "chunk_count": 0 },
    "created_at": 1774041600000,
    "updated_at": 1774041600000
  },
  "meta": { "request_id": "8a2f6c1e-4d9b-4e7a-b3c5-6f1d8e2a9c47" }
}

Timestamps are epoch milliseconds. stats counts the documents and how many are ready or failed.

Get a knowledge base

GET /document/public/knowledge-bases/{knowledge_base_id} returns the knowledge base, shaped as above.

Update a knowledge base

Send only the fields to change: name, description, ai_audience, or status (active or archived). An archived knowledge base drops out of the default list.

curl -X POST https://api-v2.dropcowboy.com/document/public/knowledge-bases/9d3f6a2c-4e8b-4b1d-a7c5-2f6e9b3d8a14 \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{ "ai_audience": "public" }'

Add a document

One route, three ways. The fields you send pick the way. Each answers 201.

Inline markdown

Best for FAQs you already have as text. Send title and markdown, up to 1 MB.

curl -X POST "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{
    "title": "Hours and location",
    "markdown": "# Hours\n\nMonday to Friday, 8am to 6pm. Saturday, 9am to 1pm. Closed Sunday.\n\n# Location\n\n100 Example Street, Springfield."
  }'

From a URL

Send source_url, a public http or https address up to 2048 characters, with an optional title. Drop Cowboy® downloads the file, up to 25 MB.

{
  "source_url": "https://www.example.com/files/price-list.pdf",
  "title": "Price list"
}

If the server labels the file with a supported type, that type wins. Otherwise send mime_type too.

Upload a file

Three steps, for files up to 25 MB.

1. Ask for an upload ticket:

Field Type Required Description
filename string Yes A plain file name, up to 255 characters. Its extension must match mime_type.
mime_type string Yes A supported type.
byte_size integer Yes The file's size, up to 26214400 (25 MB).
title string No Defaults from the file name.
{
  "title": "Price list",
  "filename": "price-list.pdf",
  "mime_type": "application/pdf",
  "byte_size": 184320
}
{
  "data": {
    "knowledge_document_id": "5b8e1c4f-7a2d-4f9e-b3c6-8d1a5e2f7b40",
    "knowledge_document": { "ingest_status": "pending", "upload_confirmed": false },
    "upload": {
      "method": "PUT",
      "url": "https://uploads.example.com/knowledge/price-list.pdf?signature=example-signature",
      "headers": { "Content-Type": "application/pdf" },
      "max_bytes": 26214400
    }
  },
  "meta": { "request_id": "4d6f8a1c-3e5b-4c7d-9f2a-6b8d1e3f5a70" }
}

2. PUT the file to upload.url with exactly the headers in upload.headers. The URL is signed for that Content-Type and rejects any other. It expires after 48 hours. If it has expired, get a new upload URL.

curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @price-list.pdf

3. Confirm the upload.

Supported types

The file extension must match mime_type. Anything else answers 415.

Type Extensions
PDF .pdf
Word .doc, .docx
Excel .xls, .xlsx
PowerPoint .ppt, .pptx
Rich text, OpenDocument .rtf, .odt
Web page .html
Text, markdown, CSV, JSON .txt, .log, .md, .csv, .json

Confirm an upload

Confirm after the PUT succeeds. The route answers 200 and processing starts.

curl -X POST \
  "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents/$DOC_ID/uploaded" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Status Cause What to do
400 The file hasn't been uploaded. PUT the file, then confirm again.
409 already-confirmed The upload is already confirmed. Nothing. Watch ingest_status.
409 duplicate-knowledge-document The same file is already in this knowledge base. details.existing_knowledge_document_id names it. Use the existing document, or upload different bytes and confirm again.
413 The stored file is over 25 MB. Upload a smaller file and confirm again.

A refused duplicate or oversized file marks the document failed, with the reason in ingest_error. A later successful confirm clears it. To give up instead, delete the document.

Get a new upload URL

Use this when the upload URL expired before you used it, or when a confirm was refused and you want to send different bytes.

curl -X POST \
  "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents/$DOC_ID/upload-url" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

The route answers 200 with the same shape as the upload ticket. PUT and confirm exactly as before. A document marked failed by a refused confirm goes back to pending.

The route is safe to retry, and earlier URLs keep working until they expire. It works only until a confirm succeeds. After that, and for markdown and URL documents, it answers 409 (already-confirmed). To replace a confirmed document, delete it and add it again.

List documents

Every document is processed into searchable passages after it's added. Poll this list and check ingest_status. Only ready documents are searched.

Field Type Required Description
search string No Matches the title.
limit integer No Page size, 1 to 100. Default 25.
offset integer No Items to skip. Default 0.
curl "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents?limit=100" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

Each document carries knowledge_document_id, knowledge_base_id, title, filename, mime_type, byte_size, source, ai_audience, upload_confirmed, ingest_status, ingest_error, chunk_count, created_at and updated_at.

ingest_status Meaning What to do
pending Waiting to be processed, or for the upload to be confirmed. Confirm the upload if you haven't.
processing Being converted. Poll again in a few seconds.
ready Searchable. chunk_count shows how many passages it produced. Nothing.
failed Couldn't be processed. ingest_error says why. Fix the file and add it again.

Search a knowledge base

Before you attach a knowledge base, ask it the questions callers will ask. query is up to 1000 characters.

curl -X POST "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/query" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{ "query": "What are your hours on Saturday?" }'
{
  "data": {
    "query": "What are your hours on Saturday?",
    "results": [
      {
        "chunk_id": "7f4c2a9e-3b1d-4e6a-8c5f-9d2b7e1a4c36",
        "knowledge_base_id": "9d3f6a2c-4e8b-4b1d-a7c5-2f6e9b3d8a14",
        "knowledge_document_id": "2c7a9e4b-1d6f-4a3e-8b5c-7f2d9a6e1c83",
        "chunk_index": 0,
        "text": "Monday to Friday, 8am to 6pm. Saturday, 9am to 1pm. Closed Sunday.",
        "score": 0.87,
        "heading": "Hours",
        "section_path": "Hours",
        "page": null
      }
    ]
  },
  "meta": { "request_id": "6e8a1c3f-5b7d-4e9a-8c2f-1d3b5e7a9c42" }
}

These are the passages an agent would retrieve, best first. If the right passage is missing, improve the document before you attach it.

Delete a document

curl -X DELETE "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents/$DOC_ID" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

The route returns {"knowledge_document_id": "...", "deleted": true}.

Delete a knowledge base

curl -X DELETE "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"

The route returns {"knowledge_base_id": "...", "deleted": true}. Take the id out of any agent's think.knowledge and publish the agent again.

Attach to an agent

Set think.knowledge on the agent, then publish it:

{
  "think": {
    "prompt_spec": { "role": "Receptionist for Example Dental" },
    "knowledge": {
      "mode": "selected",
      "knowledge_base_ids": ["9d3f6a2c-4e8b-4b1d-a7c5-2f6e9b3d8a14"],
      "audience": "public"
    }
  }
}
Key Description
mode selected searches only knowledge_base_ids, and is the default when you give ids. all searches every knowledge base on the account with the matching audience.
knowledge_base_ids The knowledge bases to search.
audience public (the default) or internal. It must match the knowledge bases' ai_audience, or nothing is found.

Updating think replaces the whole object, so send the agent's existing think with knowledge added. Update an agent has a complete example.

Publishing checks the selected knowledge bases. It fails with 400 (unusable_knowledge_base) if their content reads like instructions for your staff ("click Settings, then...") rather than answers for callers, or tells callers to check an app for your hours without stating them. Write documents the way you want the agent to speak.

Errors

The errors specific to knowledge bases are below. For the error format and everything else, see Responses, errors and limits.

Status type ends with Cause What to do
400 missing-parameters, invalid-parameters, invalid-filename, invalid-request A field is missing or out of range. Fix the field named in detail.
400 url-required, url-invalid, url-protocol-blocked, url-credentials source_url is empty, malformed, not http or https, or has a user name or password in it. Send a plain public URL.
400 url-private-host, url-unresolvable The host is a private address, or doesn't resolve. Host the file publicly, or upload it instead.
400 empty-file The file or download was empty. Check the file.
403 forbidden A signed-in user's role doesn't allow it. See below. Ask an account admin to change the role, or use an API key.
404 not-found Unknown knowledge base or document. Check the id.
409 duplicate-knowledge-document, already-confirmed See Confirm an upload. See there.
413 payload-too-large, url-too-large Over 1 MB of markdown or 25 MB of file. Split the document.
415 unsupported-media-type Type not supported, or the extension doesn't match. Convert to a supported type.
502 url-fetch-failed, url-too-many-redirects The download failed. Check the URL works without a login, or upload the file.
504 url-timeout The download took too long. Upload the file instead.

A token issued for a signed-in user is checked against that user's role. API keys never are. A denial has detail You do not have permission to use Knowledge Bases. on reads and You do not have permission to manage Knowledge Bases. on changes:

{
  "type": "https://api-v2.dropcowboy.com/errors/forbidden",
  "title": "Forbidden",
  "status": 403,
  "detail": "You do not have permission to manage Knowledge Bases.",
  "instance": "/document/public/knowledge-bases",
  "request_id": "3c5e7a9b-1d2f-4a6c-8e0b-5f7d9a1c3e62"
}

If the role can't be looked up, the answer is 500. Retry.

Code samples

The requests from this page, ready to copy. Set DC_KEY and DC_SECRET to your API key pair first.

List knowledge bases
curl "https://api-v2.dropcowboy.com/document/public/knowledge-bases?search=faq" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Create a knowledge base
curl -X POST https://api-v2.dropcowboy.com/document/public/knowledge-bases \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{
    "name": "Customer FAQ",
    "description": "Hours, pricing and service area for callers.",
    "ai_audience": "public"
  }'
Update a knowledge base
curl -X POST https://api-v2.dropcowboy.com/document/public/knowledge-bases/9d3f6a2c-4e8b-4b1d-a7c5-2f6e9b3d8a14 \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{ "ai_audience": "public" }'
Inline markdown
curl -X POST "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET" \
  -H "content-type: application/json" \
  -d '{
    "title": "Hours and location",
    "markdown": "# Hours\n\nMonday to Friday, 8am to 6pm. Saturday, 9am to 1pm. Closed Sunday.\n\n# Location\n\n100 Example Street, Springfield."
  }'
Upload a file
curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @price-list.pdf
Confirm an upload
curl -X POST \
  "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents/$DOC_ID/uploaded" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
Get a new upload URL
curl -X POST \
  "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents/$DOC_ID/upload-url" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"
List documents
curl "https://api-v2.dropcowboy.com/document/public/knowledge-bases/$KB_ID/documents?limit=100" \
  -H "x-key: $DC_KEY" -H "x-secret: $DC_SECRET"