---
title: "Run an Architect turn (Chat Completions)"
method: POST
path: "/api/v1/chat/completions"
tags: ["Architect"]
---

# Run an Architect turn (Chat Completions)

`POST /api/v1/chat/completions`

## Request

- Base URL: `https://editor.pascal.app`
- URL: `https://editor.pascal.app/api/v1/chat/completions`
- Auth: HTTP bearer

OpenAI Chat Completions over one turn of the Architect on a project. The turn builds and edits the project’s scene. The reply is `content`; the readable reasoning (the model’s thinking and one line per step) is `reasoning_content`; a turn that changed the scene is saved as a named version, cited as a `url_citation` in `annotations` and named in `metadata.pascal_version*`. The last user message is the request, with its `image_url` and `file` parts; earlier messages the project’s conversation already holds are not repeated, and `system` and `developer` messages become instructions for this turn. With `stream: true` the response is a `text/event-stream` of `chat.completion.chunk` events (`delta.reasoning_content`, `delta.content`, the annotation on the last chunk, a usage chunk with `stream_options.include_usage`) ending with `data: [DONE]`, with `: keepalive` comments during silences. A turn can run for minutes; closing the connection stops it. Without `stream`, the headers leave within 15 s and spaces keep the connection open until the JSON body, so a turn that fails after that answers 200 with the error as the body. A question the Architect asks is the reply, and the next request answers it: `1`, `2`… picks an option. `metadata.commit_message` names the version the turn saves; `metadata.pascal_max_credits` caps the credits the turn may spend, and a turn that reaches it ends with `finish_reason: "length"`. Errors carry `x-should-retry: false`: a turn that started may already have edited the scene. A turn needs at least one credit in the project’s credit pool.

## Headers

- `X-Pascal-Project` string

## Request body

- ArchitectChatCompletionRequest
  - `model` 'architect' | 'architect-low' | 'architect-medium' | 'architect-high' | 'architect-pro', required: The Architect, at a reasoning effort: `architect` uses `reasoning_effort` (default medium); a suffix fixes it.
  - `messages` object[], required
    - `role` 'system' | 'developer' | 'user' | 'assistant', required
    - `content` union, required: Text, or content parts.
      - string
      - ArchitectContentPart[]
        - `type` string, required
  - `stream` boolean: Stream `chat.completion.chunk` events as server-sent events.
  - `stream_options` object
    - `include_usage` boolean
  - `reasoning_effort` 'minimal' | 'low' | 'medium' | 'high' | 'pro'
  - `metadata` object: `project_id` is an alternative to the `X-Pascal-Project` header; `pascal_max_credits` caps the credits the turn may spend.
    - `project_id` string
    - `pascal_max_credits` string: The most Pascal credits this turn may spend, a number above 0 sent as a string like every metadata value. No cap when absent; an invalid value is a 400. When the turn reaches it, it ends `incomplete` with `incomplete_details.reason: "max_credits"` (chat: `finish_reason: "length"`), and what it changed so far is saved as a version as usual. An architect-pro turn admits a model call only if its worst case fits under the cap, so its model calls never take it over; the time of the sandbox running its tools is billed after the fact and can. Every other turn is checked between its rounds of scene tools: once it has spent the cap it stops before the next round, so it can end above the cap by what its last round of model steps cost. A request that answers a question continues the turn under the cap the turn started with.

## Response `200`

Completion, or a server-sent event stream of `chat.completion.chunk` events when `stream` is true

- ArchitectChatCompletion
  - `id` string, required
  - `object` 'chat.completion', required
  - `created` integer, required
  - `model` string, required
  - `choices` object[], required
    - `index` integer
    - `finish_reason` string: `stop`, or `length` for a turn that stopped short.
    - `message` object
      - `role` 'assistant', required
      - `content` string, required
      - `reasoning_content` string
      - `annotations` object[]
        - `type` 'url_citation'
        - `url_citation` ArchitectUrlCitation: The version the turn saved, at the end of the reply.
          - `type` 'url_citation'
          - `start_index` integer
          - `end_index` integer
          - `title` string: "Version 7: 1 room added"
          - `url` string
  - `metadata` ArchitectPascalMetadata: The turn’s outcome, beside the caller’s own string metadata: `pascal_project_id`; `pascal_version`, `pascal_version_label` and `pascal_version_url` when the turn saved a version; `pascal_waiting: "question"` when the next request answers the Architect’s question.
  - `usage` ArchitectUsage, required
    - `prompt_tokens` integer
    - `completion_tokens` integer
    - `completion_tokens_details` object
      - `reasoning_tokens` integer
    - `total_tokens` integer

## Other responses

- `400`: OpenAI-shaped error, with `x-should-retry: false`: no error is retried. 400 invalid request, missing project, a file that can’t be sent, or `unsupported_parameter` (tools, structured output, `n` > 1) with its `param`; 401 invalid key; 403 `upgrade_required`; 404 unknown model, or project not found or not editable with this key; 409 `turn_in_progress` (naming the running `response_id`) or `previous_response_id` not on the project’s active conversation; 503 `executor_unavailable` on a deployment with no executor. The one retryable error is a `background` launch that failed before its turn ran (502, without the header).
- `401`: OpenAI-shaped error, with `x-should-retry: false`: no error is retried. 400 invalid request, missing project, a file that can’t be sent, or `unsupported_parameter` (tools, structured output, `n` > 1) with its `param`; 401 invalid key; 403 `upgrade_required`; 404 unknown model, or project not found or not editable with this key; 409 `turn_in_progress` (naming the running `response_id`) or `previous_response_id` not on the project’s active conversation; 503 `executor_unavailable` on a deployment with no executor. The one retryable error is a `background` launch that failed before its turn ran (502, without the header).
- `402`: The project’s credit pool (its workspace’s, else the key owner’s) cannot fund a turn. Returned before the turn starts, with `type` and `code` `insufficient_quota`.
- `404`: OpenAI-shaped error, with `x-should-retry: false`: no error is retried. 400 invalid request, missing project, a file that can’t be sent, or `unsupported_parameter` (tools, structured output, `n` > 1) with its `param`; 401 invalid key; 403 `upgrade_required`; 404 unknown model, or project not found or not editable with this key; 409 `turn_in_progress` (naming the running `response_id`) or `previous_response_id` not on the project’s active conversation; 503 `executor_unavailable` on a deployment with no executor. The one retryable error is a `background` launch that failed before its turn ran (502, without the header).
- `409`: OpenAI-shaped error, with `x-should-retry: false`: no error is retried. 400 invalid request, missing project, a file that can’t be sent, or `unsupported_parameter` (tools, structured output, `n` > 1) with its `param`; 401 invalid key; 403 `upgrade_required`; 404 unknown model, or project not found or not editable with this key; 409 `turn_in_progress` (naming the running `response_id`) or `previous_response_id` not on the project’s active conversation; 503 `executor_unavailable` on a deployment with no executor. The one retryable error is a `background` launch that failed before its turn ran (502, without the header).
- `503`: OpenAI-shaped error, with `x-should-retry: false`: no error is retried. 400 invalid request, missing project, a file that can’t be sent, or `unsupported_parameter` (tools, structured output, `n` > 1) with its `param`; 401 invalid key; 403 `upgrade_required`; 404 unknown model, or project not found or not editable with this key; 409 `turn_in_progress` (naming the running `response_id`) or `previous_response_id` not on the project’s active conversation; 503 `executor_unavailable` on a deployment with no executor. The one retryable error is a `background` launch that failed before its turn ran (502, without the header).

---

[API](https://skmtc.dev/pascal/apis/pascal-editor-scene-api.md) · [All operations](https://skmtc.dev/pascal/apis/pascal-editor-scene-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pascal/apis/pascal-editor-scene-api/revisions/08f1f3f41067?raw)
