{
  "openapi": "3.1.0",
  "info": {
    "title": "BusinessCraft API",
    "version": "1.0.0",
    "description": "Authenticated programmatic access to BusinessCraft.\nThe current v1 surface provides company discovery and Contract Documents operations.\n\n## Authentication\n\nEvery `/api/v1` endpoint requires an opaque Bearer token issued from\nUser Settings or from System > Admin > API. A token names one\nBusinessCraft user and carries no company of its own: each request\nre-resolves that user's company assignments, groups, permissions,\nenabled state, API eligibility, and the global API switch, so a change\nmade in the web app takes effect on the next request. A secret is shown\nonce at creation and stored only as a hash.\n\n## Permissions\n\nA company or contract operation requires access to the company plus the\nsame permission the Contract Documents screen enforces: menu access to\n`CO_CONSEL` for reads, and `CO` package code `C` for writes. A token\nwith company access but without that permission is denied.\n\n## Identifiers\n\n`documentId` is the canonical base-10 value of the mapped\n`CONLINW.CLW_SEQNUM`. `revisionId` is the canonical base-10 value of the\nmapped `MSGLINR.MLR_SEQ` for its parent document; the revision number\nitself (`MLR_REV`) is metadata, not an identifier. Neither id carries\npadding, and a padded form is rejected rather than normalised.\n\n## Concurrency\n\nA document response carries an opaque ETag computed from the complete\nmutable representation of its CONLINW row, including the mapped\ngenerated `CLW_MOD_STAMP` where the database has materialised one. A\nrevision response carries its own separate ETag over the MSGLINR row,\nwhich has creation fields and no modification fields. Both `PATCH`\nroutes require `If-Match`; a stale value answers `412`.\n\n## Idempotency\n\nEvery mutating request requires an `Idempotency-Key`. Repeating the same\nkey with the same content returns the original outcome and sets\n`Idempotent-Replay: true`. Reusing the key with different content is a\n`409`.\n\n## Pagination and bounds\n\nList responses use opaque forward cursors. The default page size is 100 and the maximum is 500.\n`compare` and `batch` accept at most 500 items per request.\nThere is no unbounded list option and no response carries a total.\nUpload endpoints accept one file per request within the company's\nconfigured document size and media-type limits.\n\n## Resume\n\nThe API is stateless: it holds no run, job, or checkpoint resource. A\nclient resumes an interrupted migration by replaying the opaque `cursor`\nit last received and reusing its `Idempotency-Key` values; per-item\nresults in `batch` and per-item outcomes in `compare` tell it what still\nneeds work.\n\n## Request limit\n\nEach token may make at most 600 requests every 60 seconds.\nThe counter is durable and shared across API instances. Exceeding it\nanswers `429` with `Retry-After` and a `rate_limited` error code. Every\nauthenticated `/api/v1` response carries `X-RateLimit-Limit`,\n`X-RateLimit-Remaining`, and `X-RateLimit-Reset`; an unauthenticated\nresponse carries none, because nothing was counted against a token."
  },
  "servers": [
    {
      "url": "https://api.dev.bsncraft.net"
    }
  ],
  "security": [
    {
      "bearerToken": []
    }
  ],
  "tags": [
    {
      "name": "Operations",
      "description": "Liveness and readiness."
    },
    {
      "name": "Companies",
      "description": "Companies this token can reach."
    },
    {
      "name": "Contract Documents",
      "description": "Contract document register."
    },
    {
      "name": "Contract Document Revisions",
      "description": "Contract document revision history."
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Process liveness",
        "security": [],
        "responses": {
          "200": {
            "description": "The process is running.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "const": "ok"
                    }
                  },
                  "required": [
                    "status"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/ready": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Readiness for authenticated traffic",
        "security": [],
        "responses": {
          "200": {
            "description": "Dependencies are reachable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Readiness"
                }
              }
            }
          },
          "503": {
            "description": "A required dependency is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Readiness"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "This contract",
        "security": [],
        "responses": {
          "200": {
            "description": "The OpenAPI 3.1 document."
          }
        }
      }
    },
    "/docs": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Self-hosted Scalar reference",
        "security": [],
        "responses": {
          "200": {
            "description": "HTML reference UI."
          }
        }
      }
    },
    "/swagger": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Self-hosted Swagger UI",
        "security": [],
        "responses": {
          "200": {
            "description": "HTML reference UI."
          }
        }
      }
    },
    "/api/v1/companies": {
      "get": {
        "tags": [
          "Companies"
        ],
        "summary": "Companies currently accessible to this token",
        "responses": {
          "200": {
            "description": "Accessible companies, keyed by code.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "companies": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Company"
                      }
                    }
                  },
                  "required": [
                    "companies"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "The contracts in a company that hold documents",
        "description": "Cursor-paged contract numbers, ascending. A caller migrating a company needs to know which contracts exist before it can read any of them, and probing a span one number at a time costs a request per number whether or not anything is there. `from` and `to` bound the listing; both are optional and either may stand alone. No response carries a total.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from a previous response's `nextCursor`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Lowest contract number to report, inclusive.",
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,5}$"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Highest contract number to report, inclusive.",
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,5}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One bounded page of contract numbers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContractPage"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot use documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such company for this token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The page size, cursor, or a contract bound is not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Cursor-paged document and revision metadata",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "An opaque cursor from a previous response's `nextCursor`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One bounded page.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentPage"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot use documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such contract in that company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The page size or cursor is not valid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Create a document and upload its content",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "document": {
                    "type": "string",
                    "description": "JSON object of the document fields (see `DocumentCreateFields`)."
                  }
                },
                "required": [
                  "file",
                  "document"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The document and its ETag.",
            "headers": {
              "ETag": {
                "description": "The document's new ETag.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such contract in that company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The key was used for different content, or the document type already exists on this contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The upload exceeds the company profile or the API's 1 GB request limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request is not multipart/form-data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "A field or the file type is not accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "One document with its revision metadata",
        "responses": {
          "200": {
            "description": "The document, its ETag, and its revisions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetail"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot use documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such document on that contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Update mutable document metadata",
        "description": "Never replaces file content. `objectKey` repoints the register at an already-validated managed object; uploading bytes is a separate request.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated document and its new ETag.",
            "headers": {
              "ETag": {
                "description": "The document's new ETag.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such document on that contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "A field is not accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/register": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Register a file already copied into managed storage",
        "description": "Creates a document record for an object the caller has already placed in the company's managed container. No file bytes are uploaded. The object key is validated for addressability and existence before the record is written.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentRegisterRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The registered document and its ETag.",
            "headers": {
              "ETag": {
                "description": "The document's new ETag.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such contract in that company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The key was used for different content, or the document type already exists on this contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The object key is not addressable, or the object is not there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/compare": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Compare legacy identities against current state",
        "description": "Identity comparison, not a timestamp watermark: each item is answered `missing`, `changed`, or `current` by comparing the supplied fingerprint with the item's current ETag. A row whose legacy modification stamp was never written is therefore still reachable.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CompareRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One outcome per item.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CompareResponse"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot use documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such contract in that company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request is malformed or carries more than 500 items.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/batch": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Apply a bounded batch of metadata and registration items",
        "description": "Items are applied independently and never share a transaction, so one failure cannot hide or corrupt its siblings. No file bodies.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One result per item.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResponse"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such contract in that company.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The key was used for different content.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The request is malformed or carries more than 500 items.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/revisions": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Contract Document Revisions"
        ],
        "summary": "Create one revision and upload its content",
        "description": "Archives the document's current file, records the revision, and attaches the uploaded replacement as one operation.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The revision and the advanced document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevisionCreated"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such document on that contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The document's current file changed while the revision was being taken.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The upload exceeds the company profile or the API's 1 GB request limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The document cannot take a revision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/revisions/register": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Contract Document Revisions"
        ],
        "summary": "Register a revision file already copied into managed storage",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevisionRegisterRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The registered revision and its ETag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevisionDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such document on that contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "The key was used for different content.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The object key is not addressable, or the object is not there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/content": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "put": {
        "tags": [
          "Contract Documents"
        ],
        "summary": "Upload the file for an existing document",
        "description": "Brings a document's file into the company's managed storage. The API decides the object key from the company's own path template, then repoints the register row at it. No record is created and no revision is archived, so this is what moves an existing document off an on-premises folder without the caller reaching the database or the storage account itself.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The document, now pointing at managed storage, and its new ETag.",
            "headers": {
              "ETag": {
                "description": "The document's new ETag.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DocumentDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such document on that contract.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The upload exceeds the company profile or the API's 1 GB request limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request is not multipart/form-data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The file type is not accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/library/{libraryLineId}/content": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        },
        {
          "name": "libraryLineId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLIN_G.CL_G_SEQNUM` under the document.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "put": {
        "tags": [
          "Contract Document Library"
        ],
        "summary": "Upload the file for an existing library line",
        "description": "Brings one library line's file into managed storage. A document's own register row frequently carries no file while its library holds every file the document has, so a migration that reads only the register misses them.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The library line, now pointing at managed storage, and its new ETag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LibraryLineDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such library line on that document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The upload exceeds the company profile or the API's 1 GB request limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request is not multipart/form-data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The file type is not accepted, or the line's type carries no file.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/library/{libraryLineId}": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        },
        {
          "name": "libraryLineId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLIN_G.CL_G_SEQNUM` under the document.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "patch": {
        "tags": [
          "Contract Document Library"
        ],
        "summary": "Point a library line at an object already in storage",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "objectKey": {
                    "type": "string",
                    "maxLength": 180
                  }
                },
                "required": [
                  "objectKey"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The library line and its new ETag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LibraryLineDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such library line on that document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "No managed object exists at that key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/revisions/{revisionId}/content": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        },
        {
          "name": "revisionId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `MSGLINR.MLR_SEQ` for the parent document.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "put": {
        "tags": [
          "Contract Document Revisions"
        ],
        "summary": "Upload the file for an existing revision",
        "description": "Brings one revision's file into managed storage, under the archive locator that revision is filed at. The locator is derived from where the document's own file sits, so the document has to be in managed storage first.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The revision, now pointing at managed storage, and its new ETag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevisionDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such revision on that document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "The upload exceeds the company profile or the API's 1 GB request limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "The request is not multipart/form-data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "The file type is not accepted, or the document's own file is not in managed storage yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Document storage is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/companies/{companyCode}/contracts/{contractNumber}/documents/{documentId}/revisions/{revisionId}": {
      "parameters": [
        {
          "name": "companyCode",
          "in": "path",
          "required": true,
          "description": "BusinessCraft company code.",
          "schema": {
            "type": "string",
            "pattern": "^[A-Za-z0-9]{1,15}$"
          }
        },
        {
          "name": "contractNumber",
          "in": "path",
          "required": true,
          "description": "Contract number, unpadded.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,5}$"
          }
        },
        {
          "name": "documentId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `CONLINW.CLW_SEQNUM`.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        },
        {
          "name": "revisionId",
          "in": "path",
          "required": true,
          "description": "Canonical base-10 `MSGLINR.MLR_SEQ` for the parent document.",
          "schema": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,8}$"
          }
        }
      ],
      "patch": {
        "tags": [
          "Contract Document Revisions"
        ],
        "summary": "Update mutable revision metadata",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "Caller-chosen key, at most 200 characters. Replaying it with the same content returns the original outcome.",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": true,
            "description": "The ETag the caller last read for this record.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevisionPatch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated revision and its new ETag.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RevisionDetail"
                }
              }
            }
          },
          "400": {
            "description": "`Idempotency-Key` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "The token is missing or not usable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token cannot write documents there.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such revision on that document.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "412": {
            "description": "`If-Match` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "428": {
            "description": "`If-Match` is missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "The token's request limit is exhausted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "An opaque BusinessCraft API token. Issued in User Settings or System > Admin > API; shown once and stored only as a hash."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "unauthenticated",
                  "forbidden",
                  "not_found",
                  "validation_failed",
                  "conflict",
                  "precondition_required",
                  "precondition_failed",
                  "idempotency_key_required",
                  "idempotency_key_conflict",
                  "idempotency_in_progress",
                  "payload_too_large",
                  "unsupported_media_type",
                  "rate_limited",
                  "not_configured",
                  "server_error"
                ]
              },
              "message": {
                "type": "string"
              },
              "requestId": {
                "type": "string"
              },
              "fields": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "field",
                    "message",
                    "code"
                  ]
                }
              },
              "retryAfterSeconds": {
                "type": "integer",
                "description": "Present only on `rate_limited`."
              }
            },
            "required": [
              "code",
              "message",
              "requestId"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Readiness": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "unavailable"
            ]
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "ok": {
                  "type": "boolean"
                }
              },
              "required": [
                "name",
                "ok"
              ]
            }
          }
        },
        "required": [
          "status",
          "checks"
        ]
      },
      "Company": {
        "type": "object",
        "properties": {
          "companyCode": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "number": {
            "type": "string"
          },
          "documentAccess": {
            "type": "object",
            "properties": {
              "read": {
                "type": "boolean"
              },
              "write": {
                "type": "boolean"
              }
            },
            "required": [
              "read",
              "write"
            ]
          }
        },
        "required": [
          "companyCode",
          "name",
          "number",
          "documentAccess"
        ]
      },
      "FileReference": {
        "type": "object",
        "description": "The register row's file identity. `objectKey` is the provider-relative key inside the company's managed container. `sourceLocation` is the exact stored Desktop locator only while the file remains on premises, allowing migration tools to select its configured source root.",
        "properties": {
          "state": {
            "type": "string",
            "enum": [
              "available",
              "metadata_only",
              "unsupported_locator"
            ]
          },
          "objectKey": {
            "type": [
              "string",
              "null"
            ]
          },
          "originalFilename": {
            "type": "string"
          },
          "sourceLocation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The exact stored Desktop locator when `location` is `on_premises`; otherwise null. Returned to authenticated document readers so migration tools can distinguish configured source roots that contain the same relative object key."
          },
          "unresolvedLocation": {
            "type": [
              "string",
              "null"
            ],
            "description": "The stored Desktop locator, and only when the state is `unsupported_locator`. Public contracts otherwise never name one: this is the single case where withholding it helps nobody, because there is no object key to return and the only fix is to see which configured root is missing."
          },
          "location": {
            "type": "string",
            "enum": [
              "managed",
              "on_premises",
              "unsupported",
              "none"
            ],
            "description": "Whether the file has been brought into managed storage yet. `state` says whether the locator is addressable; this says where it points. Decided from the company's configured roots alone, so a page costs no storage calls."
          }
        },
        "required": [
          "state",
          "objectKey",
          "originalFilename",
          "location",
          "sourceLocation",
          "unresolvedLocation"
        ]
      },
      "Document": {
        "type": "object",
        "properties": {
          "documentId": {
            "type": "string"
          },
          "companyCode": {
            "type": "string"
          },
          "contractNumber": {
            "type": "integer"
          },
          "documentType": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "rating": {
            "type": "string"
          },
          "privacy": {
            "type": "string"
          },
          "createdFor": {
            "type": "string"
          },
          "hasNotes": {
            "type": "boolean"
          },
          "eventNumber": {
            "type": "integer"
          },
          "variationNumber": {
            "type": "integer"
          },
          "progressBillingStage": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "section": {
            "type": "string"
          },
          "heading": {
            "type": "string"
          },
          "submitted": {
            "type": "string"
          },
          "revision": {
            "type": "string"
          },
          "revisedBy": {
            "type": "string"
          },
          "revisionDate": {
            "type": "string"
          },
          "crossReferenceSource": {
            "type": "string"
          },
          "crossReferenceKey": {
            "type": "string"
          },
          "file": {
            "$ref": "#/components/schemas/FileReference"
          },
          "createdBy": {
            "type": "string"
          },
          "createdDate": {
            "type": "string"
          },
          "createdTime": {
            "type": "string"
          },
          "modifiedBy": {
            "type": "string"
          },
          "modifiedDate": {
            "type": "string"
          },
          "modifiedTime": {
            "type": "string"
          }
        },
        "required": [
          "documentId",
          "companyCode",
          "contractNumber",
          "documentType"
        ]
      },
      "Revision": {
        "type": "object",
        "properties": {
          "revisionId": {
            "type": "string"
          },
          "documentId": {
            "type": "string"
          },
          "companyCode": {
            "type": "string"
          },
          "contractNumber": {
            "type": "integer"
          },
          "revision": {
            "type": "integer"
          },
          "file": {
            "$ref": "#/components/schemas/FileReference"
          },
          "createdBy": {
            "type": "string"
          },
          "createdDate": {
            "type": "string"
          },
          "createdTime": {
            "type": "string"
          }
        },
        "required": [
          "revisionId",
          "documentId",
          "revision",
          "file"
        ]
      },
      "LibraryLine": {
        "type": "object",
        "description": "One sub-document filed under a register row. A third kind of file beside the row itself and its revision history.",
        "properties": {
          "libraryLineId": {
            "type": "string"
          },
          "documentId": {
            "type": "string"
          },
          "companyCode": {
            "type": "string"
          },
          "contractNumber": {
            "type": "integer"
          },
          "documentType": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "file": {
            "$ref": "#/components/schemas/FileReference"
          },
          "createdBy": {
            "type": "string"
          },
          "createdDate": {
            "type": "string"
          },
          "createdTime": {
            "type": "string"
          },
          "modifiedBy": {
            "type": "string"
          },
          "modifiedDate": {
            "type": "string"
          },
          "modifiedTime": {
            "type": "string"
          }
        },
        "required": [
          "libraryLineId",
          "documentId",
          "file"
        ]
      },
      "LibraryLineDetail": {
        "type": "object",
        "properties": {
          "libraryLine": {
            "$ref": "#/components/schemas/LibraryLine"
          },
          "etag": {
            "type": "string"
          }
        },
        "required": [
          "libraryLine",
          "etag"
        ]
      },
      "ContractPage": {
        "type": "object",
        "description": "Contract numbers that hold documents, ascending. `nextCursor` is null on the last page.",
        "properties": {
          "contracts": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "pageSize": {
            "type": "integer"
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "contracts",
          "pageSize",
          "nextCursor"
        ]
      },
      "DocumentPage": {
        "type": "object",
        "properties": {
          "documents": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Document"
                },
                {
                  "type": "object",
                  "properties": {
                    "etag": {
                      "type": "string"
                    },
                    "revisions": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/Revision"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "etag": {
                                "type": "string"
                              }
                            }
                          }
                        ]
                      }
                    },
                    "library": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/LibraryLine"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "etag": {
                                "type": "string"
                              }
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              ]
            }
          },
          "pageSize": {
            "type": "integer",
            "maximum": 500
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Replay this to read the next page, or to resume."
          }
        },
        "required": [
          "documents",
          "pageSize",
          "nextCursor"
        ]
      },
      "DocumentDetail": {
        "type": "object",
        "properties": {
          "document": {
            "$ref": "#/components/schemas/Document"
          },
          "etag": {
            "type": "string"
          },
          "revisions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RevisionWithEtag"
            }
          }
        },
        "required": [
          "document",
          "etag"
        ]
      },
      "RevisionWithEtag": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Revision"
          },
          {
            "type": "object",
            "properties": {
              "etag": {
                "type": "string"
              }
            }
          }
        ]
      },
      "RevisionDetail": {
        "type": "object",
        "properties": {
          "revision": {
            "$ref": "#/components/schemas/Revision"
          },
          "etag": {
            "type": "string"
          }
        },
        "required": [
          "revision",
          "etag"
        ]
      },
      "RevisionCreated": {
        "type": "object",
        "properties": {
          "revision": {
            "$ref": "#/components/schemas/Revision"
          },
          "etag": {
            "type": "string"
          },
          "document": {
            "$ref": "#/components/schemas/Document"
          },
          "documentEtag": {
            "type": "string"
          }
        },
        "required": [
          "revision",
          "etag",
          "document",
          "documentEtag"
        ]
      },
      "DocumentCreateFields": {
        "type": "object",
        "properties": {
          "documentType": {
            "type": "string",
            "maxLength": 5
          },
          "reference": {
            "type": "string",
            "maxLength": 8
          },
          "description": {
            "type": "string",
            "maxLength": 50
          },
          "rating": {
            "type": "string",
            "maxLength": 1
          },
          "privacy": {
            "type": "string",
            "maxLength": 2
          },
          "createdFor": {
            "type": "string",
            "maxLength": 3
          },
          "eventNumber": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "documentType"
        ]
      },
      "DocumentPatch": {
        "type": "object",
        "description": "At least one field must be present.",
        "properties": {
          "documentType": {
            "type": "string",
            "maxLength": 5
          },
          "reference": {
            "type": "string",
            "maxLength": 8
          },
          "description": {
            "type": "string",
            "maxLength": 50
          },
          "rating": {
            "type": "string",
            "maxLength": 1
          },
          "privacy": {
            "type": "string",
            "maxLength": 2
          },
          "createdFor": {
            "type": "string",
            "maxLength": 3
          },
          "progressBillingStage": {
            "type": "string",
            "maxLength": 3
          },
          "status": {
            "type": "string",
            "maxLength": 1
          },
          "section": {
            "type": "string",
            "maxLength": 2
          },
          "heading": {
            "type": "string",
            "maxLength": 4
          },
          "submitted": {
            "type": "string",
            "maxLength": 1
          },
          "originalFilename": {
            "type": "string",
            "maxLength": 244
          },
          "objectKey": {
            "type": "string",
            "maxLength": 250,
            "description": "A validated managed object key, or an empty string to clear the locator."
          }
        }
      },
      "DocumentRegisterRequest": {
        "type": "object",
        "properties": {
          "document": {
            "$ref": "#/components/schemas/DocumentCreateFields"
          },
          "objectKey": {
            "type": "string",
            "maxLength": 250
          },
          "originalFilename": {
            "type": "string",
            "maxLength": 244
          }
        },
        "required": [
          "document",
          "objectKey"
        ]
      },
      "RevisionRegisterRequest": {
        "type": "object",
        "properties": {
          "objectKey": {
            "type": "string",
            "maxLength": 250
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 99
          }
        },
        "required": [
          "objectKey"
        ]
      },
      "RevisionPatch": {
        "type": "object",
        "description": "At least one field must be present.",
        "properties": {
          "objectKey": {
            "type": "string",
            "maxLength": 250
          },
          "revision": {
            "type": "integer",
            "minimum": 0,
            "maximum": 99
          }
        }
      },
      "CompareRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "maxLength": 120
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "document",
                    "revision"
                  ]
                },
                "documentId": {
                  "type": [
                    "string",
                    "integer"
                  ]
                },
                "revisionId": {
                  "type": [
                    "string",
                    "integer"
                  ]
                },
                "fingerprint": {
                  "type": "string",
                  "description": "The ETag this client last held for the item. Omit it to be told `changed`."
                }
              },
              "required": [
                "key",
                "kind",
                "documentId"
              ]
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "CompareResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "document",
                    "revision"
                  ]
                },
                "documentId": {
                  "type": "string"
                },
                "revisionId": {
                  "type": "string"
                },
                "outcome": {
                  "type": "string",
                  "enum": [
                    "missing",
                    "changed",
                    "current"
                  ]
                },
                "etag": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "key",
                "kind",
                "documentId",
                "outcome",
                "etag"
              ]
            }
          }
        },
        "required": [
          "results"
        ]
      },
      "BatchRequest": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 500,
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string",
                  "maxLength": 120
                },
                "operation": {
                  "type": "string",
                  "enum": [
                    "update-document",
                    "register-document",
                    "register-revision",
                    "update-revision"
                  ]
                },
                "documentId": {
                  "type": [
                    "string",
                    "integer"
                  ]
                },
                "revisionId": {
                  "type": [
                    "string",
                    "integer"
                  ]
                },
                "ifMatch": {
                  "type": "string"
                },
                "patch": {
                  "$ref": "#/components/schemas/DocumentPatch"
                },
                "document": {
                  "$ref": "#/components/schemas/DocumentCreateFields"
                },
                "objectKey": {
                  "type": "string",
                  "maxLength": 250
                },
                "originalFilename": {
                  "type": "string",
                  "maxLength": 244
                },
                "revision": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 99
                }
              },
              "required": [
                "key",
                "operation"
              ]
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "BatchResponse": {
        "type": "object",
        "properties": {
          "results": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "operation": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "success",
                    "validation",
                    "conflict",
                    "denied",
                    "failed"
                  ]
                },
                "documentId": {
                  "type": "string"
                },
                "revisionId": {
                  "type": "string"
                },
                "etag": {
                  "type": "string"
                },
                "error": {
                  "type": "object"
                }
              },
              "required": [
                "key",
                "operation",
                "status"
              ]
            }
          }
        },
        "required": [
          "results"
        ]
      }
    }
  }
}