Chat Completions

Generate a chat completion from one or more messages, with optional streaming. The model searches your team’s document libraries and returns an answer grounded in those sources, together with citations.

POST /api/chat/completions

Authentication

Requires a Bearer token. See Getting Started.

Authorization: Bearer <your-api-key>

Request body

FieldTypeDefaultDescription
model"vulgate-1" | "vulgate"RequiredModel to use. Both values behave identically.
messagesMessage[]RequiredConversation messages. See Message format.
streambooleanfalseEnable server-sent events (SSE) streaming.
max_tokensintegerMaximum tokens in the response. Range: 1–128 000.
temperaturenumberSampling temperature. Range: 0–2.
top_pnumberNucleus sampling threshold. Range: 0–1.
reasoning_effortstring"medium"How much reasoning the model should perform. One of "minimal", "low", "medium", "high".
return_citationsbooleantrueInclude source citations in the response. Vulgate-specific.
stopstring | string[]Accepted for compatibility but not currently supported.
response_formatobjectOnly { "type": "text" } is supported.

Fields marked with — in the Default column use the model’s own defaults when omitted.

Message format

Each message has a role ("system", "user", or "assistant") and content. The content field can be a plain string or an array of typed parts for multimodal input.

Text

{ "role": "user", "content": "What does Aquinas say about natural law?" }

Or, using the parts array:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "What does Aquinas say about natural law?" }
  ]
}

Image input

Pass an image URL using the image_url part type:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "What does this diagram represent?" },
    { "type": "image_url", "image_url": "https://example.com/diagram.png" }
  ]
}

The image_url field also accepts an object form:

{ "type": "image_url", "image_url": { "url": "https://example.com/diagram.png" } }

File input

Attach a file using the file_url part type. You can optionally provide a file_name to help the model identify the document:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "Summarize this document." },
    { "type": "file_url", "file_url": "https://example.com/paper.pdf", "file_name": "paper.pdf" }
  ]
}

The file_url field also accepts an object form:

{ "type": "file_url", "file_url": { "url": "https://example.com/paper.pdf" }, "file_name": "paper.pdf" }

Response

Non-streaming

When stream is false (the default), the API returns a single JSON object:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1741200000,
  "model": "vulgate-1",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Thomas Aquinas defines natural law as..."
      },
      "finish_reason": "stop"
    }
  ],
  "citations": [
    {
      "cited_text": "<p>Natural law is a participation of the eternal law...</p>",
      "document_title": "Summa Theologiae",
      "document_index": 0,
      "document_author": "Thomas Aquinas",
      "source_url": null
    }
  ]
}
FieldTypeDescription
idstringUnique completion ID.
objectstringAlways "chat.completion".
createdintegerUnix timestamp of creation.
modelstringModel used.
choicesarrayArray containing the completion.
choices[].messageobjectThe assistant’s response (role + content).
choices[].finish_reasonstring | nullWhy generation stopped: "stop", "length", or null.
citationsCitation[]Source citations. See Citations. Omitted when return_citations is false.

Streaming

When stream is true, the API returns server-sent events (SSE). Each event contains a JSON chunk with incremental content:

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1741200000,"model":"vulgate-1","choices":[{"index":0,"delta":{"content":"Thomas "},"finish_reason":null}]}

data: {"id":"chatcmpl-abc123","object":"chat.completion.chunk","created":1741200000,"model":"vulgate-1","choices":[{"index":0,"delta":{"content":"Aquinas "},"finish_reason":null}]}

data: [DONE]
  • Text chunks have choices[0].delta.content with the next piece of text. Clients should not assume every event carries text content.
  • The stream ends with data: [DONE].
  • Citations, if enabled, are sent as a final event before [DONE] in a citations field.

Citations

The citations array is a Vulgate-specific extension to the OpenAI format. Each citation references a source passage from your document libraries.

FieldTypeDescription
cited_textstringHTML content of the cited passage.
document_titlestring | nullTitle of the source document.
document_indexintegerPosition of this citation in the list.
document_authorstring | nullAuthor of the source document.
source_urlstring | nullLink to the source, if available.

Set return_citations to false in the request body to omit citations entirely.

Error codes

The API uses standard HTTP status codes. Below are the most common errors you may encounter:

HTTP StatusDescription
400Invalid request body. Returns a JSON validation error from the request schema.
401Missing or invalid API key.
429Rate limit exceeded. Includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.

Examples

Basic completion

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "messages": [
      { "role": "user", "content": "What is the Filioque clause?" }
    ]
  }'

Multi-turn conversation

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "messages": [
      { "role": "system", "content": "You are a theology research assistant." },
      { "role": "user", "content": "Explain the concept of transubstantiation." },
      { "role": "assistant", "content": "Transubstantiation is the teaching that..." },
      { "role": "user", "content": "How does the Orthodox view differ?" }
    ]
  }'

Streaming

curl -N -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "stream": true,
    "messages": [
      { "role": "user", "content": "Summarize Lumen Gentium chapter 2." }
    ]
  }'

Image input

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "What does this image depict?" },
          { "type": "image_url", "image_url": "https://example.com/icon.jpg" }
        ]
      }
    ]
  }'

File input

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "messages": [
      {
        "role": "user",
        "content": [
          { "type": "text", "text": "Summarize this document." },
          { "type": "file_url", "file_url": "https://example.com/paper.pdf", "file_name": "paper.pdf" }
        ]
      }
    ]
  }'

Adjusting reasoning effort

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "reasoning_effort": "high",
    "messages": [
      { "role": "user", "content": "Compare Augustine and Pelagius on original sin, citing primary sources." }
    ]
  }'

Without citations

curl -X POST "https://vulgate.ai/api/chat/completions" \
  -H "Authorization: Bearer $VULGATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "vulgate-1",
    "return_citations": false,
    "messages": [
      { "role": "user", "content": "What are the seven sacraments?" }
    ]
  }'
Chat Completions | Vulgate AI