> ## Documentation Index
> Fetch the complete documentation index at: https://docs.morphllm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Compact API

> Compress chat history and code context at 33,000 tok/s with byte-identical output

## Overview

Compact compresses chat history and code context at **33,000 tok/s** by removing irrelevant lines. Every surviving line is byte-for-byte identical to the original input. 100K tokens compresses in under 2 seconds.

Pass `query` to tell the model what matters for the next LLM call. Without it, the model auto-detects from the last user message.

## Usage Examples

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { MorphClient } from '@morphllm/morphsdk';

  const morph = new MorphClient({ apiKey: "YOUR_API_KEY" });

  const result = await morph.compact({
    input: chatHistory,
    query: "How do I validate JWT tokens?",
    compressionRatio: 0.5,
    preserveRecent: 3,
  });

  // result.output is the compressed text — pass it to your LLM
  ```

  ```python Python (OpenAI SDK) theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="YOUR_API_KEY",
      base_url="https://api.morphllm.com/v1",
  )

  response = client.chat.completions.create(
      model="morph-compactor",
      messages=[{"role": "user", "content": chat_history}],
  )

  compressed = response.choices[0].message.content
  ```

  ```python Python (requests) theme={null}
  import requests

  response = requests.post(
      "https://api.morphllm.com/v1/compact",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={
          "input": source_code,
          "query": "authentication",
          "compression_ratio": 0.5,
          "preserve_recent": 0,
      },
  )

  data = response.json()
  print(data["output"])

  for r in data["messages"][0]["compacted_line_ranges"]:
      print(f"  lines {r['start']}-{r['end']} removed")
  ```

  ```bash cURL theme={null}
  curl -X POST "https://api.morphllm.com/v1/compact" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "input": "def hello():\n    return 1\n\ndef unused():\n    pass\n\ndef world():\n    return 2",
      "query": "hello function",
      "compression_ratio": 0.5,
      "preserve_recent": 0
    }'
  ```
</CodeGroup>

## keepContext Tags

Wrap sections you never want compressed in `<keepContext>` / `</keepContext>` tags. Tagged content survives compression verbatim regardless of the compression ratio.

```
<keepContext>
// CRITICAL: Auth middleware — do not compress
function authenticate(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token' });
  req.user = jwt.verify(token, process.env.JWT_SECRET);
  next();
}
</keepContext>
```

The response includes `kept_line_ranges` showing which lines were force-preserved.

## Compatible Endpoints

Compact also works through OpenAI-compatible endpoints with `model: "morph-compactor"`:

| Endpoint                    | Format                  | Use with                                     |
| --------------------------- | ----------------------- | -------------------------------------------- |
| `POST /v1/compact`          | Native Morph format     | Direct HTTP, Morph SDK                       |
| `POST /v1/responses`        | OpenAI Responses API    | Any OpenAI SDK (`client.responses.create()`) |
| `POST /v1/chat/completions` | OpenAI Chat Completions | Any OpenAI-compatible client                 |

See the full [Compact documentation](/sdk/components/compact) for SDK reference, best practices, and advanced usage.


## OpenAPI

````yaml POST /v1/compact
openapi: 3.1.0
info:
  title: Morph API
  version: 1.1.0
  description: >-
    The Morph public API at api.morphllm.com: OpenAI- and Anthropic-compatible
    inference (chat completions, messages), Fast Apply code editing, Compact
    context compression, Reflex classification, and fine-tuning. Model ids,
    prices, and context windows are served live at
    https://www.morphllm.com/api/models/json.
  contact:
    name: Morph
    url: https://morphllm.com
    email: info@morphllm.com
  license:
    name: Proprietary
    url: https://morphllm.com/privacy/tos
servers:
  - url: https://api.morphllm.com
    description: Production
security: []
tags:
  - name: chat
    description: >-
      OpenAI- and Anthropic-compatible chat inference, including Fast Apply and
      WarpGrep models.
  - name: compact
    description: Context compression for long agent conversations.
  - name: reflex
    description: 'Per-turn classifiers: realtime prediction and batches.'
  - name: fine-tuning
    description: Reflex fine-tuning job lifecycle.
  - name: models
    description: Model listing and management.
  - name: telemetry
    description: Usage reporting hooks.
paths:
  /v1/compact:
    post:
      tags:
        - compact
      summary: Compact context
      description: >-
        Compress chat history and code context by removing irrelevant lines at
        33,000 tok/s. Every surviving line is byte-for-byte identical to the
        original input. Accepts string input or message arrays.
      operationId: createCompaction
      requestBody:
        description: Compact request with text or messages to compress
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CompactRequest'
      responses:
        '200':
          description: Compact response with compressed output and metadata
          content:
            application/json:
              example:
                id: cmpr-7373faf8af65
                object: compact
                model: morph-compactor
                output: |-
                  def hello():
                      return 1
                  (filtered 3 lines)
                  def world():
                      return 2
                messages:
                  - role: user
                    content: |-
                      def hello():
                          return 1
                      (filtered 3 lines)
                      def world():
                          return 2
                    compacted_line_ranges:
                      - start: 4
                        end: 6
                    kept_line_ranges: []
                usage:
                  input_tokens: 101
                  output_tokens: 65
                  compression_ratio: 0.644
                  processing_time_ms: 109
              schema:
                $ref: '#/components/schemas/CompactResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - bearerAuth: []
components:
  schemas:
    CompactRequest:
      type: object
      properties:
        input:
          type: string
          default: |-
            def hello():
                return 1

            def unused():
                pass

            def world():
                return 2
          description: Text to compact. One of `input` or `messages` is required.
          example: |-
            def hello():
                return 1

            def unused():
                pass

            def world():
                return 2
        messages:
          type: array
          items:
            $ref: '#/components/schemas/CompactInputMessage'
          description: Conversation messages to compact. Takes priority over `input`.
          example:
            - role: user
              content: Help me build a Node.js API with JWT auth
        query:
          type: string
          default: hello function
          description: >-
            Focus query for relevance-based pruning. Lines relevant to this
            query are kept.
          example: hello function
        compression_ratio:
          type: number
          default: 0.5
          description: Fraction of input to keep. 0.3 = aggressive, 0.7 = light.
          example: 0.5
        preserve_recent:
          type: integer
          default: 2
          description: Keep last N messages uncompressed.
          example: 0
        compress_system_messages:
          type: boolean
          default: false
          description: >-
            When true, system messages are also compressed. By default they are
            preserved verbatim.
          example: false
        include_line_ranges:
          type: boolean
          default: true
          description: Include compacted_line_ranges in response.
          example: true
        include_markers:
          type: boolean
          default: true
          description: >-
            Include (filtered N lines) text markers. When false, gaps become
            empty lines.
          example: true
        model:
          type: string
          default: morph-compactor
          description: Model ID.
          example: morph-compactor
      title: Compact
      description: >-
        Text or conversation to compress, plus the knobs controlling how
        aggressively lines are pruned.
      example:
        input: |-
          def hello():
              return 1

          def unused():
              pass

          def world():
              return 2
        messages:
          - role: user
            content: Help me build a Node.js API with JWT auth
        query: hello function
        compression_ratio: 0.5
        preserve_recent: 0
        compress_system_messages: false
        include_line_ranges: true
        include_markers: true
        model: morph-compactor
    CompactResponse:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the compact request
          example: cmpr-7373faf8af65
        object:
          type: string
          description: Object type, always `compact`
          example: compact
        model:
          type: string
          description: Model used
          example: morph-compactor
        output:
          type: string
          description: All compacted messages joined into a single string
          example: |-
            def hello():
                return 1
            (filtered 3 lines)
            def world():
                return 2
        messages:
          type: array
          items:
            $ref: '#/components/schemas/CompactOutputMessage'
          description: Per-message compaction results
          example:
            - role: user
              content: |-
                def hello():
                    return 1
                (filtered 3 lines)
                def world():
                    return 2
              compacted_line_ranges:
                - start: 4
                  end: 6
              kept_line_ranges: []
        usage:
          $ref: '#/components/schemas/CompactUsage'
      required:
        - id
        - object
        - model
        - output
        - messages
        - usage
      description: Compacted output, per-message line ranges, and usage statistics.
      example:
        id: cmpr-7373faf8af65
        object: compact
        model: morph-compactor
        output: |-
          def hello():
              return 1
          (filtered 3 lines)
          def world():
              return 2
        messages:
          - role: user
            content: |-
              def hello():
                  return 1
              (filtered 3 lines)
              def world():
                  return 2
            compacted_line_ranges:
              - start: 4
                end: 6
            kept_line_ranges: []
        usage:
          input_tokens: 101
          output_tokens: 65
          compression_ratio: 0.644
          processing_time_ms: 109
    CompactInputMessage:
      type: object
      properties:
        role:
          type: string
          enum:
            - system
            - user
            - assistant
          description: >-
            Role of the author of this message. System messages are preserved
            verbatim unless `compress_system_messages` is set.
          example: user
        content:
          type: string
          description: >-
            Text of this message, from which the compactor prunes irrelevant
            lines
          example: Help me build a Node.js API with JWT auth
      required:
        - role
        - content
      description: A single conversation message submitted for compaction.
      example:
        role: user
        content: Help me build a Node.js API with JWT auth
    CompactOutputMessage:
      type: object
      properties:
        role:
          type: string
          description: Role carried over from the corresponding input message
          example: user
        content:
          type: string
          description: The compacted message content with irrelevant lines removed
          example: |-
            def hello():
                print("hello world")
            (filtered 6 lines)
            def world():
                return 42
        compacted_line_ranges:
          type: array
          items:
            $ref: '#/components/schemas/CompactLineRange'
          description: >-
            Line ranges that were removed during compaction (1-indexed,
            inclusive)
          example:
            - start: 5
              end: 10
        kept_line_ranges:
          type: array
          items:
            $ref: '#/components/schemas/CompactLineRange'
          description: >-
            Line ranges force-preserved via `<keepContext>` tags (1-indexed,
            inclusive)
          example: []
      required:
        - role
        - content
      description: >-
        Per-message compaction result. Every surviving line is byte-for-byte
        identical to the corresponding input line.
      example:
        role: user
        content: |-
          def hello():
              print("hello world")
          (filtered 6 lines)
          def world():
              return 42
        compacted_line_ranges:
          - start: 5
            end: 10
        kept_line_ranges: []
    CompactUsage:
      type: object
      properties:
        input_tokens:
          type: integer
          description: Number of tokens in the text submitted for compaction
          example: 101
        output_tokens:
          type: integer
          description: Number of tokens in the compacted output
          example: 65
        compression_ratio:
          type: number
          description: Actual compression ratio achieved (output_tokens / input_tokens)
          example: 0.644
        processing_time_ms:
          type: integer
          description: Processing time in milliseconds
          example: 109
      required:
        - input_tokens
        - output_tokens
        - compression_ratio
        - processing_time_ms
      description: Usage statistics — token counts and timing for a single compaction.
      example:
        input_tokens: 101
        output_tokens: 65
        compression_ratio: 0.644
        processing_time_ms: 109
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              example: invalid_request_error
              description: Machine-readable error code.
            message:
              type: string
              example: The request body is missing the `model` field.
              description: Human-readable explanation of the failure.
          required:
            - code
            - message
      required:
        - error
      description: Standard error envelope returned by every non-2xx response.
      example:
        error:
          code: invalid_request_error
          message: The request body is missing the `model` field.
    CompactLineRange:
      type: object
      properties:
        start:
          type: integer
          description: Start line number (1-indexed, inclusive)
          example: 5
        end:
          type: integer
          description: End line number (1-indexed, inclusive)
          example: 10
      required:
        - start
        - end
      description: A contiguous range of lines, 1-indexed and inclusive on both ends.
      example:
        start: 5
        end: 10
  responses:
    BadRequest:
      description: Malformed request — missing or invalid fields.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: invalid_request_error
              message: The request body is missing the `model` field.
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Invalid API key provided.
    RateLimited:
      description: Rate limited — retry after the interval in the Retry-After header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: Too many requests. Retry in 12 seconds.
    InternalError:
      description: Internal error — safe to retry with backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: internal_error
              message: Something went wrong on our side.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: opaque
      description: >-
        Morph API key, passed as `Authorization: Bearer sk-...`. Create keys at
        https://www.morphllm.com/dashboard/api-keys.

````