---
title: "Create a context_attachment from an inline text payload (≤16KB)"
method: POST
path: "/documents/{document_id}/context-attachments"
tags: ["context-attachments"]
---

# Create a context_attachment from an inline text payload (≤16KB)

`POST /documents/{document_id}/context-attachments`

Create a context_attachment on the given document using a JSON body. For payloads larger than 16 KB use the multipart `/upload` variant of this endpoint.

**Channel vs type:** any `type` value (`author_note` or `json_schema`) can be created via either channel — the channel is a function of payload size, not attachment kind.

**Note on the 16 KB cap:** byte-size enforcement happens at the Pydantic validator layer (before the route handler runs), so oversized `content_text` surfaces as a `422` with the Pydantic error detail, not the route's stable `{code, ...}` shape. The multipart `/upload` path emits `413 ATTACHMENT_FILE_TOO_LARGE` in-handler when its 80 KB cap is exceeded — that's the dedicated stable code for oversize payloads. Inline >16KB is a 422.

## Path parameters

- `document_id` string, uuid, required

## Request body

- ContextAttachmentCreateRequest — JSON body for ``POST /documents/{document_id}/context-attachments``. Only the inline (small text) path. Files larger than 16 KB use the multipart variant of the same endpoint, which does NOT consume this schema — FastAPI ``Form`` + ``UploadFile`` parse those requests directly. ``extra='forbid'`` rejects unknown fields with a 422 instead of silently ignoring them. This mirrors the discipline applied to ``IngestionRequest`` and keeps integrator typos visible at the boundary.
  - `type` 'author_note' | 'json_schema', required — Vocabulary label for the attachment. scipot-core does NOT interpret the payload by type — both kinds are opaque typed strings to the extraction pipeline. The label flows into the prompt framing ('=== [json_schema: Eightfold v3] ===').
  - `name` string, required — Human-readable label shown to curators ('Eightfold schema v3').
  - `content_text` string, required — Inline UTF-8 text payload. Max 16 KB by encoded byte size. Payloads larger than 16 KB are rejected by this schema's validator and surface as a 422 with the Pydantic error detail — use the multipart `/upload` variant of the endpoint for larger payloads (it returns 413 ATTACHMENT_FILE_TOO_LARGE for files > 80 KB).
  - `mime_type` 'text/plain' | 'application/json' | 'application/schema+json', nullable — Optional MIME type. Defaults to 'text/plain' for author_note and 'application/schema+json' for json_schema when omitted.

## Response `201`

Attachment created

- ContextAttachment — Persisted attachment item — used as both repository row shape and response body for create/list endpoints. DynamoDB key layout: PK = WORKSPACE#{workspace_id} SK = CONTEXTATTACH#{document_id}#{attachment_id} Listing all attachments for a document is a single ``Query(PK = WORKSPACE#..., SK begins_with CONTEXTATTACH#{document_id}#)``. Deletion by attachment_id reconstructs the SK from the path (``/documents/{document_id}/context-attachments/{attachment_id}``) — no GSI lookup required.
  - `attachment_id` string, uuid — UUIDv7 — chronologically sortable. Stable order for prompt assembly.
  - `workspace_id` string, uuid, required — Owning workspace; multi-tenant isolation key.
  - `document_id` string, uuid, required — Document this attachment travels with.
  - `type` 'author_note' | 'json_schema', required — Vocabulary label (see CreateRequest).
  - `name` string, required
  - `content_text` string, nullable — Set for inline (≤16KB) attachments. Mutually exclusive with s3_key — see the model_validator below.
  - `s3_key` string, nullable — Set for >16KB attachments stored on the FileStorageBackend. Mutually exclusive with content_text. The repository computes this; callers never set it via the create endpoint.
  - `mime_type` 'text/plain' | 'application/json' | 'application/schema+json', required — MIME type of the payload (text/plain | application/json | application/schema+json).
  - `byte_size` integer, required — Encoded UTF-8 byte size of the payload. Used for cap math at extract time.
  - `created_at` string, date-time

## Other responses

- `404` — Document not found in workspace
- `422` — Validation error: 5-per-doc cap exceeded (`ATTACHMENT_CAP_EXCEEDED`), unknown fields (extra='forbid'), XOR violation, content_text > 16 KB (Pydantic validation), etc.

---

[API](https://skmtc.dev/scipot/apis/scipot-core-api.md) · [All operations](https://skmtc.dev/scipot/apis/scipot-core-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/scipot/scipot-core-api/revisions/e8712e9ffeae/schema)
