openapi: 3.0.3
info:
  title: ModernEDI Integration API
  version: 1.24.0
  termsOfService: https://www.modernedi.com/terms
  contact:
    name: ModernEDI Integration Support
    url: https://www.modernedi.com/contact
    email: support@modernedi.com
  description: |
    Customer-facing integration endpoints for ModernEDI tenants. Use this API when your ERP, WMS, integration service, or internal automation needs to receive inbound partner documents as mapped business payloads, send XML/JSON/text source inputs that ModernEDI turns into outbound X12, send already-generated X12 without applying a map, validate X12, or inspect transaction activity across the whole exchange.

    ModernEDI keeps X12 at the trading-partner boundary instead of making it the shape your internal systems have to speak. Incoming maps translate partner X12 into JSON, XML, HTML, text, or another business format your system can process. Outgoing maps do the reverse: your system sends an XML, JSON, or text source document plus optional runtime params, and ModernEDI selects the matching outgoing map, generates the X12 transaction body, syntax-checks it, and sends it over AS2.

    ### Official SDKs

    ModernEDI-supported SDKs:

    - **TypeScript / JavaScript:** [`@modernedi/sdk` on npm](https://www.npmjs.com/package/@modernedi/sdk) — install with `npm install @modernedi/sdk`.

    Keep Integration API keys in a trusted server or backend-for-frontend; do not embed them in browser JavaScript or another client distribution that an end user can inspect.

    In the mapper editor, generated-X12 trace highlights can connect output values back to the map and source fixtures. XSLT maps trace generated values back to stylesheet instructions, source input values, and test params; JSLT maps use the same trace contract against ModernEDI's wrapper root, where source values live under `.input` and params under `.params`, including simple aliases such as `let po = .input`.

    A typical purchase-order-to-invoice round trip is:

    1. A partner sends an inbound 850 purchase order to ModernEDI.
    2. ModernEDI validates the inbound X12, applies the incoming map, and makes the mapped payload available through `GET /v1/mapped-outputs` or a mapped-output webhook.
    3. Call `POST /v1/mapped-outputs/{id}/ack` after your integration has durably stored the mapped output or enqueued it for reliable processing. This acknowledgment confirms custody, not later ERP or business processing.
    4. Your system builds an invoice, ASN, or other business reply as XML, JSON, or text.
    5. Call `POST /v1/as2/reply`; ModernEDI applies the matching outgoing map, generates X12, validates it, and sends the reply AS2 message.
    6. Use `/v1/integration/transactions` to confirm the inbound document, mapped output, generated outbound X12, AS2 receipts, 997 or 999 acknowledgments, and reply linkage.

    If you prefer push delivery, configure a per-partner mapped-output webhook in the ModernEDI workspace. ModernEDI sends the same mapped-output message shape to your HTTPS endpoint and automatically acknowledges the queue item only when your endpoint returns a 2xx response. Failed webhook attempts leave the message available through the pull API.

    Push webhook requests include `X-ModernEDI-Event`, `X-ModernEDI-Delivery-Id`, `X-ModernEDI-Timestamp`, and `X-ModernEDI-Signature`. `X-ModernEDI-Timestamp` is whole Unix epoch seconds. The signature is `sha256=<64 lowercase hexadecimal HMAC-SHA-256 characters>` over the exact bytes of `<timestamp>.<raw request body>` using the partner webhook signing secret. Verify the raw bytes with a constant-time comparison and reject timestamps outside a short freshness window before parsing or acting on the event. The official TypeScript SDK provides `verifyMappedOutputWebhook(...)` with a five-minute default tolerance. Timestamp freshness does not prevent replay within that window: after signature verification, durably record and reject duplicate `deliveryId` values. For production `mapped_output.available` processing, also use `message.id` as the durable business-processing idempotency key because a legitimate redelivery attempt receives a new `deliveryId`.

    `/v1/as2/send` is available when your system is first in the chain, such as sending a purchase order or another outbound document that is not replying to a received document. `/v1/as2/carbonCopy` uses the same outgoing-map selection as the original partner, then sends the generated X12 envelope to a second partner.

    Trading partner records can be created before an AS2 profile is known, which lets teams publish and test maps during migration. Use `GET /v1/partners` to list the partner ids your integration client can send as `partnerId` for exact outgoing-map selection. These AS2 endpoints require the matched destination partner to have a complete AS2 profile, destination URL, and X12 identity for the selected environment at send time; otherwise ModernEDI rejects the request before delivery.

    Key fields in the mapped-output and reply loop:

    - `id`: mapped output id used in the `/v1/mapped-outputs/{id}/ack` path.
    - `receiptHandle`: token from the latest poll, required when marking mapped output as received.
    - `messageId`: original inbound AS2 message id; use it as `originalMessageId` for `/v1/as2/reply`.
    - `transactionKey`: transaction identifier within the AS2 message, usually `GS06#ST02`.
    - `mappedOutputKey`: unique mapped-output key inside the transaction.
    - `purpose`: why the map result exists. `PROCESSING` is a normal mapped output for your application workflow, while `ACKNOWLEDGMENT` is an automatically generated response document such as a purchase order acknowledgment.
    - `payload`: mapped document body; parse it according to `contentType`.
    - `extraFields`: runtime routing metadata recorded by ModernEDI, such as `{"destination":"managedQueue"}`; it is not customer-selectable business metadata. Use an incoming mapping's closed `deliveredMetadata` object to include or omit the documented partner, transaction, X12, and map-source context fields.
    - `delivery`: stored transaction handoff state. `acknowledged` means acknowledged by your integration; it does not prove how another application handled the document afterward.
    - `replyToMessageId`: present on outbound replies and points back to the inbound message.

    For a transaction detail view, start with the metadata-first inbound transaction detail. Use its document index to discover retained X12, mapped output, MDN, 997, 999, and response artifacts, and fetch an individual document only when an operator opens it. Linked replies in `relatedTransactions` are compact summaries; fetch a reply's detail when selected.

    Common failures to handle include missing or invalid API keys, unknown partner names, missing outgoing maps, generated X12 syntax errors, `originalMessageId` not found, partner AS2 delivery failure, and mapped output returned again because it was not marked received before the visibility timeout.

    Every `/v1` response includes an `X-Request-Id` header. You may send a safe caller-generated `X-Request-Id` (1 to 128 characters using letters, numbers, `.`, `_`, `:`, `@`, `/`, `+`, `=`, or `-`); ModernEDI preserves it, or generates a replacement when it is absent or unsafe. Log the response value for both successful and failed calls so ModernEDI support can correlate the request with runtime logs. Error bodies repeat the same value as `error.requestId`.

    Integration API keys carry explicit least-privilege scopes. Read transaction history, mapped outputs, and usage or validate X12 without sending it with `transactions:read`; add or remove transactions from the operator watchlist with `transactions:write`; replay inbound transactions with `transactions:replay`; send messages and acknowledge mapped outputs with `messages:write`; read partners, mappings, AS2 connections, the public AS2 profile, and webhook settings with `configuration:read`; and change those configuration objects with `configuration:write`. Every operation below states its required scope. A valid key without that scope receives `403 insufficient_scope` with the required and granted scopes in `error.details`.

    Integration API keys are server-side credentials. Do not embed them in browser JavaScript, mobile applications, desktop binaries, or other distributions that an end user can inspect. A browser-based transaction viewer should call a customer-controlled backend or backend-for-frontend (BFF), and that server should call ModernEDI. CORS is a browser request policy, not protection for an exposed credential.

    Treat X12, MDN reports, raw HTTP response bodies, mapped outputs, and other partner-originated values as untrusted content. Escape them when displaying text, sanitize HTML against a narrow allowlist, or render active formats in a sandboxed frame. Do not insert these values directly into the DOM as trusted HTML.

    Structured JSON request bodies use strict schemas. Configuration writes and transaction replay reject unknown fields at any documented object level rather than ignoring them, and scalar values must use the documented JSON type; for example, `"true"` is not accepted for a boolean and numeric ids are not accepted as strings. `null` is accepted only where the schema explicitly allows it. These failures return `400 invalid_request` with the offending JSON field path in the message.

    Public transaction timestamps are UTC instants formatted with exactly nine fractional digits and `Z`, for example `2026-07-15T18:30:00.000000000Z`. Transaction date-time filters must include an explicit RFC 3339 offset; date-only filters represent UTC calendar days. Offset-less date-times are rejected.

    While a workspace is active, ModernEDI normally keeps transaction documents and associated acknowledgements available in operational history for 12 months after processing. When both transaction `startDate` and `endDate` are omitted, ModernEDI queries that preceding 12-month window by default. Specify dates explicitly when a client requires a particular interval, and do not infer deletion merely because a record is absent from a response.

    For 90 days after a self-serve cancellation, authorized users can use read-only recovery mode to access records that remain within their applicable retention periods. Each transaction remains subject to its original 12-month window, which continues from its processing date and does not restart or extend at cancellation. An Enterprise order form may specify a different period. Content removed from the active service may remain in protected backup copies until those copies age out and is not ordinarily accessible through the workspace or Integration API.

    ModernEDI transaction history is intended for transaction operations, investigation, and recovery. It is not a legal archive, records-management service, or the customer's exclusive system of record. Export and independently retain records needed for business, tax, regulatory, contractual, or legal purposes.

    All customer-facing Integration API endpoints use `https://api.modernedi.com`. ModernEDI forwards outbound `/v1/as2/send`, `/v1/as2/reply`, `/v1/as2/carbonCopy`, and their `/v1/as2/x12/...` counterparts into the tenant AS2 runtime after authenticating the same Integration API key used by mapped-output and transaction-viewer endpoints.
servers:
  - url: https://api.modernedi.com
tags:
  - name: Partners
    description: Read and manage tenant trading-partner records and stable partner ids.
  - name: AS2 Connections
    description: Manage partner AS2 identifiers, destination URLs, public certificates, and transport settings.
  - name: Mappings
    description: Manage safe incoming and outgoing mapping configuration as source-controlled text.
  - name: Outbound AS2
    description: Send reply documents and standalone outbound AS2 messages through an existing ModernEDI partner connection.
  - name: Mapped Output Queue
    description: Receive mapped inbound documents by polling, or configure per-partner HTTPS push delivery in the workspace.
  - name: Transaction Viewer
    description: Read transaction history, documents, events, acknowledgements, linked replies, manage the operator watchlist, and perform safe response-only replays.
  - name: Mapping Runtime
    description: Inspect mapping health and safe failure diagnostics, including failures that occurred before a transaction could be created.
  - name: Integration Events
    description: Poll tenant-scoped invalidation events and refetch current transaction state after late acknowledgments or processing changes.
  - name: X12 Tools
    description: Validate X12 and discover the X12 versions and transaction sets available to the tenant.
  - name: Account
    description: Read current plan usage and enforcement status.
paths:
  /v1/partners:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationPartners
      tags:
        - Partners
      summary: List configured trading partners
      x-required-scope: configuration:read
      description: >
        **Required key scope:** `configuration:read`.

        Returns the tenant's active configured trading partners in workspace order. Retired partners are excluded.
        Use `partnerId` from this response as the `partnerId` query parameter
        on `/v1/as2/send`, `/v1/as2/reply`, or `/v1/as2/carbonCopy` when your
        integration selects the outbound partner. The returned `name` is display
        metadata; use `copyToPartnerId` for the carbon-copy recipient. Partners can appear before their AS2
        profile is complete so teams can publish and test maps during
        onboarding; `as2ConnectionConfigured` tells you whether live AS2
        delivery can use that partner yet.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/partners" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.get(
                "https://api.modernedi.com/v1/partners",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            partners = response.json()["partners"]
            partner_id_by_name = {partner["name"]: partner["partnerId"] for partner in partners}
        - lang: JavaScript
          label: JavaScript
          source: |
            const response = await fetch("https://api.modernedi.com/v1/partners", {
              headers: { "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY },
            })

            if (!response.ok) {
              throw new Error(`ModernEDI partner list failed: ${response.status}`)
            }

            const { partners } = await response.json()
            const partnerIdByName = Object.fromEntries(
              partners.map((partner) => [partner.name, partner.partnerId]),
            )
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: Trading partners were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerListResponse'
              example:
                success: true
                partners:
                  - partnerId: 1
                    name: Customer One
                    as2ConnectionId: 1
                    as2ConnectionConfigured: true
                    productionReady: true
                    testReady: true
                    carbonCopyOnly: false
                    implementationAcknowledgmentEnabled: true
                    ediSupportEmail: edi@example.com
                    unmappedInboundPolicy: MAPPED_ONLY
                    signingCertificateSlot: active
                    supportsNewlineAfterSegmentTerminator: false
                    x12:
                      production:
                        isaQualifier: ZZ
                        isaId: CUSTOMERONE
                        gsId: CUSTOMERONE
                      test:
                        isaQualifier: ZZ
                        isaId: CUSTOMERONET
                        gsId: CUSTOMERONET
                    etag: '"44e5a1b1242e11a8b29380d9de44c08b46433673f30e23ac876a345fc2c5f1b3"'
                  - partnerId: 2
                    name: Broker One
                    as2ConnectionId: 2
                    as2ConnectionConfigured: true
                    productionReady: true
                    testReady: true
                    carbonCopyOnly: true
                    implementationAcknowledgmentEnabled: false
                    ediSupportEmail: edi@example.com
                    unmappedInboundPolicy: MAPPED_ONLY
                    signingCertificateSlot: active
                    supportsNewlineAfterSegmentTerminator: false
                    x12:
                      production:
                        isaQualifier: ZZ
                        isaId: BROKERONE
                        gsId: BROKERONE
                      test:
                        isaQualifier: ZZ
                        isaId: BROKERONET
                        gsId: BROKERONET
                    etag: '"bf47b5bc59d748f05de58beb93a766a823a4a796f117143b1e3c815bd5b2c9bf"'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    post:
      operationId: createIntegrationPartner
      tags:
        - Partners
      summary: Create a trading partner
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Creates a tenant-scoped partner. Partner names are unique within the workspace. For every partner attached to an AS2 connection, including carbon-copy-only partners, each configured X12 ISA identifier must be unique on that connection. `as2ConnectionId` may be `null` while maps are authored before the partner's connection sheet is available; detached drafts may omit or leave X12 identities incomplete. A connected partner always requires a complete production X12 identity. The test identity may be omitted or set to `null` when the partner has no separate test configuration; when supplied, all three test fields are required together. Configured identities use an ISA qualifier of exactly 2 characters and ISA and GS identifiers between 1 and 15 characters inclusive. Invalid connected identities return `422 partner_x12_identity_invalid` without creating the partner. `signingCertificateSlot` may be `active` or `next`; `next` is accepted only after a rollover certificate exists.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      requestBody:
        required: true
        description: Partner configuration bodies may be at most 1 MiB (1,048,576 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerWriteRequest'
            example:
              name: Retailer One
              as2ConnectionId: null
              x12:
                production:
                  isaQualifier: ZZ
                  isaId: RETAILERONE
                  gsId: RETAILERONE
                test:
                  isaQualifier: ZZ
                  isaId: RETAILERONET
                  gsId: RETAILERONET
              ediSupportEmail: edi@retailer.example
              carbonCopyOnly: false
              implementationAcknowledgmentEnabled: false
              unmappedInboundPolicy: MAPPED_ONLY
              signingCertificateSlot: active
              supportsNewlineAfterSegmentTerminator: false
      responses:
        '201':
          description: The partner was created. The response `ETag` matches `partner.etag`; inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          $ref: '#/components/responses/ConfigurationConflictError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/PartnerX12IdentityValidationError'
  /v1/partners/{partnerId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: partnerId
        in: path
        required: true
        description: Tenant-scoped partner id.
        schema:
          type: integer
          minimum: 1
    get:
      operationId: getIntegrationPartner
      tags:
        - Partners
      summary: Get a trading partner
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns the complete active public partner configuration. Retired partners return `404`; their retained rows are used only for historical transaction authorization. The response never exposes internal header overrides or infrastructure settings. Save the `ETag` header or `partner.etag` value before updating or retiring the partner. The partner ETag hashes only mutable partner configuration; derived AS2 readiness fields are excluded because the referenced AS2 connection has its own independently versioned ETag.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: The partner was returned.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    patch:
      operationId: patchIntegrationPartner
      tags:
        - Partners
      summary: Update a trading partner
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Applies the supplied fields and preserves omitted fields. Send the current resource ETag in `If-Match`. Partner-name and per-connection ISA-identifier uniqueness rules are rechecked atomically. X12 identity validation runs against the final merged configuration, not only the fields in the PATCH body: production is required for a connected partner, while an optional test identity must be complete when present. Set `x12.test` to `null` to remove a partner's test X12 identity; omitting `x12.test` preserves it. This makes an attach-only PATCH fail with `422 partner_x12_identity_invalid` when a required stored identity is incomplete or invalid, without changing the partner. Set `as2ConnectionId` to `null` to detach the partner from its AS2 connection without deleting either record.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      requestBody:
        required: true
        description: Partner configuration bodies may be at most 1 MiB (1,048,576 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PartnerPatchRequest'
            example:
              as2ConnectionId: 12
              ediSupportEmail: edi-operations@retailer.example
      responses:
        '200':
          description: The partner was updated. Inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '409':
          $ref: '#/components/responses/ConfigurationConflictError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/PartnerX12IdentityValidationError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
    delete:
      operationId: deleteIntegrationPartner
      tags:
        - Partners
      summary: Retire a trading partner
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Retires the partner when no mapping still references it. Send the current resource ETag in `If-Match`; delete dependent mappings first when this operation returns `409 configuration_in_use`.

        Retirement removes the partner from active configuration reads, capabilities, runtime routing, and response-only replay without physically deleting its retained row. The retained partner id continues to authorize historical transaction visibility. Replay requires an active partner plus an applicable currently published map, so retired-partner transactions remain readable but are not replayable. The attached AS2 connection remains in use by the retained row. If you intend to delete that connection, detach it with partner PATCH before retirement.

        Retirement remains available when the aggregate runtime configuration already exceeds 12 MiB so configuration can be reduced. The database change commits, but `runtimePublication.state` may remain `pending` until later deletes bring the runtime document below the cap.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      responses:
        '200':
          description: The partner was retired. `retiredPartnerId` identifies the retired partner. Inspect `runtimePublication` for runtime activation state.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                type: object
                required: [success, retiredPartnerId, runtimePublication]
                properties:
                  success:
                    type: boolean
                    enum: [true]
                    description: Always `true`; retirement conflicts or failures use the documented error response instead.
                  retiredPartnerId:
                    type: integer
                    description: Id of the partner that was retired.
                  runtimePublication:
                    $ref: '#/components/schemas/RuntimePublication'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '409':
          $ref: '#/components/responses/ConfigurationInUseError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
  /v1/partners/{partnerId}/capabilities:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationPartnerCapabilities
      tags:
        - Partners
      summary: Inspect a partner's published mapping capabilities
      x-required-scope: configuration:read
      description: >
        **Required key scope:** `configuration:read`.

        Returns the selected partner plus its published incoming and outgoing
        mapping capabilities. Use this before sending to discover the exact X12
        version, functional group, transaction set, source content type, and
        transform type that are currently configured. `productionReady` and
        `testReady` report whether the corresponding AS2 destination endpoint is
        configured; a published mapping can exist before either endpoint is ready.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: partnerId
          in: path
          required: true
          description: Tenant-scoped partner id returned by `GET /v1/partners`.
          schema:
            type: integer
      responses:
        '200':
          description: Partner capabilities were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PartnerCapabilitiesResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The partner was not found in this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/as2/profile:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationAs2Profile
      tags:
        - Partners
      summary: Get the tenant's public AS2 profile
      x-required-scope: configuration:read
      description: >
        **Required key scope:** `configuration:read`.

        Returns the safe connection sheet your trading partners need: production
        and test AS2 URLs and identifiers, X12 sender identities, static network
        addresses included in the current plan, and active or next public
        certificates. Private keys, secret ARNs, billing contacts, and internal
        infrastructure identifiers are never returned. Network capability status
        is `ready`, `pending`, or `not_included`.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: The tenant's AS2 profile was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/As2ProfileResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: No AS2 profile was found for the authenticated tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/as2/connections:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationAs2Connections
      tags:
        - AS2 Connections
      summary: List partner AS2 connections
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns every partner AS2 connection in this tenant. Certificates are partner public X.509 certificates formatted as PEM. Private keys and secret locations are never returned.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: AS2 connections were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/As2ConnectionListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    post:
      operationId: createIntegrationAs2Connection
      tags:
        - AS2 Connections
      summary: Create a partner AS2 connection
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Creates transport configuration for a partner. The production AS2 profile requires an identifier and one PEM-encoded X.509 public certificate. Its destination URL is optional so inbound-only partners can be configured before they provide an outbound endpoint. The test profile is optional: omit it or send `null` when the partner has no separate test configuration; when present, its identifier and certificate are required together and its destination URL remains optional. A destination URL cannot be configured without the corresponding identifier and certificate. Configured production and test AS2 identifiers must each be unique across this tenant's AS2 connections. Configured URLs must be absolute public HTTP or HTTPS URLs without user information or fragments. Endpoint is HTTPS-only; plain HTTP partner URLs require Endpoint Plus, Static Outbound, Static Network, or Enterprise. Omitted transport settings use ModernEDI defaults. ModernEDI never copies production values into the test environment. Outbound sends remain unavailable until the selected environment also has a destination URL and complete partner X12 identity.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/connections" \
              -H "Content-Type: application/json" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              --data @examples/as2-connection-create-request.json
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      requestBody:
        required: true
        description: AS2 connection configuration bodies may be at most 1 MiB (1,048,576 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/As2ConnectionCreateRequest'
      responses:
        '201':
          description: The AS2 connection was created. The response `ETag` matches `connection.etag`; inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/As2ConnectionMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          $ref: '#/components/responses/ConfigurationConflictError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/PlanEntitlementRequiredError'
  /v1/as2/connections/{connectionId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: connectionId
        in: path
        required: true
        description: Tenant-scoped AS2 connection id.
        schema:
          type: integer
          minimum: 1
    get:
      operationId: getIntegrationAs2Connection
      tags:
        - AS2 Connections
      summary: Get a partner AS2 connection
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns one public AS2 connection configuration and its concurrency-control ETag.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: The AS2 connection was returned.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/As2ConnectionResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    patch:
      operationId: patchIntegrationAs2Connection
      tags:
        - AS2 Connections
      summary: Update a partner AS2 connection
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Applies the supplied nested fields and preserves omitted fields. Send the current resource ETag in `If-Match`. Set either `endpointUrl` to `null` to make that profile inbound-only. Set `environments.test` to `null` to remove the complete test profile; omitting it preserves the stored test profile. A non-null test object must resolve to an identifier and certificate together, while its URL remains optional. A URL without those profile fields is invalid. Test-profile removal returns `409 configuration_in_use` without changing the connection while any attached partner still has test X12 identity fields; remove those partner fields first. Production and configured test AS2 identifier uniqueness is rechecked atomically. Configured URLs must remain HTTPS unless the workspace has Endpoint Plus, Static Outbound, Static Network, or Enterprise plain-HTTP entitlement. ModernEDI never falls back from test to production.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      requestBody:
        required: true
        description: AS2 connection configuration bodies may be at most 1 MiB (1,048,576 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/As2ConnectionPatchRequest'
            example:
              environments:
                test: null
      responses:
        '200':
          description: The AS2 connection was updated. Inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/As2ConnectionMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '409':
          $ref: '#/components/responses/As2ConnectionPatchConflictError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/PlanEntitlementRequiredError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
    delete:
      operationId: deleteIntegrationAs2Connection
      tags:
        - AS2 Connections
      summary: Delete a partner AS2 connection
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Deletes the connection when no active or retained partner is assigned to it. Send the current resource ETag in `If-Match`; detach referencing partner records before retirement when this operation returns `409 configuration_in_use`. Delete remains available when the aggregate runtime configuration already exceeds 12 MiB so configuration can be reduced; `runtimePublication.state` may remain `pending` until the document is below the cap.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      responses:
        '200':
          description: The AS2 connection was deleted. Inspect `runtimePublication` for runtime activation state.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                type: object
                required: [success, deletedConnectionId, runtimePublication]
                properties:
                  success:
                    type: boolean
                    enum: [true]
                    description: Always `true`; deletion conflicts or failures use the documented error response instead.
                  deletedConnectionId:
                    type: integer
                    description: Stable workspace-scoped id of the AS2 connection that was deleted.
                  runtimePublication:
                    $ref: '#/components/schemas/RuntimePublication'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '409':
          $ref: '#/components/responses/ConfigurationInUseError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
  /v1/as2/preview:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: previewOutboundX12
      tags:
        - Outbound AS2
      summary: Transform and validate an outbound document without sending it
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Uses the same partner, X12 metadata, content type, source body, params,
        and business-key contract as `/v1/as2/send`, but stops after mapping and
        X12 validation. It returns generated X12, validation details, mapping
        provenance, the resolved partner, and the optional business key. It does
        not contact the trading partner, create an outbound transaction, or
        require the partner's AS2 endpoint to be configured. Use it to validate
        a production-shaped request before the first live send.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/preview?partnerId=1&x12Version=4010&functionalGroupType=IN&transactionGroupType=810" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/vnd.modernedi.outbound+json" \
              --data-binary @invoice-envelope.json
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/OutboundPartnerId'
        - $ref: '#/components/parameters/OutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
      requestBody:
        $ref: '#/components/requestBodies/OutboundMappedSourceBody'
      responses:
        '200':
          description: The source document was mapped and the generated X12 passed validation.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OutboundPreviewResponse'
        '400':
          description: The request was invalid, the transform failed, or generated X12 failed validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: No outgoing map matched the supplied partner, metadata, and content type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
  /v1/as2/send:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: sendAs2Message
      tags:
        - Outbound AS2
      summary: Send a standalone outbound document
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends a standalone outbound document to the configured trading partner.
        Send the source XML, JSON, or text input as the HTTP request body.
        ModernEDI looks up the matching outgoing map by partner, X12 version,
        functional group, transaction set, and request `Content-Type`, applies
        that map to generate X12, syntax-checks the generated X12, then sends it
        through the configured AS2 connection. JSON source maps can use XSLT
        with Saxon `json-to-xml($json)` or JSLT. For JSLT, ModernEDI sets
        the current input `.` to a wrapper object, so the source document is
        read through `.input` paths. Send `partnerId` to select the partner; use
        `GET /v1/partners` when your integration client needs to discover stable
        partner ids.
        If the outgoing map needs extra runtime parameters such as a
        bill-of-lading number, pallet list, or generated control number, send
        the JSON envelope shape with `input`, `contentType`, and `params`.
        The envelope can also include `businessKey` when your system knows a
        stable purchase order, shipment, BOL, or other business identifier that
        should appear on the outbound transaction record.
        XSLT maps receive those params as top-level stylesheet parameters;
        JSLT maps receive them under `.params`. Mapper-editor params files are
        test fixtures only; live API calls must provide required params in this
        request envelope.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/send?partnerId=1&x12Version=4010&functionalGroupType=PO&transactionGroupType=850" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/json" \
              -H "Idempotency-Key: send-po-demo-1001" \
              --data '{
                "contentType": "application/xml",
                "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><orderDate>20260520</orderDate><shipTo><id>DC-DEMO</id></shipTo></PurchaseOrder>",
                "businessKey": {
                  "name": "purchaseOrderNumber",
                  "value": "PO-DEMO-1001"
                },
                "params": {
                  "transactionSetControlNumber": "000002321",
                  "buyerContact": {
                    "name": "Demo Buyer",
                    "email": "buyer@example.com"
                  },
                  "orderNotes": [
                    "Deliver during receiving hours",
                    "Use buyer routing guide"
                  ]
                }
              }'
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.post(
                "https://api.modernedi.com/v1/as2/send",
                params={
                    "partnerId": 1,
                    "x12Version": "4010",
                    "functionalGroupType": "PO",
                    "transactionGroupType": "850",
                },
                headers={
                    "x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"],
                    "Content-Type": "application/json",
                    "Idempotency-Key": "send-po-demo-1001",
                },
                json={
                    "contentType": "application/xml",
                    "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><orderDate>20260520</orderDate><shipTo><id>DC-DEMO</id></shipTo></PurchaseOrder>",
                    "businessKey": {
                        "name": "purchaseOrderNumber",
                        "value": "PO-DEMO-1001",
                    },
                    "params": {
                        "transactionSetControlNumber": "000002321",
                        "buyerContact": {
                            "name": "Demo Buyer",
                            "email": "buyer@example.com",
                        },
                        "orderNotes": [
                            "Deliver during receiving hours",
                            "Use buyer routing guide",
                        ],
                    },
                },
                timeout=30,
            )
            response.raise_for_status()
        - lang: JavaScript
          label: Node.js
          source: |
            const url = new URL("https://api.modernedi.com/v1/as2/send")
            url.search = new URLSearchParams({
              partnerId: "1",
              x12Version: "4010",
              functionalGroupType: "PO",
              transactionGroupType: "850",
            })

            const response = await fetch(url, {
              method: "POST",
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                "Content-Type": "application/json",
                "Idempotency-Key": "send-po-demo-1001",
              },
              body: JSON.stringify({
                contentType: "application/xml",
                input: "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><orderDate>20260520</orderDate><shipTo><id>DC-DEMO</id></shipTo></PurchaseOrder>",
                businessKey: {
                  name: "purchaseOrderNumber",
                  value: "PO-DEMO-1001",
                },
                params: {
                  transactionSetControlNumber: "000002321",
                  buyerContact: {
                    name: "Demo Buyer",
                    email: "buyer@example.com",
                  },
                  orderNotes: [
                    "Deliver during receiving hours",
                    "Use buyer routing guide",
                  ],
                },
              }),
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/OutboundPartnerId'
        - $ref: '#/components/parameters/OutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
      requestBody:
        required: true
        description: Source document to transform into X12. Its media type participates in outgoing-map selection; send XML, JSON, or text that matches the selected map's configured input content type.
        content:
          application/xml:
            schema:
              type: string
            example: |
              <PurchaseOrder>
                <orderNumber>PO-DEMO-1001</orderNumber>
                <orderDate>20260520</orderDate>
                <department code="D12">Demo Department</department>
                <shipTo>
                  <id>DC-DEMO</id>
                  <name>Demo Distribution Center</name>
                </shipTo>
              </PurchaseOrder>
          application/vnd.modernedi.outbound+json:
            schema:
              $ref: '#/components/schemas/OutboundTransformEnvelope'
          application/json:
            schema:
              anyOf:
                - type: object
                  additionalProperties: true
                - type: array
                  items: {}
                - type: string
                  nullable: true
                - type: number
                - type: boolean
            examples:
              jsonSourceInput:
                summary: JSON source input
                value:
                  orderNumber: PO-DEMO-1001
                  orderDate: '20260520'
                  department:
                    code: D12
                    name: Demo Department
                  shipTo:
                    id: DC-DEMO
                    name: Demo Distribution Center
                  lines:
                    - position: 1
                      quantity: 24
                      unitOfMeasure: EA
                      unitPrice: '10.00'
                      buyerItemNumber: DEMO-BUY-001
                      description: Demo Item Alpha
          text/plain:
            schema:
              type: string
            example: PO-DEMO-1001|20260520|D12|Demo Distribution Center
      responses:
        '200':
          description: >
            Outbound AS2 message accepted, transformed into X12, and sent. The
            `x12` field is generated output returned for visibility; request
            bodies remain XML, JSON, text, or the transform envelope.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
              example:
                success: true
                messageId: <generated-message-id@modernedi>
                x12: ISA*00*          *00*          *ZZ*SENDERID       *ZZ*RECEIVERID     *260427*2100*U*00401*000000001*0*T*>~GS*PO*SENDER*RECEIVER*20260427*2100*1*X*004010~ST*850*000000001~BEG*00*SA*PO-DEMO-1001**20260520~REF*DP*D12~N1*ST*Demo Distribution Center*92*DC-DEMO~PO1*1*24*EA*10.00**IN*DEMO-BUY-001~CTT*1~SE*6*000000001~GE*1*1~IEA*1*000000001~
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          description: The Idempotency-Key is already in progress or was reused for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: idempotency_key_conflict
                  message: This Idempotency-Key was already used for a different request body or operation.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '400':
          description: >
            The source input could not be transformed, or the generated X12
            failed syntax validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: invalid_generated_x12
                  message: Outgoing map generated invalid X12.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '404':
          description: No outgoing map matched the supplied partner, transaction metadata, and content type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: not_found
                  message: No outgoing transform map matched partnerId "1", x12Version "4010", functionalGroupType "PO", transactionGroupType "850", and contentType "application/xml".
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The generated X12 could not be delivered to the tenant AS2 runtime.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: tenant_as2_send_failed
                  message: The tenant AS2 runtime rejected the outbound message.
                  retryable: true
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    tenantAs2StatusCode: 502
        default:
          description: >
            A non-2xx status was returned by the downstream partner AS2 endpoint
            and was forwarded back to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/as2/reply:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: replyToInboundAs2Message
      tags:
        - Outbound AS2
      summary: Send a follow-up document tied to an inbound message
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends a follow-up document such as an ASN or invoice in response to a
        previously received inbound message. Send the source XML, JSON, or text
        input as the HTTP request body. ModernEDI looks up the original
        message by `originalMessageId`, and uses unambiguous metadata from that
        inbound transaction to recover an omitted partner selector and
        `x12Version`. When the inbound AS2 message contains more than one
        transaction set, send `originalTransactionKey` to bind the reply to the
        exact `GS06#ST02` transaction. ModernEDI validates that composite
        reference before transforming or sending; an unknown or non-inbound
        reference returns `404`. When it is omitted, ModernEDI resolves and
        persists the key only if the message contains exactly one inbound
        transaction; an ambiguous multi-transaction message returns `400`.
        This lookup uses production transaction history by default;
        send `test=true` to infer from and link to isolated test history.
        ModernEDI uses the persisted `partnerId`, so the reply
        still selects the same partner after its configured name changes.
        Transactions without a persisted partner id do not supply inferred
        partner metadata. An explicit `partnerId` always overrides inferred
        partner metadata. After the partner id, X12 version, and request
        `Content-Type` are known, ModernEDI can
        also fill omitted `functionalGroupType` and `transactionGroupType` when
        those selectors match exactly one outgoing reply map. ModernEDI then
        selects the matching outgoing map by partner, X12 version, functional
        group, transaction set, and request `Content-Type`, generates and
        validates X12, then sends the reply through the configured AS2
        connection.
        Send `x12Version` explicitly when a partner requires reply documents on
        a different X12 version than the one they send; explicit query parameters
        override inferred metadata.
        If multiple reply maps could match, send `functionalGroupType` and
        `transactionGroupType` explicitly. The original inbound document type is
        not reused as the reply type; these fields identify the generated reply
        document, such as `IN`/`810` for an invoice. JSON source maps can use XSLT
        with Saxon `json-to-xml($json)` or JSLT. For JSLT, ModernEDI sets
        the current input `.` to a wrapper object, so the source document is
        read through `.input` paths.
        If the outgoing map needs extra runtime parameters, send the JSON
        envelope shape with `input`, `contentType`, and `params`; XSLT maps
        receive those values as top-level stylesheet parameters, JSLT maps read
        them from `.params`, and mapper-editor params files are not used as live
        defaults. Use the envelope's optional `businessKey` field when the reply
        has a stable identifier, such as an invoice number, that should be stored
        on the outbound transaction record.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/reply?originalMessageId=%3Cinbound-message-id%40partner%3E" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/json" \
              -H "Idempotency-Key: reply-invoice-demo-1001" \
              --data '{
                "contentType": "application/xml",
                "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><invoice><number>INV-DEMO-1001</number><date>20260525</date></invoice><totals><amount>240.00</amount></totals></PurchaseOrder>",
                "businessKey": {
                  "name": "invoiceNumber",
                  "value": "INV-DEMO-1001"
                },
                "params": {
                  "invoiceDate": "20260525",
                  "termsCode": "05",
                  "termDays": 30
                }
              }'
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.post(
                "https://api.modernedi.com/v1/as2/reply",
                params={
                    "originalMessageId": "<inbound-message-id@partner>",
                },
                headers={
                    "x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"],
                    "Content-Type": "application/json",
                    "Idempotency-Key": "reply-invoice-demo-1001",
                },
                json={
                    "contentType": "application/xml",
                    "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><invoice><number>INV-DEMO-1001</number><date>20260525</date></invoice><totals><amount>240.00</amount></totals></PurchaseOrder>",
                    "businessKey": {
                        "name": "invoiceNumber",
                        "value": "INV-DEMO-1001",
                    },
                    "params": {
                        "invoiceDate": "20260525",
                        "termsCode": "05",
                        "termDays": 30,
                    },
                },
                timeout=30,
            )
            response.raise_for_status()
        - lang: JavaScript
          label: Node.js
          source: |
            const url = new URL("https://api.modernedi.com/v1/as2/reply")
            url.search = new URLSearchParams({
              originalMessageId: "<inbound-message-id@partner>",
            })

            const response = await fetch(url, {
              method: "POST",
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                "Content-Type": "application/json",
                "Idempotency-Key": "reply-invoice-demo-1001",
              },
              body: JSON.stringify({
                contentType: "application/xml",
                input: "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><invoice><number>INV-DEMO-1001</number><date>20260525</date></invoice><totals><amount>240.00</amount></totals></PurchaseOrder>",
                businessKey: {
                  name: "invoiceNumber",
                  value: "INV-DEMO-1001",
                },
                params: {
                  invoiceDate: "20260525",
                  termsCode: "05",
                  termDays: 30,
                },
              }),
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/ReplyOutboundPartnerId'
        - $ref: '#/components/parameters/ReplyOutboundX12Version'
        - $ref: '#/components/parameters/ReplyOutboundFunctionalGroupType'
        - $ref: '#/components/parameters/ReplyOutboundTransactionGroupType'
        - $ref: '#/components/parameters/OriginalMessageId'
        - $ref: '#/components/parameters/OriginalTransactionKey'
      requestBody:
        required: true
        description: Source document to transform into the X12 reply. Its media type participates in outgoing-map selection; the body is not raw X12 unless you use the corresponding `/v1/as2/x12/reply` endpoint.
        content:
          application/xml:
            schema:
              type: string
            example: |
              <PurchaseOrder>
                <orderNumber>PO-DEMO-1001</orderNumber>
                <invoice>
                  <number>INV-DEMO-1001</number>
                  <date>20260525</date>
                </invoice>
                <totals>
                  <amount>240.00</amount>
                </totals>
              </PurchaseOrder>
          application/vnd.modernedi.outbound+json:
            schema:
              $ref: '#/components/schemas/OutboundTransformEnvelope'
          application/json:
            schema:
              anyOf:
                - type: object
                  additionalProperties: true
                - type: array
                  items: {}
                - type: string
                  nullable: true
                - type: number
                - type: boolean
            examples:
              jsonSourceInput:
                summary: JSON source input
                value:
                  orderNumber: PO-DEMO-1001
                  invoice:
                    number: INV-DEMO-1001
                    date: '20260525'
                  totals:
                    amount: '240.00'
          text/plain:
            schema:
              type: string
            example: PO-DEMO-1001|INV-DEMO-1001|20260525|240.00
      responses:
        '200':
          description: >
            Outbound reply accepted, transformed into X12, and sent. The `x12`
            field is generated output returned for visibility; request bodies
            remain XML, JSON, text, or the transform envelope.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
              example:
                success: true
                messageId: <generated-message-id@modernedi>
                x12: ISA*00*          *00*          *ZZ*SENDERID       *ZZ*RECEIVERID     *260427*2100*U*00401*000000001*0*T*>~GS*IN*SENDER*RECEIVER*20260427*2100*1*X*004010~ST*810*000000001~BIG*20260427*INV-DEMO-1001*20260420*PO-DEMO-1001~IT1*1*24*EA*10.00**IN*DEMO-BUY-001~TDS*24000~SE*5*000000001~GE*1*1~IEA*1*000000001~
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          description: The Idempotency-Key is already in progress or was reused for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: idempotency_key_conflict
                  message: This Idempotency-Key was already used for a different request body or operation.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '400':
          description: >
            The source input could not be transformed, or the generated X12
            failed syntax validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: invalid_generated_x12
                  message: Outgoing map generated invalid X12.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '404':
          description: No outgoing map matched the supplied partner, transaction metadata, and content type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: not_found
                  message: No outgoing transform map matched partnerId "1", x12Version "4010", functionalGroupType "IN", transactionGroupType "810", and contentType "application/xml".
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The generated X12 could not be delivered to the tenant AS2 runtime.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: tenant_as2_send_failed
                  message: The tenant AS2 runtime rejected the outbound message.
                  retryable: true
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    tenantAs2StatusCode: 502
        default:
          description: >
            A non-2xx status was returned by the downstream partner AS2 endpoint
            and was forwarded back to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/as2/carbonCopy:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: sendAs2CarbonCopy
      tags:
        - Outbound AS2
      summary: Send a carbon copy of an inbound message flow to another partner
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends a generated X12 document to a second partner while preserving
        context from a previously received inbound message. Send the source XML,
        JSON, or text input as the HTTP request body. The `partnerId` query
        parameter identifies the source/original partner whose outgoing map
        should generate the X12, and `copyToPartnerId` identifies the destination partner for the copied AS2
        envelope. ModernEDI selects the matching
        outgoing map for that original/source partner, generates and validates X12,
        then forwards the carbon copy through the configured AS2 connection.
        Example: to generate an 856 ASN for Retailer One and copy it to Broker One,
        send `partnerId=1` and `copyToPartnerId=2`; ModernEDI uses partner 1's
        outgoing 856 map. `copyToPartnerId` does not select the outgoing map.
        JSON source maps can use XSLT with Saxon
        `json-to-xml($json)` or JSLT. For JSLT, ModernEDI sets the current
        input `.` to a wrapper object, so the source document is read through
        `.input` paths. If the
        outgoing map needs extra runtime parameters, send the JSON envelope
        shape with `input`, `contentType`, and `params`; the map is still
        selected by `partnerId`, not by `copyToPartnerId`. XSLT maps
        receive params as top-level stylesheet parameters, JSLT maps read them
        from `.params`, and mapper-editor params files are test fixtures only
        and are not read by live carbon-copy calls. The envelope's optional
        `businessKey` is recorded on the copied outbound transaction, but it
        does not affect map selection. Send `originalTransactionKey` when the
        source message contains multiple transaction sets and this copy belongs
        to one exact transaction.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/carbonCopy?partnerId=1&copyToPartnerId=2&x12Version=4010&functionalGroupType=SH&transactionGroupType=856&originalMessageId=msg-850-api" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/json" \
              -H "Idempotency-Key: carbon-copy-asn-demo-1001" \
              --data '{
                "contentType": "application/xml",
                "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><shipment><id>ASN-DEMO-1001</id><date>20260526</date></shipment></PurchaseOrder>",
                "businessKey": {
                  "name": "shipmentId",
                  "value": "ASN-DEMO-1001"
                },
                "params": {
                  "bolNumber": "BOL-DEMO-8842",
                  "totalWeightInLbs": 1232.54,
                  "transactionSetControlNumber": "000002321"
                }
              }'
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.post(
                "https://api.modernedi.com/v1/as2/carbonCopy",
                params={
                    "partnerId": 1,
                    "copyToPartnerId": 2,
                    "x12Version": "4010",
                    "functionalGroupType": "SH",
                    "transactionGroupType": "856",
                    "originalMessageId": "msg-850-api",
                },
                headers={
                    "x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"],
                    "Content-Type": "application/json",
                    "Idempotency-Key": "carbon-copy-asn-demo-1001",
                },
                json={
                    "contentType": "application/xml",
                    "input": "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><shipment><id>ASN-DEMO-1001</id><date>20260526</date></shipment></PurchaseOrder>",
                    "businessKey": {
                        "name": "shipmentId",
                        "value": "ASN-DEMO-1001",
                    },
                    "params": {
                        "bolNumber": "BOL-DEMO-8842",
                        "totalWeightInLbs": 1232.54,
                        "transactionSetControlNumber": "000002321",
                    },
                },
                timeout=30,
            )
            response.raise_for_status()
        - lang: JavaScript
          label: Node.js
          source: |
            const url = new URL("https://api.modernedi.com/v1/as2/carbonCopy")
            url.search = new URLSearchParams({
              partnerId: "1",
              copyToPartnerId: "2",
              x12Version: "4010",
              functionalGroupType: "SH",
              transactionGroupType: "856",
              originalMessageId: "msg-850-api",
            })

            const response = await fetch(url, {
              method: "POST",
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                "Content-Type": "application/json",
                "Idempotency-Key": "carbon-copy-asn-demo-1001",
              },
              body: JSON.stringify({
                contentType: "application/xml",
                input: "<PurchaseOrder><orderNumber>PO-DEMO-1001</orderNumber><shipment><id>ASN-DEMO-1001</id><date>20260526</date></shipment></PurchaseOrder>",
                businessKey: {
                  name: "shipmentId",
                  value: "ASN-DEMO-1001",
                },
                params: {
                  bolNumber: "BOL-DEMO-8842",
                  totalWeightInLbs: 1232.54,
                  transactionSetControlNumber: "000002321",
                },
              }),
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/OutboundPartnerId'
        - $ref: '#/components/parameters/OutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
        - $ref: '#/components/parameters/OriginalMessageId'
        - $ref: '#/components/parameters/OriginalTransactionKey'
        - $ref: '#/components/parameters/CopyToPartnerId'
      requestBody:
        required: true
        description: Source document to transform into the carbon-copy X12 payload. Its media type participates in selecting the source partner's outgoing map.
        content:
          application/xml:
            schema:
              type: string
            example: |
              <PurchaseOrder>
                <orderNumber>PO-DEMO-1001</orderNumber>
                <shipment>
                  <id>ASN-DEMO-1001</id>
                  <date>20260526</date>
                  <time>1015</time>
                  <billOfLading>BOL-DEMO-1001</billOfLading>
                </shipment>
              </PurchaseOrder>
          application/vnd.modernedi.outbound+json:
            schema:
              $ref: '#/components/schemas/OutboundTransformEnvelope'
          application/json:
            schema:
              anyOf:
                - type: object
                  additionalProperties: true
                - type: array
                  items: {}
                - type: string
                  nullable: true
                - type: number
                - type: boolean
            examples:
              jsonSourceInput:
                summary: JSON source input
                value:
                  orderNumber: PO-DEMO-1001
                  shipment:
                    id: ASN-DEMO-1001
                    date: '20260526'
                    time: '1015'
                    billOfLading: BOL-DEMO-1001
          text/plain:
            schema:
              type: string
            example: PO-DEMO-1001|ASN-DEMO-1001|20260526|1015|BOL-DEMO-1001
      responses:
        '200':
          description: >
            Outbound carbon copy accepted, transformed into X12, and sent. The
            `x12` field is generated output returned for visibility; request
            bodies remain XML, JSON, text, or the transform envelope.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
              example:
                success: true
                messageId: <generated-message-id@modernedi>
                x12: ISA*00*          *00*          *ZZ*SENDERID       *ZZ*RECEIVERID     *260427*2100*U*00401*000000001*0*T*>~GS*SH*SENDER*RECEIVER*20260427*2100*1*X*004010~ST*856*000000001~BSN*00*ASN0001*20260427*2100~HL*1**S~TD5*B*2*UPSN*M*GROUND~REF*CN*1Z999999~HL*2*1*O~PRF*PO0001~SE*8*000000001~GE*1*1~IEA*1*000000001~
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          description: The Idempotency-Key is already in progress or was reused for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: idempotency_key_conflict
                  message: This Idempotency-Key was already used for a different request body or operation.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '400':
          description: >
            The source input could not be transformed, or the generated X12
            failed syntax validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: invalid_generated_x12
                  message: Outgoing map generated invalid X12.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '404':
          description: No outgoing map matched the supplied partner, transaction metadata, and content type.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: not_found
                  message: No outgoing transform map matched partnerId "1", x12Version "4010", functionalGroupType "SH", transactionGroupType "856", and contentType "application/xml".
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The generated X12 could not be delivered to the tenant AS2 runtime.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                success: false
                error:
                  code: tenant_as2_send_failed
                  message: The tenant AS2 runtime rejected the outbound message.
                  retryable: true
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    tenantAs2StatusCode: 502
        default:
          description: >
            A non-2xx status was returned by the downstream partner AS2 endpoint
            and was forwarded back to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/as2/x12/send:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: sendGeneratedX12Message
      tags:
        - Outbound AS2
      summary: Send an already-generated X12 document
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends X12 that your system generated without applying a ModernEDI
        outgoing map. ModernEDI parses and validates the supplied X12, builds
        the AS2 message, and delivers it through the selected partner connection.
        Supply the X12 directly with `Content-Type: application/edi-x12` (or
        `text/plain`), or use the JSON envelope when you also want to record a
        business key. The partner selector and X12 metadata remain explicit so
        ModernEDI can choose and audit the correct destination. Use
        `/v1/as2/send` instead when ModernEDI should map your business document
        into X12 first.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/x12/send?partnerId=1&x12Version=4010&functionalGroupType=PO&transactionGroupType=850" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/edi-x12" \
              -H "Idempotency-Key: raw-po-100045" \
              --data-binary @purchase-order.edi
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/OutboundPartnerId'
        - $ref: '#/components/parameters/OutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
      requestBody:
        $ref: '#/components/requestBodies/GeneratedX12Body'
      responses:
        '200':
          description: The supplied X12 was validated and sent over AS2.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
        '400':
          description: The request or supplied X12 was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The selected partner was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: The idempotency key was previously used for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The selected tenant AS2 runtime or partner destination was unreachable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: A downstream partner AS2 status was forwarded to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/as2/x12/reply:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: replyWithGeneratedX12
      tags:
        - Outbound AS2
      summary: Reply to an inbound message with already-generated X12
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends X12 that your system generated as a reply tied to an inbound AS2
        message. ModernEDI does not apply an outgoing map. When the partner or
        X12 version is omitted, `originalMessageId` can recover it from the
        selected transaction history. Use `originalTransactionKey` to bind a
        reply to one exact transaction in a multi-ST message; the composite
        reference is validated before delivery. Production history is the default; send
        `test=true` to infer from and link to isolated test history. The functional group
        and transaction-set identifiers describe the reply document and remain
        required because they are not copied from the original inbound document.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/x12/reply?originalMessageId=%3Cinbound-message-id%40partner%3E&functionalGroupType=IN&transactionGroupType=810" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/edi-x12" \
              -H "Idempotency-Key: raw-invoice-100045" \
              --data-binary @invoice.edi
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/ReplyOutboundPartnerId'
        - $ref: '#/components/parameters/ReplyOutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
        - $ref: '#/components/parameters/OriginalMessageId'
        - $ref: '#/components/parameters/OriginalTransactionKey'
      requestBody:
        $ref: '#/components/requestBodies/GeneratedX12Body'
      responses:
        '200':
          description: The supplied X12 reply was validated and sent over AS2.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
        '400':
          description: The request or supplied X12 was invalid or reply metadata was ambiguous.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The original message or selected partner was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: The idempotency key was previously used for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The selected tenant AS2 runtime or partner destination was unreachable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: A downstream partner AS2 status was forwarded to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/as2/x12/carbonCopy:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: carbonCopyGeneratedX12
      tags:
        - Outbound AS2
      summary: Send already-generated X12 to a carbon-copy partner
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Sends supplied X12 to a second partner while preserving the original
        transaction context. ModernEDI validates the X12 but does not apply an
        outgoing map. Select the original partner with `partnerId` and the
        recipient with `copyToPartnerId`. Use
        `originalTransactionKey` when the original AS2 message contains more
        than one transaction set.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/as2/x12/carbonCopy?partnerId=1&copyToPartnerId=2&originalMessageId=msg-850-api&x12Version=4010&functionalGroupType=SH&transactionGroupType=856" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/edi-x12" \
              -H "Idempotency-Key: raw-asn-copy-100045" \
              --data-binary @shipment.edi
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TestMode'
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/OutboundPartnerId'
        - $ref: '#/components/parameters/OutboundX12Version'
        - $ref: '#/components/parameters/OutboundFunctionalGroupType'
        - $ref: '#/components/parameters/OutboundTransactionGroupType'
        - $ref: '#/components/parameters/OriginalMessageId'
        - $ref: '#/components/parameters/OriginalTransactionKey'
        - $ref: '#/components/parameters/CopyToPartnerId'
      requestBody:
        $ref: '#/components/requestBodies/GeneratedX12Body'
      responses:
        '200':
          description: The supplied X12 was validated and sent to the carbon-copy partner.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SendSuccessResponse'
        '400':
          description: The request or supplied X12 was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The original transaction or selected partner was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: The idempotency key was previously used for a different request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '429':
          $ref: '#/components/responses/TenantAs2RateLimitError'
        '502':
          description: The selected tenant AS2 runtime or partner destination was unreachable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        default:
          description: A downstream partner AS2 status was forwarded to the caller.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/mappings:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationMappings
      tags:
        - Mappings
      summary: List published mappings
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns the tenant's published incoming and outgoing maps, including the full transform source, delivery category, and each resource ETag. Infrastructure details are never exposed.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: Mappings were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingListResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    post:
      operationId: createIntegrationMapping
      tags:
        - Mappings
      summary: Publish a mapping
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Publishes a map and archives its initial revision. Incoming mappings require `direction: INCOMING`, `transform.type: X12_MAPPER`, and `businessKey`; incoming mappings deliver through the managed mapped-output polling and webhook lane and cannot name arbitrary infrastructure destinations. Outgoing mappings require `direction: OUTGOING`, `transform.type: XSLT` or `JSLT`, and `output.purpose: PROCESSING`. `output.delivery` is a response-only field selected by ModernEDI.

        Before publishing, ModernEDI parses and semantically checks incoming X12 Mapper source and its business-key extractor against the selected X12 version and transaction set. Outgoing XSLT and JSLT source is compiled with the hosted runtime compiler. A failure returns `422 mapping_validation_failed` with field-specific diagnostics and does not create a mapping or revision.

        `Idempotency-Key` is required. Repeating the same tenant-scoped key with the same JSON request returns the existing mapping with `Idempotency-Replayed: true` and does not create another mapping or revision. JSON object field order does not affect request identity. Reusing the key with a different request returns `409 idempotency_key_conflict`. If the originally created mapping was later deleted, reuse returns `409 idempotency_result_unavailable`; use a new key only when you intend to create a new mapping.
      x-codeSamples:
        - lang: curl
          label: Incoming map
          source: |
            curl -X POST "https://api.modernedi.com/v1/mappings" \
              -H "Content-Type: application/json" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Idempotency-Key: mapping-850-incoming-v1" \
              --data @examples/mapping-incoming-create-request.json
        - lang: curl
          label: Outgoing map
          source: |
            curl -X POST "https://api.modernedi.com/v1/mappings" \
              -H "Content-Type: application/json" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Idempotency-Key: mapping-810-outgoing-v1" \
              --data @examples/mapping-outgoing-create-request.json
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MappingCreateIdempotencyKey'
      requestBody:
        required: true
        description: Mapping configuration bodies may be at most 1 MiB (1,048,576 bytes). This is a transport ceiling for the complete JSON document, not a guaranteed maximum transform-source size.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MappingWriteRequest'
      responses:
        '201':
          description: The mapping was published in configuration storage. The response `ETag` matches `mapping.etag`; inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            Idempotency-Replayed:
              $ref: '#/components/headers/MappingIdempotencyReplayed'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '409':
          $ref: '#/components/responses/MappingIdempotencyConflictError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/MappingValidationError'
  /v1/mappings/{mappingId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: mappingId
        in: path
        required: true
        description: Tenant-scoped mapping id.
        schema:
          type: integer
          minimum: 1
    get:
      operationId: getIntegrationMapping
      tags:
        - Mappings
      summary: Get a published mapping
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns one published map, its complete source text, safe output configuration, delivery category, patchability, and concurrency-control ETag.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: The mapping was returned.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    patch:
      operationId: patchIntegrationMapping
      tags:
        - Mappings
      summary: Update and republish a mapping
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Deep-merges the supplied fields with the current configuration, validates the complete resulting mapping, archives the prior revision, and publishes it. Send the current resource ETag in `If-Match`. For a source-only deployment, send `{ "transform": { "source": "..." } }`.

        Incoming X12 Mapper source and its business-key extractor are parsed and semantically checked against the selected X12 version and transaction set. Outgoing XSLT and JSLT source is compiled with the hosted runtime compiler. A `422 mapping_validation_failed` response leaves the currently published mapping and revision unchanged.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      requestBody:
        required: true
        description: Mapping configuration bodies may be at most 1 MiB (1,048,576 bytes). This is a transport ceiling for the complete JSON document, not a guaranteed maximum transform-source size.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MappingPatchRequest'
            example:
              transform:
                source: '"{\"purchaseOrderNumber\":\"" + ST->BEG(03) + "\"}"'
      responses:
        '200':
          description: The mapping was updated in configuration storage. Inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingMutationResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/MappingValidationError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
    delete:
      operationId: deleteIntegrationMapping
      tags:
        - Mappings
      summary: Delete a mapping
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Archives the current revision and deletes the published mapping. Send the current resource ETag in `If-Match`. Delete remains available when the aggregate runtime configuration already exceeds 12 MiB so configuration can be reduced; `runtimePublication.state` may remain `pending` until the document is below the cap.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      responses:
        '200':
          description: The mapping was deleted. Inspect `runtimePublication` for runtime activation state.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                type: object
                required: [success, deletedMappingId, runtimePublication]
                properties:
                  success:
                    type: boolean
                    enum: [true]
                    description: Always `true`; deletion conflicts or failures use the documented error response instead.
                  deletedMappingId:
                    type: integer
                    description: Stable workspace-scoped id of the mapping that was deleted.
                  runtimePublication:
                    $ref: '#/components/schemas/RuntimePublication'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
  /v1/mappings/{mappingId}/revisions:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: mappingId
        in: path
        required: true
        description: Tenant-scoped mapping id.
        schema:
          type: integer
          minimum: 1
    get:
      operationId: listIntegrationMappingSourceVersions
      tags:
        - Mappings
      summary: List a mapping's source history
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns one page of the immutable transform-source versions retained for a published mapping, newest first. Page entries intentionally omit source text; fetch one source version by id to preview it or compute a diff. Follow `nextCursor` while `hasMore` is true. Cursors are opaque and must be sent back unchanged.

        `currentSourceVersion` always contains the complete currently published source, even when that source's chronological entry is outside this page. It and `currentEtag` are read from the same locked configuration snapshot, so clients can use them as an authoritative diff baseline and restore precondition. If `currentEtag` changes between page requests, restart from the first page before presenting a coherent history view.

        This is source history, not a full configuration audit log. A source version retains the transform type and filename recorded with that source, but partner selection, X12 identity, output, business-key, and active-attribute changes are not independently versioned here. `current` compares a stored source hash with the source that is currently published.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/mappings/31/revisions" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: cursor
          in: query
          required: false
          description: Opaque `nextCursor` from the preceding source-history page. Omit for the first page.
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: Maximum chronological source-version summaries to return. `currentSourceVersion` is returned separately and does not count against this limit.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
      responses:
        '200':
          description: Source history was returned. The response `ETag` matches `currentEtag` and protects the complete currently published mapping.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingSourceVersionListResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/mappings/{mappingId}/revisions/{sourceVersionId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: mappingId
        in: path
        required: true
        description: Tenant-scoped mapping id.
        schema:
          type: integer
          minimum: 1
      - name: sourceVersionId
        in: path
        required: true
        description: Source-version id returned by the mapping history endpoint.
        schema:
          type: integer
          minimum: 1
    get:
      operationId: getIntegrationMappingSourceVersion
      tags:
        - Mappings
      summary: Get a historical mapping source
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns one immutable historical transform source for preview or diffing. The source version must belong to the tenant-scoped mapping in the path. Its transform filename is historical context; restoring this version changes only `transform.source` and keeps the currently published filename and all other mapping configuration.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: The source version was returned. The response `ETag` protects the complete currently published mapping, not the immutable historical source.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingSourceVersionResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/mappings/{mappingId}/revisions/{sourceVersionId}/restore:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - name: mappingId
        in: path
        required: true
        description: Tenant-scoped mapping id.
        schema:
          type: integer
          minimum: 1
      - name: sourceVersionId
        in: path
        required: true
        description: Source-version id returned by the mapping history endpoint.
        schema:
          type: integer
          minimum: 1
    post:
      operationId: restoreIntegrationMappingSourceVersion
      tags:
        - Mappings
      summary: Restore a historical mapping source
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Republishes the selected historical `transform.source` as the current source. Send the mapping's current ETag, available from `GET /v1/mappings/{mappingId}` or the history response's `currentEtag`, in `If-Match`. This prevents a restore from overwriting a concurrent workspace or API edit.

        Restore deliberately keeps the current mapping's transform filename, partner, direction, X12 selection, output, business key, and active attributes. ModernEDI validates the historical source against that current configuration using the same parser or compiler as a normal mapping PATCH. A validation failure returns `422 mapping_validation_failed` without changing the mapping. A successful restore follows the normal runtime-publication lane and returns the newly current mapping and ETag. Because source history is deduplicated by source hash, restoring a saved source makes its existing version current; it does not create a duplicate immutable history entry.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/mappings/31/revisions/87/restore" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H 'If-Match: "<etag-from-the-latest-mapping-or-history-response>"'
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/IfMatch'
      responses:
        '200':
          description: The historical source was validated and published. The response `ETag` matches `mapping.etag`; inspect `runtimePublication` to determine whether the committed change is already active in the tenant runtime.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingMutationResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          $ref: '#/components/responses/ConfigurationNotFoundError'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '413':
          $ref: '#/components/responses/ConfigurationMutationTooLargeError'
        '422':
          $ref: '#/components/responses/MappingValidationError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
  /v1/mapped-outputs:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: pollMappedOutputs
      tags:
        - Mapped Output Queue
      summary: Poll mapped inbound output
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns server-managed mapped inbound documents for this tenant and
        temporarily marks them in progress. Transaction-record-only results and
        legacy direct-to-SQS or direct-to-DynamoDB outputs are not duplicated
        into this queue. If a returned message is not acknowledged before the
        visibility timeout expires, ModernEDI may return it again on a later
        poll. Push delivery uses the same queue state: a successful 2xx webhook
        response acknowledges the message, while a failed push leaves it
        available through this endpoint. Each request performs a bounded scan.
        When `hasMore` is true, send `nextCursor` as the next request's `cursor`
        so polling advances past unavailable or output-free transactions instead
        of rescanning them. This endpoint runs on the shared ModernEDI API host,
        not on the tenant AS2 hostname.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/mapped-outputs?limit=10&visibilityTimeoutSeconds=120" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.get(
                "https://api.modernedi.com/v1/mapped-outputs",
                params={"limit": 10, "visibilityTimeoutSeconds": 120},
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            messages = response.json()["messages"]
        - lang: JavaScript
          label: Node.js
          source: |
            const url = new URL("https://api.modernedi.com/v1/mapped-outputs")
            url.search = new URLSearchParams({
              limit: "10",
              visibilityTimeoutSeconds: "120",
            })

            const response = await fetch(url, {
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
              },
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { messages } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
        - name: startDate
          in: query
          required: false
          schema:
            type: string
          description: >
            Optional inclusive transaction-window start. Accepts an ISO date or
            an RFC 3339 date-time with an explicit offset. Date-only values start
            at 00:00:00 UTC. Date-times are normalized to UTC; offset-less
            date-times are rejected.
          example: '2026-07-01T00:00:00.000000000Z'
        - name: endDate
          in: query
          required: false
          schema:
            type: string
          description: >
            Optional inclusive transaction-window end. Accepts the same formats
            as `startDate`; a date-only value includes the complete UTC day.
          example: '2026-07-15'
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: >
            Opaque continuation cursor returned as `nextCursor`. When supplied,
            it retains the original transaction window; omit `startDate` and
            `endDate` or send the same normalized values.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 10
          description: Maximum number of mapped output messages to return.
        - name: visibilityTimeoutSeconds
          in: query
          required: false
          schema:
            type: integer
            minimum: 5
            maximum: 43200
            default: 120
          description: Seconds ModernEDI keeps returned messages hidden from later polls while your system processes them.
        - name: direction
          in: query
          required: false
          schema:
            type: string
            enum:
              - inbound
              - outbound
          description: Transaction direction. Mapped outputs normally come from inbound transactions.
        - name: partnerName
          in: query
          required: false
          schema:
            type: string
          description: Case-insensitive persisted partner name.
        - name: partnerId
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
          description: Tenant-scoped partner id returned by `GET /v1/partners`.
        - name: transactionSet
          in: query
          required: false
          schema:
            type: string
          description: X12 transaction-set identifier such as `850` or `856`.
        - name: businessKey
          in: query
          required: false
          schema:
            type: string
          description: Exact mapped-output business-key value.
        - name: messageId
          in: query
          required: false
          schema:
            type: string
          description: Exact AS2 Message-Id.
        - name: replyToMessageId
          in: query
          required: false
          schema:
            type: string
          description: Exact original inbound Message-Id recorded on a reply.
        - name: transactionControlNumber
          in: query
          required: false
          schema:
            type: string
          description: Exact ST02 transaction control number.
        - name: functionalGroupControlNumber
          in: query
          required: false
          schema:
            type: string
          description: Exact GS06 functional-group control number.
      responses:
        '200':
          description: Mapped output messages were returned for processing.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputQueueResponse'
              example:
                success: true
                environment: production
                messages:
                  - id: 7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a
                    receiptHandle: 0af7dd1d-b6a1-4ff9-8ad1-d395de0b97f2
                    deliveryCount: 1
                    leasedUntil: '2026-04-29T15:35:00.000000000Z'
                    environment: production
                    messageId: msg-850-api
                    transactionKey: 17#0001
                    partnerName: Customer One
                    partnerId: 1
                    transactionTimestamp: '2026-04-29T15:33:00.000000000Z'
                    transactionSet:
                      code: '850'
                      description: Purchase Order
                    controlNumbers:
                      transaction: '0001'
                      functionalGroup: '17'
                    edi:
                      x12Version: '4010'
                      functionalIdentifierCode: PO
                      transactionGroupType: '850'
                      segmentTerminator: '~'
                    mapping:
                      id: 44
                      type: ManagedQueueMapping
                      file: customer-one-850.jslt
                      fileSha256Hash: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
                    mappedOutputKey: 17#0001#00001
                    sequenceNumber: 1
                    purpose: PROCESSING
                    contentType: application/json
                    createdAt: '2026-04-29T15:33:04.000000000Z'
                    businessKey:
                      name: purchaseOrderNumber
                      value: PO-100045
                    extraFields:
                      destination: managedQueue
                    payload: '{"purchaseOrderNumber":"PO-100045","shipTo":{"name":"Main DC"}}'
                limit: 10
                visibilityTimeoutSeconds: 120
                nextCursor: null
                hasMore: false
        '400':
          description: Invalid cursor, date window, limit, or visibility timeout.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/mapped-outputs/{id}/ack:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: acknowledgeMappedOutput
      tags:
        - Mapped Output Queue
      summary: Mark mapped output as received
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Records that your integration acknowledged custody of a previously returned
        mapped output message. Call this after the mapped output has been durably
        stored or enqueued for reliable processing in your system. This acknowledgment
        does not prove later ERP or business processing. The receipt handle must match
        the latest poll response for this mapped output id. A retry with the same
        id and receipt handle is idempotent: it returns the original
        acknowledgment and `ackedAt` value instead of failing. If a call ends
        without a definitive response, retry that same acknowledgment before
        polling. Poll for a new receipt only when the old lease is rejected or
        the message becomes available again; an acknowledged item is no longer
        returned by polling.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/mapped-outputs/7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a/ack" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/json" \
              --data '{"receiptHandle":"0af7dd1d-b6a1-4ff9-8ad1-d395de0b97f2"}'
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            mapped_output_id = "7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a"
            response = requests.post(
                f"https://api.modernedi.com/v1/mapped-outputs/{mapped_output_id}/ack",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                json={"receiptHandle": "0af7dd1d-b6a1-4ff9-8ad1-d395de0b97f2"},
                timeout=30,
            )
            response.raise_for_status()
        - lang: JavaScript
          label: Node.js
          source: |
            const mappedOutputId = "7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a"
            const response = await fetch(`https://api.modernedi.com/v1/mapped-outputs/${mappedOutputId}/ack`, {
              method: "POST",
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                receiptHandle: "0af7dd1d-b6a1-4ff9-8ad1-d395de0b97f2",
              }),
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: Mapped output id returned by `GET /v1/mapped-outputs`.
        - $ref: '#/components/parameters/TransactionEnvironment'
      requestBody:
        required: true
        description: A receipt handle from the latest poll response for this mapped-output id. The id, receipt handle, and selected environment must refer to the same leased output.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MappedOutputAckRequest'
            example:
              receiptHandle: 0af7dd1d-b6a1-4ff9-8ad1-d395de0b97f2
      responses:
        '200':
          description: Mapped output was marked as received.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputAckResponse'
              example:
                success: true
                environment: production
                acknowledgment:
                  id: 7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a
                  messageId: msg-850-api
                  mappedOutputKey: 17#0001#00001
                  ackedAt: '2026-04-29T15:34:10.000000000Z'
                id: 7e8276c1d55988a4bf7fbf9f8c2d87187a24bd316dfed84bbf64397b8d5b6e4a
                messageId: msg-850-api
                mappedOutputKey: 17#0001#00001
                ackedAt: '2026-04-29T15:34:10.000000000Z'
        '400':
          description: Missing receipt handle or no current in-progress message matched the id and receipt handle.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
  /v1/mapped-outputs/ack:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: acknowledgeMappedOutputs
      tags:
        - Mapped Output Queue
      summary: Atomically acknowledge multiple mapped outputs
      x-required-scope: messages:write
      description: >
        **Required key scope:** `messages:write`.

        Acknowledges between 1 and 100 mapped-output receipts in one database
        transaction. If any id or receipt handle is invalid, none of the items
        are acknowledged. Repeating an already successful request with the same
        id and receipt handles is idempotent and returns the original
        acknowledgment timestamps. Retry the same batch first when a call ends
        without a definitive response; already acknowledged items are not
        returned by polling. All items must belong to the environment
        selected by the `environment` query parameter.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
      requestBody:
        required: true
        description: Mapped-output acknowledgment bodies may be at most 16 KiB (16,384 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MappedOutputBulkAckRequest'
      responses:
        '200':
          description: Every receipt was acknowledged or had already been acknowledged.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputBulkAckResponse'
        '400':
          description: The batch was empty, exceeded 100 items, or contained an invalid receipt.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
  /v1/integration/mapping-runtime/health:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationMappingRuntimeHealth
      tags:
        - Mapping Runtime
      summary: Get mapping runtime health
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns aggregate unresolved and recovered mapping outcomes for the
        selected environment. This view includes failures that occurred before
        an X12 transaction could be created, so its totals can be non-zero even
        when no corresponding transaction appears in the transaction list.
        `truncated=true` means the bounded health scan could not summarize every
        retained attempt; use the paginated failures endpoint for investigation.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/mapping-runtime/health?environment=production" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Mapping runtime health was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingRuntimeHealthResponse'
        '400':
          description: The environment value was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/mapping-runtime/failures:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationMappingRuntimeFailures
      tags:
        - Mapping Runtime
      summary: List mapping runtime failures
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns safe, tenant-scoped mapping failure diagnostics in reverse
        chronological order. The response deliberately omits raw source input,
        generated output, stack traces, and internal exception text. A failure
        whose `transactionReference` is null occurred before a transaction
        existed. For those pre-transaction outbound failures, `correlationId`
        is a ModernEDI request-correlation identifier rather than an AS2
        Message-Id, and `transactionKey` is `outbound-request`.

        Use `failureId` as the stable investigation and deduplication key.
        `resolved=true` means a later equivalent mapping attempt succeeded; it
        does not mean an AS2 document was sent, delivered, or acknowledged.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/mapping-runtime/failures?environment=production&resolved=false&limit=50" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
        - name: mappingId
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
          description: Tenant-scoped mapping id. Omit it to include unmatched pre-transaction failures.
        - name: direction
          in: query
          required: false
          schema:
            type: string
            enum:
              - inbound
              - outbound
          description: Case-insensitive mapping direction.
        - name: resolved
          in: query
          required: false
          schema:
            type: boolean
          description: Filter resolved or unresolved failures; omit it to return both.
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: >
            Opaque cursor returned by the preceding page. Send it back
            unchanged with the same environment and filters.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
          description: Maximum failures to return.
      responses:
        '200':
          description: Mapping runtime failures were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingRuntimeFailuresResponse'
        '400':
          description: A filter, cursor, environment, or limit was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/mapping-runtime/failures/{failureId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationMappingRuntimeFailure
      tags:
        - Mapping Runtime
      summary: Get one mapping runtime failure
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns one safe diagnostic by its opaque `failureId`. The id is still
        checked against the authenticated tenant; knowing another tenant's id
        never grants access.
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: failureId
          in: path
          required: true
          schema:
            type: string
            minLength: 1
          description: Opaque non-null `failureId` returned by the failure list or a failed transaction mapping attempt.
      responses:
        '200':
          description: The mapping failure was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappingRuntimeFailureResponse'
        '400':
          description: The failure id was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The failure was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/events:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationChangeEvents
      tags:
        - Integration Events
      summary: Poll transaction-state changes
      x-required-scope: transactions:read
      description: |
        **Required key scope:** `transactions:read`.

        Returns a small invalidation feed for transaction state detected after an initial snapshot, including late mapping results, MDNs, 997 and 999 evaluations, mapped-output handoff changes, and attention changes. Events do not duplicate transaction detail. Refetch the referenced transaction to read authoritative current state.

        When `cursor` is omitted, ModernEDI returns no historical events, `bootstrap=true`, and a `nextCursor` positioned at the current high-water mark. A race-safe custom viewer should:

        1. Request this endpoint without a cursor and retain `nextCursor`.
        2. Load its current transaction snapshot from `/v1/integration/transactions`.
        3. Poll this endpoint again using the retained cursor.
        4. Refetch every transaction named by events that arrived while the snapshot loaded.

        Thereafter, keep sending each `nextCursor` back unchanged. `observedAt` is when the reconciliation sweep detected the change, not necessarily the partner's event time; event order is detection order. The feed is eventually consistent, so inspect `freshness.complete` and `freshness.status` before treating an empty poll as proof that no changes are pending.

        Change events have a rolling 30-day retention independent of retained transaction documents. Polling successfully refreshes the cursor's age. A client that resumes with an expired cursor receives `410 cursor_expired`; request a new bootstrap cursor and repeat the snapshot sequence.
      x-codeSamples:
        - lang: curl
          label: Bootstrap cursor
          source: |
            curl "https://api.modernedi.com/v1/integration/events?environment=production" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: curl
          label: Poll from cursor
          source: |
            curl "https://api.modernedi.com/v1/integration/events?environment=production&cursor=$MODERNEDI_EVENT_CURSOR&limit=100" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: >
            Opaque, integrity-protected cursor from `nextCursor`. It is bound
            to the authenticated tenant and selected environment and must be
            returned unchanged. A modified cursor, or one used with another
            tenant or environment, returns HTTP 400. Omit it only to establish
            a new high-water-mark bootstrap cursor.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 250
            default: 100
          description: Maximum events to return after the cursor.
      responses:
        '200':
          description: A bootstrap cursor or page of change events was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/IntegrationChangeEventsResponse'
        '400':
          description: The cursor, environment, or limit was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '410':
          description: >
            The cursor is older than retained change history. Error code
            `cursor_expired` includes `retentionSeconds`; obtain a bootstrap
            cursor and reload the transaction snapshot.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listIntegrationTransactions
      tags:
        - Transaction Viewer
      summary: List transactions
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns a pageable transaction history for custom transaction viewers,
        dashboards, and reconciliation workflows. Outbound replies include
        `replyToMessageId` so they can be shown underneath the inbound document
        they answer. Each row includes the stable `needsAttention` operator
        signal, machine-readable `attentionReasons`, and a compact
        `mappingStatus` so unattended integrations can route failures without
        fetching every transaction detail. `functionalAckStatus`,
        `implementationAckStatus`, and `mdnStatus` expose the same compact
        status values used by their exact
        list filters. The root `attentionSummary` is an environment-wide count
        and reconciliation-freshness signal; it is not restricted to the
        requested page or date window. Exact mapping, functional-acknowledgment,
        implementation-acknowledgment, and MDN filters use that same
        asynchronous projection, so check
        `attentionSummary.freshness.complete` before treating an empty filtered
        page as proof that no matching transaction exists.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions?startDate=2026-03-01T00:00:00.000000000Z&endDate=2026-03-31T23:59:59.999999999Z&direction=inbound&partnerId=1&transactionSet=850&mappingStatus=NOT_RECORDED&functionalAckStatus=accepted,accepted_with_errors&mdnStatus=processed&limit=25" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.get(
                "https://api.modernedi.com/v1/integration/transactions",
                params={
                    "startDate": "2026-03-01T00:00:00.000000000Z",
                    "endDate": "2026-03-31T23:59:59.999999999Z",
                    "direction": "inbound",
                    "partnerId": 1,
                    "transactionSet": "850",
                    "mappingStatus": "NOT_RECORDED",
                    "functionalAckStatus": "accepted,accepted_with_errors",
                    "mdnStatus": "processed",
                    "limit": 25,
                },
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            transactions = response.json()["transactions"]
        - lang: JavaScript
          label: Node.js
          source: |
            const url = new URL("https://api.modernedi.com/v1/integration/transactions")
            url.search = new URLSearchParams({
              startDate: "2026-03-01T00:00:00.000000000Z",
              endDate: "2026-03-31T23:59:59.999999999Z",
              direction: "inbound",
              partnerId: "1",
              transactionSet: "850",
              mappingStatus: "NOT_RECORDED",
              functionalAckStatus: "accepted,accepted_with_errors",
              mdnStatus: "processed",
              limit: "25",
            })

            const response = await fetch(url, {
              headers: {
                "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
              },
            })
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { transactions } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/TransactionEnvironment'
        - name: needsAttention
          in: query
          required: false
          schema:
            type: boolean
          description: >
            Filters by the authoritative operator-inbox projection. Use `true`
            to return transactions that currently need attention or `false` to
            return transactions with no active attention reason. Check
            `attentionSummary.freshness.complete` before treating an empty
            filtered page as proof that no transaction needs attention.
        - name: attentionReason
          in: query
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: '#/components/schemas/TransactionAttentionReason'
          description: >
            Repeat this parameter to select more than one attention reason;
            repeated values are ORed. Supplying a reason implies
            `needsAttention=true`, and combining a reason with
            `needsAttention=false` returns `400`. Repeat all explicit filters,
            including every reason, when following an opaque cursor.
        - name: mappingStatus
          in: query
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FilterableTransactionMappingStatus'
          description: >
            Exact consolidated mapping status. Repeat the parameter or use
            comma-separated values to select more than one status; values
            within this parameter are ORed. `UNAVAILABLE` cannot be selected
            because it describes a request-local telemetry read failure rather
            than a durable projected state. This filter is ANDed with
            `functionalAckStatus`, `implementationAckStatus`, `mdnStatus`,
            attention, and transaction metadata filters. Repeat it when
            following an opaque cursor and
            check `attentionSummary.freshness.complete` before drawing a
            conclusion from an empty page.
        - name: functionalAckStatus
          in: query
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FilterableFunctionalAcknowledgmentStatus'
          description: >
            Exact normalized 997 status selected for this transaction. ModernEDI
            uses a uniquely matched AK2/AK5 result when possible and otherwise
            uses the conservative AK9 group result. Repeat the parameter or use
            comma-separated values to select more than one status; values
            within this parameter are ORed. This filter is ANDed with the other
            filter categories. A missing actionable X12 acknowledgment is selected with
            `attentionReason=x12_ack_overdue`, not by this parameter.
            Repeat the filter when following an opaque cursor and check
            `attentionSummary.freshness.complete` before drawing a conclusion
            from an empty page.
        - name: implementationAckStatus
          in: query
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FilterableImplementationAcknowledgmentStatus'
          description: >
            Exact normalized 999 status selected for this transaction.
            ModernEDI uses a uniquely matched AK2/IK5 result when possible and
            otherwise uses the conservative AK9 implementation-group result.
            Repeat the parameter or use comma-separated values to select more
            than one status; values within this parameter are ORed. This
            filter is ANDed with the other filter categories. Transactions
            without an attributable 999 do not match this filter. Repeat it
            when following an opaque cursor and check
            `attentionSummary.freshness.complete` before drawing a conclusion
            from an empty page.
        - name: mdnStatus
          in: query
          required: false
          style: form
          explode: true
          schema:
            type: array
            items:
              $ref: '#/components/schemas/FilterableTransactionMdnStatus'
          description: >
            Exact normalized AS2 receipt-assurance status. Repeat the parameter
            or use comma-separated values to select more than one status;
            values within this parameter are ORed. This filter is ANDed with
            the other filter categories. Transactions for which no MDN status
            applies have `mdnStatus: null` and do not match this filter. Repeat
            the filter when following an opaque cursor and check
            `attentionSummary.freshness.complete` before drawing a conclusion
            from an empty page.
        - name: startDate
          in: query
          required: false
          schema:
            type: string
          description: >
            Optional inclusive window start. Accepts an ISO date or an RFC 3339
            date-time with an explicit offset. Date-only values start at
            00:00:00 UTC. Date-times are normalized to UTC; offset-less
            date-times are rejected. When both dates are omitted, the query
            covers the standard active-workspace transaction-history window of
            the preceding 12 months. Specify dates when your client requires a
            particular interval, and do not infer deletion from an absent row.
          example: '2026-03-01T00:00:00.000000000Z'
        - name: endDate
          in: query
          required: false
          schema:
            type: string
          description: >
            Optional inclusive window end. Accepts the same formats as
            `startDate`; a date-only value includes the complete UTC day. When
            both dates are omitted, the query covers the preceding 12 months.
          example: '2026-03-31'
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: Cursor from the previous response.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 250
            default: 50
          description: Maximum number of transactions to return.
        - name: direction
          in: query
          required: false
          schema:
            type: string
            enum:
              - inbound
              - outbound
          description: Case-insensitive filter for the persisted inbound or outbound transaction direction.
        - name: partnerName
          in: query
          required: false
          schema:
            type: string
          description: Case-insensitive persisted partner name. This filters display metadata; transaction access remains scoped by persisted `partnerId`.
        - name: partnerId
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
          description: >
            Filters transactions by the tenant-scoped partner id returned by
            `GET /v1/partners`. The id remains stable when a partner is renamed.
            Transactions without a stored id are not returned.
          example: 1
        - name: transactionSet
          in: query
          required: false
          schema:
            type: string
          description: X12 transaction set code.
          example: '850'
        - name: businessKey
          in: query
          required: false
          schema:
            type: string
          description: >
            Exact business key value recorded on a transaction. Inbound keys
            come from the incoming map. Outbound keys are recorded only when
            `/send`, `/reply`, `/carbonCopy`, or a `/v1/as2/x12/...` endpoint is
            called with a JSON envelope that includes `businessKey`.
          example: PO-100045
        - name: messageId
          in: query
          required: false
          schema:
            type: string
          description: Exact AS2 message id.
        - name: replyToMessageId
          in: query
          required: false
          schema:
            type: string
          description: Original inbound AS2 message id for outbound replies.
        - name: transactionControlNumber
          in: query
          required: false
          schema:
            type: string
          description: ST02 transaction control number.
        - name: functionalGroupControlNumber
          in: query
          required: false
          schema:
            type: string
          description: GS06 functional group control number.
      responses:
        '200':
          description: Transactions were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionListResponse'
              example:
                success: true
                environment: production
                transactions:
                  - id: msg-850-api/17#0001
                    environment: production
                    needsAttention: true
                    attentionReasons:
                      - mapped_output_not_collected
                      - watchlist
                    mappingStatus:
                      status: NOT_RECORDED
                      latestAttemptAt: null
                      failureCount: 0
                    functionalAckStatus: accepted
                    implementationAckStatus: null
                    mdnStatus: processed
                    onWatchlist: true
                    x12AcknowledgmentExpectedBy: null
                    technicalAckRequested: false
                    technicalAckStatus: not_requested
                    technicalAckExpectedBy: null
                    technicalAckOutcome: null
                    messageId: msg-850-api
                    transactionKey: 17#0001
                    replyToMessageId: null
                    replyToTransactionKey: null
                    direction: inbound
                    partnerName: Customer One
                    partnerId: 1
                    partnerConfigurationSha256: null
                    timestamp: '2026-03-25T18:15:00.000000000Z'
                    transactionSet:
                      code: '850'
                      description: Purchase Order
                    controlNumbers:
                      transaction: '0001'
                      functionalGroup: '17'
                    edi:
                      x12Version: '4010'
                      functionalIdentifierCode: PO
                      transactionGroupType: '850'
                      segmentTerminator: '~'
                    businessKey:
                      name: purchaseOrderNumber
                      value: PO-100045
                    functionalAckOutcome:
                      status: accepted
                      acknowledgmentCode: A
                      summary: Functional group accepted; 1 of 1 received transaction set was accepted.
                    functionalAckTransactionOutcome:
                      functionalIdentifierCode: PO
                      functionalGroupControlNumber: '17'
                      transactionSetIdentifierCode: '850'
                      transactionSetControlNumber: '0001'
                      implementationConventionReference: null
                      status: accepted
                      acknowledgmentCode: A
                      errorCodes: []
                    functionalAckGroupOutcome:
                      functionalIdentifierCode: PO
                      functionalGroupControlNumber: '17'
                      functionalGroupVersion: null
                      status: accepted
                      acknowledgmentCode: A
                      includedTransactionSets: 1
                      receivedTransactionSets: 1
                      acceptedTransactionSets: 1
                      errorCodes: []
                    functionalAckEvaluationScope: transaction_set
                    implementationAckOutcome: null
                    implementationAckTransactionOutcome: null
                    implementationAckEvaluationScope: null
                nextCursor: null
                hasMore: false
                window:
                  startDate: '2026-03-01T00:00:00.000000000Z'
                  endDate: '2026-03-31T23:59:59.999999999Z'
                  timeZone: UTC
                attentionSummary:
                  needsAttentionCount: 1
                  reasonCounts:
                    mappingFailure: 0
                    functionalAckIssue: 0
                    implementationAckIssue: 0
                    x12AckOverdue: 0
                    technicalAckIssue: 0
                    technicalAckOverdue: 0
                    as2MdnAttention: 0
                    mappedOutputNotCollected: 1
                    mappedOutputAckOverdue: 0
                    watchlist: 1
                  freshness:
                    status: current
                    complete: true
                    lastCompletedAt: '2026-03-31T23:59:45.000000000Z'
                    reconciliationStartedAt: null
                    message: null
        '400':
          description: Invalid cursor, date window, or limit.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationTransaction
      tags:
        - Transaction Viewer
      summary: Get transaction detail
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns a metadata-first transaction aggregate: the summary, mapped
        output provenance and managed handoff state, normalized acknowledgment
        status, a document index, timeline events, compact linked-reply
        summaries, and the complete mapping-attempt history used to explain
        `needsAttention`. Document bodies are returned only by the individual
        document endpoint.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = "msg-850-api"
            transaction_key = "17#0001"
            message_path = quote(message_id, safe="")
            transaction_path = quote(transaction_key, safe="")
            response = requests.get(
                f"https://api.modernedi.com/v1/integration/transactions/{message_path}/{transaction_path}",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            transaction = response.json()["transaction"]
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}`,
              {
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { transaction } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Transaction detail was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDetailResponse'
        '400':
          description: Missing or invalid lookup values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/watch:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    put:
      operationId: watchIntegrationTransaction
      tags:
        - Transaction Viewer
      summary: Watch a transaction
      x-required-scope: transactions:write
      description: >
        **Required key scope:** `transactions:write`.

        Idempotently adds a tenant-visible transaction to the selected
        environment's operator watchlist. Public API watch entries do not
        expire and remain active until the DELETE operation removes them.
        The response reports the resulting state, so retrying the same request
        is safe. Workspace-wide attention counts and status-filter projections
        are asynchronous; use their `freshness` object when reconciling an
        immediately following list response.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X PUT \
              "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/watch?environment=production" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = quote("msg-850-api", safe="")
            transaction_key = quote("17#0001", safe="")
            response = requests.put(
                f"https://api.modernedi.com/v1/integration/transactions/{message_id}/{transaction_key}/watch",
                params={"environment": "production"},
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            assert response.json()["onWatchlist"] is True
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}/watch?environment=production`,
              {
                method: "PUT",
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const watch = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: The transaction is on the operator watchlist.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionWatchResponse'
              example:
                success: true
                environment: production
                messageId: msg-850-api
                transactionKey: 17#0001
                onWatchlist: true
        '400':
          description: Missing or invalid lookup values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    delete:
      operationId: unwatchIntegrationTransaction
      tags:
        - Transaction Viewer
      summary: Stop watching a transaction
      x-required-scope: transactions:write
      description: >
        **Required key scope:** `transactions:write`.

        Idempotently removes a tenant-visible transaction from the selected
        environment's operator watchlist. The response reports
        `onWatchlist: false` even when the transaction was already unwatched,
        so retrying after a network failure is safe. Workspace-wide attention
        counts and status-filter projections are asynchronous; use their
        `freshness` object when reconciling an immediately following list
        response.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X DELETE \
              "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/watch?environment=production" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = quote("msg-850-api", safe="")
            transaction_key = quote("17#0001", safe="")
            response = requests.delete(
                f"https://api.modernedi.com/v1/integration/transactions/{message_id}/{transaction_key}/watch",
                params={"environment": "production"},
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            assert response.json()["onWatchlist"] is False
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}/watch?environment=production`,
              {
                method: "DELETE",
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const watch = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: The transaction is not on the operator watchlist.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionWatchResponse'
              example:
                success: true
                environment: production
                messageId: msg-850-api
                transactionKey: 17#0001
                onWatchlist: false
        '400':
          description: Missing or invalid lookup values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/documents:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationTransactionDocuments
      tags:
        - Transaction Viewer
      summary: Get transaction documents
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns a lightweight metadata index for raw X12, mapped inbound
        outputs, MDN reports, acknowledgements, and HTTP responses recorded for
        the transaction. It never returns document bodies. Fetch one selected
        body from the individual document endpoint when an operator opens it.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/documents" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = "msg-850-api"
            transaction_key = "17#0001"
            message_path = quote(message_id, safe="")
            transaction_path = quote(transaction_key, safe="")
            response = requests.get(
                f"https://api.modernedi.com/v1/integration/transactions/{message_path}/{transaction_path}/documents",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            documents = response.json()["documents"]
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}/documents`,
              {
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { documents } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Transaction documents were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDocumentsResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/documents/{documentId}:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationTransactionDocument
      tags:
        - Transaction Viewer
      summary: Get one transaction document
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns one complete retained artifact selected by the stable
        transaction-local `documentId` from the document list. A document id is
        not a mapped-output queue id and cannot be used to acknowledge delivery.
        The returned body is untrusted external content and must be rendered
        as untrusted external content: escape text, sanitize any supported
        markup, and sandbox richer previews instead of inserting it directly
        into a page.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/documents/raw-x12" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
        - name: documentId
          in: path
          required: true
          schema:
            type: string
            minLength: 1
          description: Stable `id` returned by this transaction's document list.
          example: raw-x12
      responses:
        '200':
          description: The selected transaction document was returned with its complete content.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionDocumentResponse'
        '400':
          description: A path or environment value was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The transaction or selected document was not found. A missing document uses `document_not_found`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/x12/validation:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: validateIntegrationTransactionX12
      tags:
        - Transaction Viewer
      summary: Validate the X12 retained for a transaction
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Parses and validates the X12 content ModernEDI retained for this
        transaction and returns the same structured validation model as
        `POST /v1/x12/validate`. Invalid X12 is a successful analysis response
        with `validation.valid=false`, not an HTTP error. The retained X12 can
        be a complete interchange containing more than one transaction set;
        use the returned group and transaction indexes when displaying errors.
        This read-only endpoint lets transaction-viewer keys inspect stored
        content without granting message-send or transaction-replay authority.
        It does not rerun mappings, create mapped outputs, replay the transaction,
        or resend a document.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/x12/validation" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Stored X12 was analyzed; inspect `validation.valid` for the result.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionX12ValidationResponse'
        '400':
          description: A path or environment value was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: >
            The transaction was not visible, or it exists without retained X12.
            The latter case uses `x12_not_found`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/events:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationTransactionEvents
      tags:
        - Transaction Viewer
      summary: Get transaction events
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns a normalized timeline for the transaction, including receipt or
        send events, mapping events, MDNs, acknowledgements, mapped-output
        availability/delivery/redelivery/attention/acknowledgment, and linked
        replies. These entries are derived from current persisted evidence;
        an output acknowledgment means acknowledged by your integration, not
        accepted by a downstream business system.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/events" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = "msg-850-api"
            transaction_key = "17#0001"
            message_path = quote(message_id, safe="")
            transaction_path = quote(transaction_key, safe="")
            response = requests.get(
                f"https://api.modernedi.com/v1/integration/transactions/{message_path}/{transaction_path}/events",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            events = response.json()["events"]
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}/events`,
              {
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { events } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Transaction events were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionEventsResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/related:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getRelatedIntegrationTransactions
      tags:
        - Transaction Viewer
      summary: Get linked reply transactions
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns compact summaries of outbound reply transactions linked to an
        inbound transaction. Follow a summary's `messageId` and
        `transactionKey` to fetch its metadata-first detail or document index.
        Replies are included only when `replyToTransactionKey` identifies that
        exact transaction inside `replyToMessageId`. Use the returned linkage
        fields rather than inferring relationships from document type.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/related" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY"
        - lang: Python
          label: Python
          source: |
            import os
            from urllib.parse import quote

            import requests

            message_id = "msg-850-api"
            transaction_key = "17#0001"
            message_path = quote(message_id, safe="")
            transaction_path = quote(transaction_key, safe="")
            response = requests.get(
                f"https://api.modernedi.com/v1/integration/transactions/{message_path}/{transaction_path}/related",
                headers={"x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"]},
                timeout=30,
            )
            response.raise_for_status()
            related_transactions = response.json()["relatedTransactions"]
        - lang: JavaScript
          label: Node.js
          source: |
            const messageId = encodeURIComponent("msg-850-api")
            const transactionKey = encodeURIComponent("17#0001")
            const response = await fetch(
              `https://api.modernedi.com/v1/integration/transactions/${messageId}/${transactionKey}/related`,
              {
                headers: {
                  "x-api-key": process.env.MODERNEDI_INTEGRATION_API_KEY,
                },
              },
            )
            if (!response.ok) {
              throw new Error(await response.text())
            }
            const { relatedTransactions } = await response.json()
      servers:
        - url: https://api.modernedi.com
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/MessageId'
        - $ref: '#/components/parameters/TransactionKey'
        - $ref: '#/components/parameters/TransactionEnvironment'
      responses:
        '200':
          description: Related transactions were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RelatedTransactionsResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: Transaction was not found or is not visible to this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PlatformErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/integration/transactions/{messageId}/{transactionKey}/replays:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
      - $ref: '#/components/parameters/MessageId'
      - $ref: '#/components/parameters/TransactionKey'
    post:
      operationId: replayIntegrationTransaction
      tags:
        - Transaction Viewer
      summary: Replay an inbound transaction without redelivery
      x-required-scope: transactions:replay
      description: |
        **Required key scope:** `transactions:replay`.

        Re-runs mapping for one tenant-visible inbound transaction with the currently published maps and returns the regenerated mapped outputs directly. Historical map revision replay is not part of the public API.

        The only supported delivery is `response_only`. ModernEDI does not put regenerated outputs on the mapped-output queue, invoke mapped-output webhooks, or generate outbound acknowledgements. This endpoint is therefore suitable for inspection and controlled recovery without repeating downstream delivery side effects.

        Replay re-applies the currently active inbound protection policy. The stored inbound row must contain successful `signatureVerified` and `encryptionDecrypted` evidence for every protection required in the selected environment. A missing or `false` evidence value fails closed with an `insufficient-message-security:` replay error; consequently, older transactions without that evidence are not replayable while the corresponding protection remains required.

        `Idempotency-Key` is required. Repeating the same key and request returns the stored successful replay with `Idempotency-Replayed: true` and does not invoke mapping again. Reusing the key for different replay input returns `409 idempotency_key_conflict`; retry while the same replay is still processing returns `409 idempotency_key_in_progress` with `retryable: true`.

        The replay body is strict JSON: unknown fields are rejected, and `environment`, `mode`, `delivery`, and `reason` must be strings when present (`reason` may also be `null`). Type mismatches return `400 invalid_request` with the offending JSON pointer.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST \
              "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/replays" \
              -H "Content-Type: application/json" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Idempotency-Key: replay-msg-850-api-17-0001-v1" \
              --data @examples/transaction-replay-request.json
        - lang: Python
          label: Python
          source: |
            import os
            import requests

            response = requests.post(
                "https://api.modernedi.com/v1/integration/transactions/msg-850-api/17%230001/replays",
                headers={
                    "x-api-key": os.environ["MODERNEDI_INTEGRATION_API_KEY"],
                    "Idempotency-Key": "replay-msg-850-api-17-0001-v1",
                },
                json={
                    "environment": "production",
                    "mode": "current_maps",
                    "delivery": "response_only",
                    "reason": "Verify corrected purchase-order mapping",
                },
                timeout=60,
            )
            response.raise_for_status()
            regenerated_outputs = response.json()["regeneratedOutputs"]
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - $ref: '#/components/parameters/ReplayIdempotencyKey'
      requestBody:
        required: true
        description: Replay request bodies may be at most 16 KiB (16,384 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TransactionReplayRequest'
      responses:
        '200':
          description: Mapping replay completed or a stored successful result was returned.
          headers:
            Idempotency-Replayed:
              $ref: '#/components/headers/ReplayIdempotencyReplayed'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TransactionReplayResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The selected inbound transaction was not found in this tenant and environment.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: The idempotency key conflicts with another request or the same replay is still processing.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '422':
          description: The selected transaction is outbound or otherwise cannot be replayed with the selected map mode.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Mapping replay failed. Inspect `error.retryable` before retrying the same idempotency key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /v1/partners/{partnerId}/mapped-output-webhook:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getMappedOutputWebhookStatus
      tags:
        - Mapped Output Queue
      summary: Get mapped-output webhook status
      x-required-scope: configuration:read
      description: >
        **Required key scope:** `configuration:read`.

        Returns the current mapped-output webhook configuration and recent
        delivery health for a partner. This read-only endpoint never returns the
        signing secret; it reports whether a secret is configured and only its
        last four characters so operators can identify the active credential.
        Save the response `ETag` header or `webhook.etag` before updating.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: partnerId
          in: path
          required: true
          description: Tenant-scoped partner id returned by `GET /v1/partners`.
          schema:
            type: integer
      responses:
        '200':
          description: Webhook status was returned.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputWebhookStatusResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The partner was not found in this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
    put:
      operationId: updateMappedOutputWebhook
      tags:
        - Mapped Output Queue
      summary: Configure mapped-output webhook delivery
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Enables, disables, or rotates a partner's HTTPS mapped-output webhook. Send the current configuration ETag in `If-Match`. `endpointUrl` is required when enabling delivery and must be an absolute HTTPS URL without user information or a fragment and use a publicly routable host. Localhost, private, link-local, multicast, carrier-grade NAT, documentation, benchmark, and other reserved address targets are rejected. ModernEDI resolves the hostname again before every webhook delivery and sends only when all resolved addresses are publicly routable. Enabling a webhook without an existing signing secret creates one; `rotateSigningSecret: true` replaces it.

        The request body is strict JSON: unknown fields are rejected; `enabled` and `rotateSigningSecret` must be booleans; and `endpointUrl` must be a string or `null`. Type mismatches return `400 invalid_request` with the offending JSON pointer.

        A newly created or rotated `plainTextSigningSecret` appears only in this successful response. Save it immediately. Later reads expose only `signingSecretConfigured` and `signingSecretLastFour`.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X PUT "https://api.modernedi.com/v1/partners/1/mapped-output-webhook" \
              -H "Content-Type: application/json" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H 'If-Match: "<etag-from-the-latest-webhook-response>"' \
              --data @examples/mapped-output-webhook-update-request.json
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: partnerId
          in: path
          required: true
          description: Tenant-scoped partner id returned by `GET /v1/partners`.
          schema:
            type: integer
        - $ref: '#/components/parameters/IfMatch'
      requestBody:
        required: true
        description: Partner webhook configuration bodies may be at most 1 MiB (1,048,576 bytes).
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MappedOutputWebhookUpdateRequest'
      responses:
        '200':
          description: Webhook configuration was saved. A new signing secret is included only when created or rotated.
          headers:
            ETag:
              $ref: '#/components/headers/ConfigurationEtag'
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputWebhookUpdateResponse'
        '400':
          $ref: '#/components/responses/InvalidRequestError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The partner was not found in this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '412':
          $ref: '#/components/responses/EtagMismatchError'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
        '428':
          $ref: '#/components/responses/PreconditionRequiredError'
  /v1/partners/{partnerId}/mapped-output-webhook/test:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: testMappedOutputWebhook
      tags:
        - Mapped Output Queue
      summary: Send a synthetic mapped-output webhook test
      x-required-scope: configuration:write
      description: |
        **Required key scope:** `configuration:write`.

        Sends one signed `mapped_output.test` event to the partner's saved HTTPS webhook endpoint using the same DNS validation, pinned public-address transport, timeout, and HMAC signing path as normal mapped-output delivery. The test event is explicitly marked `test: true`, contains no mapped-output `message`, queue id, receipt handle, or business document, and never creates, leases, acknowledges, retries, or changes a real mapped-output queue item. It also does not replace the webhook's recorded production delivery health.

        The webhook may be disabled while this connectivity test runs, but an endpoint and signing secret must already be saved. The API returns `200` after every completed attempt; inspect `delivered`, `statusCode`, and `error` for the destination outcome. `requestId` matches the `X-Request-Id` response header and is also included in the signed synthetic event for correlation.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/partners/1/mapped-output-webhook/test" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "X-Request-Id: webhook-test-2026-08-01"
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: partnerId
          in: path
          required: true
          description: Tenant-scoped partner id returned by `GET /v1/partners`.
          schema:
            type: integer
      responses:
        '200':
          description: The synthetic delivery attempt completed; inspect `delivered` for the destination outcome.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MappedOutputWebhookTestResponse'
              example:
                success: true
                synthetic: true
                event: mapped_output.test
                deliveryId: test_94b2796c-1d6a-4f87-ae63-ae4f3b25f67c
                requestId: webhook-test-2026-08-01
                attemptedAt: '2026-08-01T18:30:00.000000000Z'
                attempted: true
                delivered: true
                statusCode: 204
                error: null
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '404':
          description: The partner was not found in this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: No HTTPS endpoint or signing secret is saved for this partner.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          $ref: '#/components/responses/WebhookTestRateLimitError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/usage:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: getIntegrationUsage
      tags:
        - Account
      summary: Get plan usage and enforcement status
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Returns the tenant's current AS2 message usage, plan thresholds, daily
        history, and operational signals. Use `rejectionActive`, `status`, and
        the threshold fields to warn operators before additional messages are
        rejected. The quota date and `timeZone` are reported in UTC and usage
        includes both inbound and outbound AS2 messages. Hour bucket labels use
        `HH:00` values such as `18:00`.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: days
          in: query
          required: false
          description: Number of UTC calendar days to include.
          schema:
            type: integer
            minimum: 1
            maximum: 90
            default: 14
      responses:
        '200':
          description: Usage was returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UsageResponse'
        '400':
          description: The requested day count was outside the supported range.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/x12/validate:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    post:
      operationId: validateX12
      tags:
        - X12 Tools
      summary: Parse and validate an X12 interchange
      x-required-scope: transactions:read
      description: >
        **Required key scope:** `transactions:read`.

        Parses an X12 interchange and returns structural, group, transaction,
        segment, and element validation results without sending anything. Send
        X12 directly as `application/edi-x12` or `text/plain`, or wrap it in an
        `x12` field when JSON is more convenient. A syntactically invalid X12
        document still returns a 200 validation result; malformed request shapes
        return a standard 400 error. Request bodies are limited to 3 MiB. Validation
        is available to read-only viewers and does not grant authority to send X12.
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl -X POST "https://api.modernedi.com/v1/x12/validate" \
              -H "x-api-key: $MODERNEDI_INTEGRATION_API_KEY" \
              -H "Content-Type: application/edi-x12" \
              --data-binary @purchase-order.edi
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      requestBody:
        required: true
        description: Complete X12 interchange to validate, supplied directly as `application/edi-x12` or `text/plain`, or as the `x12` property of a JSON object.
        content:
          application/edi-x12:
            schema:
              type: string
          text/plain:
            schema:
              type: string
          application/json:
            schema:
              $ref: '#/components/schemas/X12ValidationRequest'
      responses:
        '200':
          description: X12 validation completed.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/X12ValidationResponse'
        '400':
          description: The request body was empty or did not use a supported shape.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '413':
          $ref: '#/components/responses/PayloadTooLargeError'
  /v1/x12/versions:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listX12Versions
      tags:
        - X12 Tools
      summary: List available X12 versions
      x-required-scope: configuration:read
      description: |
        **Required key scope:** `configuration:read`.

        Returns X12 versions for which the tenant has reference syntax trees.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      responses:
        '200':
          description: X12 versions were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/X12VersionsResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
  /v1/x12/versions/{x12Version}/transaction-sets:
    parameters:
      - $ref: '#/components/parameters/CallerRequestId'
    get:
      operationId: listX12TransactionSets
      tags:
        - X12 Tools
      summary: List transaction sets for an X12 version
      x-required-scope: configuration:read
      description: >
        **Required key scope:** `configuration:read`.

        Returns the transaction-set identifiers and descriptions available for
        the normalized X12 version. Both `4010` and `004010` style version
        values are accepted.
      security:
        - IntegrationApiKeyHeader: []
        - IntegrationApiKeyBearer: []
      parameters:
        - name: x12Version
          in: path
          required: true
          schema:
            type: string
          description: X12 version to normalize and look up. Both `4010` and `004010` forms are accepted.
          example: '004010'
      responses:
        '200':
          description: Transaction sets were returned.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/X12TransactionSetsResponse'
        '400':
          description: The X12 version was invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '402':
          $ref: '#/components/responses/BillingInactiveError'
        '403':
          $ref: '#/components/responses/InsufficientScopeError'
        '414':
          $ref: '#/components/responses/QueryTooLargeError'
components:
  responses:
    UnauthorizedError:
      description: Missing or invalid integration API key.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: unauthorized
              message: Missing or invalid integration API key.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details: {}
    InsufficientScopeError:
      description: The API key is valid but does not grant the operation's required scope.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: insufficient_scope
              message: The Integration API key does not grant the required scope.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                requiredScopes:
                  - configuration:write
                grantedScopes:
                  - configuration:read
    InvalidRequestError:
      description: The request body, query parameters, or configuration values were invalid. Configuration bodies reject unknown fields and wrong JSON scalar types rather than coercing or silently ignoring them.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: invalid_request
              message: Request validation failed.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details: {}
    ConfigurationNotFoundError:
      description: The tenant-scoped configuration object was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ConfigurationInUseError:
      description: The configuration object is still referenced and cannot be deleted.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: configuration_in_use
              message: Configuration is still referenced by another object.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details: {}
    ConfigurationConflictError:
      description: A tenant-scoped uniqueness rule was violated while creating or updating configuration.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: configuration_conflict
              message: Another AS2 connection already uses the production AS2 identifier "RETAILER_PROD".
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details: {}
    As2ConnectionPatchConflictError:
      description: The update conflicts with identifier uniqueness or would remove a test AS2 profile still used by attached partner X12 test identities. The mutation is not committed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            identifierConflict:
              value:
                success: false
                error:
                  code: configuration_conflict
                  message: Another AS2 connection already uses the test AS2 identifier "RETAILER_TEST".
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details: {}
            testProfileInUse:
              value:
                success: false
                error:
                  code: configuration_in_use
                  message: The test AS2 profile cannot be removed while 1 attached partner still has test X12 identifiers. Remove those test X12 identities first, then retry.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    connectionId: 12
                    attachedPartnersWithTestIdentity: 1
    PlanEntitlementRequiredError:
      description: The requested AS2 endpoint transport is not included in the tenant's current plan. The configuration mutation is not committed.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: plan_entitlement_required
              message: Plain HTTP AS2 endpoint URLs are not available on plan "endpoint". Use HTTPS, or upgrade to Endpoint Plus or a higher plan.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                planCode: endpoint
                requiredCapability: plain_http_as2_endpoints
                minimumPlanCode: endpoint_plus
                fields:
                  - /environments/production/endpointUrl
    PartnerX12IdentityValidationError:
      description: A connected partner's final merged X12 identity configuration is incomplete or has unsafe field lengths. The mutation is not committed. Detached partner drafts may remain incomplete until an AS2 connection is attached.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: partner_x12_identity_invalid
              message: Connected partner production X12 identities must be complete. When a test identity is provided, it must use a 2-character ISA qualifier and 1-15 character ISA and GS identifiers.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                violations:
                  - field: /x12/production/isaQualifier
                    minimumLength: 2
                    maximumLength: 2
                    actualLength: 1
                  - field: /x12/test/isaId
                    minimumLength: 1
                    maximumLength: 15
                    actualLength: 0
    MappingIdempotencyConflictError:
      description: The tenant-scoped idempotency key belongs to a different mapping-create request, or its original mapping was later deleted. The request does not create another mapping.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            changedRequest:
              summary: The key was reused with a different JSON request.
              value:
                success: false
                error:
                  code: idempotency_key_conflict
                  message: Idempotency-Key was already used for a different mapping creation request.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    mappingId: 31
            deletedResult:
              summary: The mapping originally created with the key was deleted.
              value:
                success: false
                error:
                  code: idempotency_result_unavailable
                  message: The mapping created with this Idempotency-Key no longer exists. Use a new key to create a new mapping.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    mappingId: 31
    MappingValidationError:
      description: The executable mapping configuration did not parse, compile, or pass semantic validation. No mapping revision is published when this response is returned.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: mapping_validation_failed
              message: transform.source is not a valid X12 Mapper program.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                field: transform.source
                diagnostics:
                  - severity: ERROR
                    code: E1001
                    message: The element reference is not valid for the selected X12 transaction set.
                    line: 3
                    column: 12
    EtagMismatchError:
      description: The supplied `If-Match` value is stale. Fetch the resource again and reconcile before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: etag_mismatch
              message: Configuration changed after it was read. Fetch it again and retry with the new ETag.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                currentEtag: '"new-resource-sha256"'
    PreconditionRequiredError:
      description: >
        `If-Match` is required for configuration updates and deletes.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: precondition_required
              message: If-Match is required for configuration updates and deletes.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                currentEtag: '"resource-sha256"'
    BillingInactiveError:
      description: Tenant billing is not active for protected integration features.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: billing_inactive
              message: Tenant billing status "canceled" does not allow integration API access.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details: {}
    PayloadTooLargeError:
      description: Request body exceeded the endpoint-specific byte limit. Inspect `error.details.maximumBytes`; documented limits include 3 MiB for outbound/validation, 1 MiB for configuration writes, and 16 KiB for replay and mapped-output acknowledgments.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            configurationLimit:
              summary: Configuration request exceeded 1 MiB
              value:
                success: false
                error:
                  code: payload_too_large
                  message: Mapping configuration request body must be 1 MB or smaller.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    maximumBytes: 1048576
            replayLimit:
              summary: Replay request exceeded 16 KiB
              value:
                success: false
                error:
                  code: payload_too_large
                  message: Transaction replay request body must be 16 KB or smaller.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    maximumBytes: 16384
            outboundLimit:
              summary: Outbound or validation request exceeded 3 MiB
              value:
                success: false
                error:
                  code: payload_too_large
                  message: Outbound AS2 request body must be 3 MB or smaller.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    maximumBytes: 3145728
    ConfigurationMutationTooLargeError:
      description: |
        The request exceeded the 1 MiB HTTP body ceiling, or the resulting aggregate tenant runtime configuration would exceed 12 MiB (12,582,912 bytes).

        `payload_too_large` means the submitted request body itself is too large. `runtime_configuration_too_large` means the proposed partner, AS2 connection, or mapping create/update would make the complete runtime configuration document too large; the database mutation is rejected and the existing configuration remains active. Delete remains available above the aggregate cap so configuration can be reduced.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            requestBodyLimit:
              summary: Configuration request exceeded 1 MiB
              value:
                success: false
                error:
                  code: payload_too_large
                  message: Mapping configuration request body must be 1 MB or smaller.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    maximumBytes: 1048576
            aggregateRuntimeLimit:
              summary: Resulting runtime configuration exceeded 12 MiB
              value:
                success: false
                error:
                  code: runtime_configuration_too_large
                  message: The resulting tenant runtime configuration would be 12584021 bytes; the maximum is 12582912 bytes.
                  retryable: false
                  requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
                  details:
                    actualBytes: 12584021
                    maximumBytes: 12582912
    QueryTooLargeError:
      description: Query string exceeded 4 KiB.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            success: false
            error:
              code: query_too_large
              message: Query string exceeded the maximum allowed size.
              retryable: false
              requestId: req_01HZ9TRK7B0YQW2V4RMNC9B60A
              details:
                maximumBytes: 4096
    TenantAs2RateLimitError:
      description: The tenant AS2 runtime asked the client to retry later.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        Idempotency-Replayed:
          $ref: '#/components/headers/IdempotencyReplayed'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    WebhookTestRateLimitError:
      description: A connectivity test already started for this partner within the 30-second cooldown.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  headers:
    XRequestId:
      description: Correlation id for this request. Log it when contacting ModernEDI support.
      schema:
        type: string
      example: req_01HZ9TRK7B0YQW2V4RMNC9B60A
    RetryAfter:
      description: Number of seconds the client should wait before retrying this operation.
      schema:
        type: string
      example: '60'
    IdempotencyReplayed:
      description: >
        The value is `true` when the tenant AS2 runtime returned a stored idempotent result.
      schema:
        type: string
        enum:
          - 'true'
    ReplayIdempotencyReplayed:
      description: >
        `true` when this response was loaded from a previous successful replay with the same key and request.
      schema:
        type: string
        enum:
          - 'true'
          - 'false'
    MappingIdempotencyReplayed:
      description: >
        `true` when this response returned the mapping previously created with
        the same tenant-scoped idempotency key and JSON request; `false` when
        this request created the mapping.
      schema:
        type: string
        enum:
          - 'true'
          - 'false'
    ConfigurationEtag:
      description: Quoted SHA-256 ETag for optimistic configuration concurrency. Send this exact value in `If-Match`.
      schema:
        type: string
      example: '"44e5a1b1242e11a8b29380d9de44c08b46433673f30e23ac876a345fc2c5f1b3"'
  requestBodies:
    OutboundMappedSourceBody:
      required: true
      description: >
        Source document for an outgoing map. Use the vendor media type for an
        explicit ModernEDI envelope containing `input`, `contentType`, optional
        `params`, and optional `businessKey`. `application/json` bodies are
        always ordinary JSON map input, including objects with top-level
        `input`, `params`, `businessKey`, or `contentType` fields.
      content:
        application/vnd.modernedi.outbound+json:
          schema:
            $ref: '#/components/schemas/OutboundTransformEnvelope'
        application/json:
          schema:
            anyOf:
              - type: object
                additionalProperties: true
              - type: array
                items: {}
              - type: string
                nullable: true
              - type: number
              - type: boolean
        application/xml:
          schema:
            type: string
        text/plain:
          schema:
            type: string
    GeneratedX12Body:
      required: true
      description: >
        A complete X12 interchange that ModernEDI should validate and send
        without applying an outgoing map. Use the JSON form only when you also
        want to attach a business key to the transaction record.
      content:
        application/edi-x12:
          schema:
            type: string
        text/plain:
          schema:
            type: string
        application/json:
          schema:
            $ref: '#/components/schemas/GeneratedX12Request'
  parameters:
    CallerRequestId:
      name: X-Request-Id
      in: header
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 128
        pattern: '^[A-Za-z0-9][A-Za-z0-9._:@/+=-]{0,127}$'
      description: >
        Optional caller correlation id. ModernEDI preserves a value that matches
        this safe format and returns it in the response `X-Request-Id` header;
        otherwise ModernEDI generates a replacement. Always log the response
        value because it is the authoritative id for support correlation.
    TestMode:
      name: test
      in: query
      required: false
      schema:
        type: boolean
        default: false
      description: >
        When `true`, use the test identifiers and test endpoint configured for
        the partner connection. On `/v1/as2/reply` and
        `/v1/as2/x12/reply`, this also selects test transaction history when
        `originalMessageId` is used to infer partner metadata and link the reply.
    TransactionEnvironment:
      name: environment
      in: query
      required: false
      schema:
        type: string
        enum:
          - production
          - test
        default: production
      description: >
        Selects the isolated production or test transaction history and queue.
        Cursors and mapped-output receipt handles are bound to the environment
        that created them and cannot be reused across environments.
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      schema:
        type: string
        minLength: 1
        maxLength: 128
      description: >
        Optional caller-generated key for safely retrying outbound requests.
        Reusing the same key with the same request replays a stored terminal
        result; reusing it with a different request returns an idempotency
        conflict. Retryable downstream `408`, `425`, `429`, and `5xx` results
        are not terminal and a retry can execute the AS2 send again. A replayed
        stored result includes `Idempotency-Replayed: true`. If the tenant AS2
        runtime asks the client to wait, ModernEDI preserves its `Retry-After`
        response header. For the mapped endpoints, mapping selection,
        transformation, and generated-X12 validation happen before the tenant
        AS2 runtime reserves this key. If one of those steps fails and you
        correct the partner or map
        configuration, retry the identical operation and request with the same
        key even when that configuration error reported `retryable: false`.
        Do not change the operation, selectors, source input, content type,
        params, or business key while reusing it. When delivery may have
        succeeded but the terminal
        response was lost, reconcile transaction history and business keys
        before retrying because idempotency cannot rule out a duplicate send.
    ReplayIdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 200
      description: |
        Required caller-generated replay key. Reuse the same key only for the same message id, transaction key, environment, mode, delivery, and reason. A successful result is stored for safe retry.
    MappingCreateIdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      schema:
        type: string
        minLength: 1
        maxLength: 200
      description: |
        Required caller-generated key for safely retrying mapping creation. The key is scoped to the tenant, not to one API credential. Reuse it only with the same JSON request. Store one stable key with the intended configuration deployment operation rather than generating a new key for each retry.
    IfMatch:
      name: If-Match
      in: header
      required: true
      schema:
        type: string
      description: Exact quoted ETag returned by the latest GET, POST, or PATCH response for this resource.
    OutboundPartnerId:
      name: partnerId
      in: query
      required: true
      schema:
        type: integer
      description: Stable partner id returned by `GET /v1/partners`. For `/carbonCopy`, this id selects the original/source partner, not the `copyToPartnerId` recipient.
      example: 1
    ReplyOutboundPartnerId:
      name: partnerId
      in: query
      required: false
      schema:
        type: integer
      description: Stable partner id returned by `GET /v1/partners`. Optional for `/reply` when `originalMessageId` identifies an inbound transaction with an unambiguous persisted partner id. Transactions without a persisted id do not supply inferred partner metadata. An explicit id overrides inferred partner metadata.
      example: 1
    OutboundX12Version:
      name: x12Version
      in: query
      required: true
      schema:
        type: string
      description: X12 version tied to the outgoing map.
      example: '4010'
    ReplyOutboundX12Version:
      name: x12Version
      in: query
      required: false
      schema:
        type: string
      description: X12 version tied to the outgoing reply map. Optional for `/reply` when `originalMessageId` identifies an inbound transaction whose X12 version can be inferred unambiguously. Send this explicitly when the reply must use a different X12 version than the original inbound document.
      example: '4010'
    OutboundFunctionalGroupType:
      name: functionalGroupType
      in: query
      required: true
      schema:
        type: string
      description: X12 functional group code tied to the outgoing map.
      example: IN
    ReplyOutboundFunctionalGroupType:
      name: functionalGroupType
      in: query
      required: false
      schema:
        type: string
      description: X12 functional group code tied to the outgoing reply map. Optional for `/reply` when `originalMessageId`, the resolved partner and X12 version, and request `Content-Type` match exactly one outgoing reply map. Send this explicitly when multiple reply maps could match.
      example: IN
    OutboundTransactionGroupType:
      name: transactionGroupType
      in: query
      required: true
      schema:
        type: integer
      description: X12 transaction set identifier code tied to the outgoing map.
      example: 810
    ReplyOutboundTransactionGroupType:
      name: transactionGroupType
      in: query
      required: false
      schema:
        type: integer
      description: X12 transaction set identifier code tied to the outgoing reply map. Optional for `/reply` when `originalMessageId`, the resolved partner and X12 version, and request `Content-Type` match exactly one outgoing reply map. Send this explicitly when multiple reply maps could match.
      example: 810
    OriginalMessageId:
      name: originalMessageId
      in: query
      required: true
      schema:
        type: string
      description: Original inbound AS2 message id used to link replies or carbon copies to an inbound flow.
      example: msg-850-api
    OriginalTransactionKey:
      name: originalTransactionKey
      in: query
      required: false
      schema:
        type: string
        minLength: 1
      description: >
        Exact transaction key, normally `GS06#ST02`, inside
        `originalMessageId`. Supply it when one inbound AS2 message contains
        multiple transaction sets. ModernEDI validates the composite reference
        against the selected production or test environment and authenticated
        workspace before transforming or sending. A missing or unauthorized
        exact inbound transaction returns 404 without invoking the map or
        tenant runtime. When omitted, ModernEDI resolves and persists the key
        only if `originalMessageId` identifies exactly one inbound transaction;
        an ambiguous multi-transaction message returns 400.
      example: 17#0001
    CopyToPartnerId:
      name: copyToPartnerId
      in: query
      required: true
      schema:
        type: integer
      description: Stable partner id returned by `GET /v1/partners` for the partner that receives the carbon-copy AS2 envelope. This does not select the outgoing map; `partnerId` selects the original/source map.
      example: 2
    MessageId:
      name: messageId
      in: path
      required: true
      schema:
        type: string
      description: AS2 message id.
    TransactionKey:
      name: transactionKey
      in: path
      required: true
      schema:
        type: string
      description: Transaction key, usually `<functional-group-control-number>#<transaction-control-number>`.
  securitySchemes:
    IntegrationApiKeyHeader:
      type: apiKey
      in: header
      name: x-api-key
      description: |
        Recommended tenant integration API key header. Keys may grant `transactions:read`, `transactions:write`, `transactions:replay`, `messages:write`, `configuration:read`, and `configuration:write`. See each operation's required scope.
    IntegrationApiKeyBearer:
      type: http
      scheme: bearer
      bearerFormat: API key
      description: Alternative bearer-token form of the same scoped tenant integration API key.
  schemas:
    PartnerListResponse:
      description: Successful response containing active trading-partner configurations in this workspace.
      type: object
      required:
        - success
        - partners
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        partners:
          type: array
          description: Active configured trading partners for this tenant, ordered by partner id. Retired partners are excluded.
          items:
            $ref: '#/components/schemas/PartnerConfiguration'
    IntegrationPartner:
      type: object
      required:
        - partnerId
        - name
        - as2ConnectionConfigured
        - productionReady
        - testReady
        - carbonCopyOnly
        - implementationAcknowledgmentEnabled
        - as2ConnectionId
        - ediSupportEmail
        - unmappedInboundPolicy
        - signingCertificateSlot
        - supportsNewlineAfterSegmentTerminator
        - x12
      properties:
        partnerId:
          type: integer
          description: Stable tenant-scoped partner id. Use this value as the `partnerId` query parameter for exact outbound map selection.
          example: 1
        name:
          type: string
          description: Configured partner display name. Use `partnerId` for outbound selection.
          example: Customer One
        as2ConnectionId:
          type: integer
          nullable: true
          description: Tenant-scoped partner AS2 connection id, or `null` while connection details are not yet available.
          example: 12
        as2ConnectionConfigured:
          type: boolean
          description: True when this partner is attached to an AS2 connection profile. The profile may be inbound-only and therefore is not necessarily ready for outbound delivery.
        productionReady:
          type: boolean
          description: True when the partner has a complete production AS2 identifier and certificate, destination URL, and X12 identity, so outbound production delivery can be attempted.
        testReady:
          type: boolean
          description: True when the partner has a complete test AS2 identifier and certificate, destination URL, and X12 identity, so outbound test delivery can be attempted. False is valid for a production-only or inbound-only partner.
        carbonCopyOnly:
          type: boolean
          description: True when the partner is intended only as a carbon-copy recipient in the workspace.
        implementationAcknowledgmentEnabled:
          type: boolean
          description: >
            Whether ModernEDI sends X12 999 implementation acknowledgments for
            this partner's 005010-and-later documents instead of automatic 997s.
            Earlier X12 versions continue to receive 997s. Enable this only
            when the partner requests 999s. A 999 reports X12 syntax and
            relational validation. It does not indicate semantic or business
            acceptance, and it is not HIPAA implementation-guide certification.
        ediSupportEmail:
          type: string
          description: Partner EDI support address, or an empty string when one has not been recorded.
          example: edi@customer-one.example
        unmappedInboundPolicy:
          type: string
          enum:
            - MAPPED_ONLY
            - PASSTHROUGH_RAW_X12
          description: Whether inbound transactions without a matching map are rejected from mapped-output delivery or persisted as raw X12.
        signingCertificateSlot:
          type: string
          enum:
            - active
            - next
          description: Tenant certificate slot ModernEDI uses to sign AS2 traffic for this partner.
        supportsNewlineAfterSegmentTerminator:
          type: boolean
          description: Whether ModernEDI may emit a newline after each X12 segment terminator for this partner.
        x12:
          description: Connected partners satisfy `PartnerX12Identities`; detached drafts may contain incomplete authoring values until an AS2 connection is attached.
          anyOf:
            - $ref: '#/components/schemas/PartnerX12Identities'
            - $ref: '#/components/schemas/PartnerDraftX12Identities'
        etag:
          type: string
          description: Quoted SHA-256 ETag over mutable partner configuration, present on list and configuration detail responses. Derived `as2ConnectionConfigured`, `productionReady`, and `testReady` values are excluded; changes to the referenced AS2 connection are guarded by that connection's own ETag.
    PartnerX12Identities:
      type: object
      required:
        - production
        - test
      description: Production is always configured. Test is `null` for a production-only partner.
      properties:
        production:
          description: Complete production X12 sender identity for this connected partner.
          $ref: '#/components/schemas/PartnerX12Identity'
        test:
          description: Complete test X12 sender identity, or `null` when this partner has no separate test identity.
          oneOf:
            - $ref: '#/components/schemas/PartnerX12Identity'
            - type: object
              nullable: true
              enum:
                - null
    PartnerX12Identity:
      type: object
      required:
        - isaQualifier
        - isaId
        - gsId
      properties:
        isaQualifier:
          type: string
          minLength: 2
          maxLength: 2
          description: ISA qualifier ModernEDI expects for this partner in the selected environment. Connected partners always use exactly 2 characters; detached draft values may be incomplete.
          example: ZZ
        isaId:
          type: string
          minLength: 1
          maxLength: 15
          description: ISA id ModernEDI expects for this partner in the selected environment. Connected partners always use between 1 and 15 characters inclusive; detached draft values may be incomplete.
          example: CUSTOMERONE
        gsId:
          type: string
          minLength: 1
          maxLength: 15
          description: GS sender or receiver id configured for this partner in the selected environment. Connected partners always use between 1 and 15 characters inclusive; detached draft values may be incomplete.
          example: CUSTOMERONE
    PartnerDraftX12Identities:
      type: object
      description: Resolved authoring values returned for a detached partner draft. Production fields may remain incomplete until an AS2 connection is attached. Test is `null` when no test identity has been entered.
      required:
        - production
        - test
      properties:
        production:
          description: Current production authoring values, which may be incomplete until transport is attached.
          $ref: '#/components/schemas/PartnerDraftX12Identity'
        test:
          description: Current test authoring values, or `null` when no test identity has been entered.
          oneOf:
            - $ref: '#/components/schemas/PartnerDraftX12Identity'
            - type: object
              nullable: true
              enum:
                - null
    PartnerDraftX12Identity:
      type: object
      required:
        - isaQualifier
        - isaId
        - gsId
      properties:
        isaQualifier:
          type: string
          description: Draft ISA qualifier. Attaching an AS2 connection requires exactly 2 characters.
        isaId:
          type: string
          description: Draft ISA id. Attaching an AS2 connection requires between 1 and 15 characters inclusive.
        gsId:
          type: string
          description: Draft GS id. Attaching an AS2 connection requires between 1 and 15 characters inclusive.
    PartnerX12IdentityInputs:
      type: object
      description: Production and optional test X12 identities supplied on create or patch. Detached drafts may omit either environment or individual identity fields. On create, an omitted test environment is stored as absent. On patch, omitting test preserves it while setting `test` to `null` removes it. A non-null test identity must resolve to all three fields together when connected. Omitted production ISA qualifiers default to `ZZ`, omitted ISA ids default to an empty draft value, and an omitted GS id defaults to the resolved ISA id.
      properties:
        production:
          description: Partner identity for production traffic. ModernEDI matches it against inbound sender values and uses it as the receiver identity in outbound X12 envelopes.
          allOf:
            - $ref: '#/components/schemas/PartnerX12IdentityInput'
        test:
          description: Optional partner identity for test traffic. A connected test identity requires all three fields and a test profile on the selected AS2 connection. On patch, use `null` to remove it.
          oneOf:
            - $ref: '#/components/schemas/PartnerX12IdentityInput'
            - type: object
              nullable: true
              enum:
                - null
    PartnerX12IdentityInput:
      type: object
      properties:
        isaQualifier:
          type: string
          description: Partner ISA qualifier used as ISA05 on inbound interchanges and ISA07 on outbound interchanges. Connected identities require exactly 2 characters.
        isaId:
          type: string
          description: Partner interchange id used as ISA06 inbound and ISA08 outbound. Connected identities require between 1 and 15 characters inclusive.
        gsId:
          type: string
          description: Partner functional-group id used as GS02 inbound and GS03 outbound. Connected identities require between 1 and 15 characters inclusive.
    PartnerConfiguration:
      allOf:
        - $ref: '#/components/schemas/IntegrationPartner'
        - type: object
          required:
            - etag
    PartnerResponse:
      description: Successful response containing one current trading-partner configuration.
      type: object
      required:
        - success
        - partner
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        partner:
          description: Complete persisted partner configuration with a concurrency-control ETag.
          $ref: '#/components/schemas/PartnerConfiguration'
    PartnerMutationResponse:
      allOf:
        - $ref: '#/components/schemas/PartnerResponse'
        - type: object
          required:
            - runtimePublication
          properties:
            runtimePublication:
              $ref: '#/components/schemas/RuntimePublication'
    PartnerWriteRequest:
      type: object
      required:
        - name
      description: Creates either a connected partner or a detached draft. When `as2ConnectionId` is non-null, ModernEDI validates the complete resolved X12 identities before committing.
      properties:
        name:
          type: string
          minLength: 1
          description: Unique human-readable partner name within this workspace. ModernEDI trims surrounding whitespace; renaming the partner does not change its `partnerId` or outbound routing.
        as2ConnectionId:
          type: integer
          minimum: 1
          nullable: true
          description: Tenant-scoped connection id returned by `GET /v1/as2/connections`. Omit or use `null` to create a map-authoring draft without transport. Attaching a connection validates the final production and optional test X12 identities.
        x12:
          $ref: '#/components/schemas/PartnerX12IdentityInputs'
        ediSupportEmail:
          type: string
          default: ''
          description: Optional partner EDI support contact stored for operator reference. Use an empty string when unavailable; this is not an automated ModernEDI notification recipient.
        carbonCopyOnly:
          type: boolean
          default: false
          description: When true, this partner is intended as an explicit carbon-copy recipient rather than a primary transaction partner. It is excluded from ordinary AS2 and X12 partner matching except for acknowledgment handling.
        implementationAcknowledgmentEnabled:
          type: boolean
          default: false
          description: >
            When true, ModernEDI sends a 999 instead of a 997 for this
            partner's 005010-and-later documents. Earlier versions continue to
            receive 997s. Enable only when the partner requests 999s. The 999
            reports X12 syntax and relational validation. It does not indicate
            semantic or business acceptance, and it is not HIPAA
            implementation-guide certification.
        unmappedInboundPolicy:
          type: string
          enum:
            - MAPPED_ONLY
            - PASSTHROUGH_RAW_X12
          default: MAPPED_ONLY
          description: Controls valid inbound X12 transactions for which no published map matches. `MAPPED_ONLY` produces no mapped-output queue item. `PASSTHROUGH_RAW_X12` queues the original transaction as `application/edi-x12`, using its transaction control number as the business key.
        signingCertificateSlot:
          type: string
          enum:
            - active
            - next
          default: active
          description: Tenant certificate used to sign AS2 traffic for this partner. `active` uses the current certificate. `next` supports partner-by-partner rollover and is rejected until a rollover certificate exists.
        supportsNewlineAfterSegmentTerminator:
          type: boolean
          default: false
          description: Controls line breaks already present in outbound X12. When false, ModernEDI removes CR and LF characters before AS2 packaging; when true, it preserves them. Enable only when the partner accepts line breaks after segment terminators.
    PartnerPatchRequest:
      type: object
      description: Any subset of writable partner fields. Omitted values remain unchanged.
      properties:
        name:
          type: string
          minLength: 1
          description: Unique human-readable partner name within this workspace. ModernEDI trims surrounding whitespace; renaming the partner does not change its `partnerId` or outbound routing.
        as2ConnectionId:
          type: integer
          minimum: 1
          nullable: true
          description: Tenant-scoped connection id returned by `GET /v1/as2/connections`. Set to `null` to detach the partner without deleting either resource. Attaching a connection validates the final merged X12 identities.
        x12:
          $ref: '#/components/schemas/PartnerX12IdentityInputs'
        ediSupportEmail:
          type: string
          description: Optional partner EDI support contact stored for operator reference. Use an empty string to clear it; this is not an automated ModernEDI notification recipient.
        carbonCopyOnly:
          type: boolean
          description: When true, this partner is intended as an explicit carbon-copy recipient rather than a primary transaction partner. It is excluded from ordinary AS2 and X12 partner matching except for acknowledgment handling.
        implementationAcknowledgmentEnabled:
          type: boolean
          description: >
            When true, ModernEDI sends a 999 instead of a 997 for this
            partner's 005010-and-later documents. Earlier versions continue to
            receive 997s. Omit this field to preserve the current setting. A
            999 reports X12 syntax and relational validation. It does not
            indicate semantic or business acceptance, and it is not HIPAA
            implementation-guide certification.
        unmappedInboundPolicy:
          type: string
          enum:
            - MAPPED_ONLY
            - PASSTHROUGH_RAW_X12
          description: Controls valid inbound X12 transactions for which no published map matches. `MAPPED_ONLY` produces no mapped-output queue item. `PASSTHROUGH_RAW_X12` queues the original transaction as `application/edi-x12`, using its transaction control number as the business key.
        signingCertificateSlot:
          type: string
          enum:
            - active
            - next
          description: Tenant certificate used to sign AS2 traffic for this partner. `active` uses the current certificate. `next` supports partner-by-partner rollover and is rejected until a rollover certificate exists.
        supportsNewlineAfterSegmentTerminator:
          type: boolean
          description: Controls line breaks already present in outbound X12. When false, ModernEDI removes CR and LF characters before AS2 packaging; when true, it preserves them.
    PartnerCapabilitiesResponse:
      description: Published incoming and outgoing mapping capabilities available for one partner.
      type: object
      required:
        - success
        - partner
        - capabilities
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        partner:
          description: Partner identity and readiness context for the capability list.
          $ref: '#/components/schemas/IntegrationPartner'
        capabilities:
          type: object
          description: Published maps grouped by the direction in which data crosses the partner boundary.
          required:
            - incoming
            - outgoing
          properties:
            incoming:
              type: array
              description: Maps that transform inbound partner X12 into application-facing mapped outputs.
              items:
                $ref: '#/components/schemas/PartnerMappingCapability'
            outgoing:
              type: array
              description: Maps that transform application payloads into outbound partner X12.
              items:
                $ref: '#/components/schemas/PartnerMappingCapability'
    PartnerMappingCapability:
      description: One published map advertised as an integration capability for a partner.
      type: object
      required:
        - mappingId
        - direction
        - x12Version
        - transactionSet
        - transformType
        - mappingSha256
        - published
      properties:
        mappingId:
          type: integer
          description: Stable workspace-scoped mapping identifier used by mapping configuration operations.
        direction:
          type: string
          description: '`incoming` consumes partner X12; `outgoing` produces partner X12.'
          enum:
            - incoming
            - outgoing
        x12Version:
          type: string
          description: Numeric X12 implementation version matched or generated by this map.
          example: '4010'
        functionalGroupType:
          type: string
          nullable: true
          description: GS01 functional identifier used for outgoing selection, or `null` when it is not part of the map key.
          example: PO
        transactionSet:
          type: string
          description: ST01 transaction-set identifier matched or generated by this map.
          example: '850'
        contentType:
          type: string
          nullable: true
          description: Source content type for outgoing maps or mapped-output content type for incoming maps.
          example: application/json
        transformType:
          type: string
          description: >
            Published transform implementation: `X12_MAPPER`, `XSLT`, or `JSLT`.
          example: JSLT
        purpose:
          type: string
          nullable: true
          allOf:
            - $ref: '#/components/schemas/MappingPurpose'
        mappingSha256:
          type: string
          description: Base64-encoded SHA-256 hash of the published map contents.
          example: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
        published:
          type: boolean
          enum:
            - true
          description: Always `true` because unpublished drafts are not exposed as partner capabilities.
    As2ProfileResponse:
      description: Successful response containing the workspace AS2 identity, endpoints, network addresses, and certificates.
      type: object
      required:
        - success
        - profile
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        profile:
          description: Workspace-facing AS2 profile to exchange with trading partners and security teams.
          $ref: '#/components/schemas/As2Profile'
    As2Profile:
      description: ModernEDI-hosted AS2 identity and network information for production and test traffic.
      type: object
      required:
        - domainName
        - environments
        - network
        - certificates
      properties:
        domainName:
          type: string
          nullable: true
          description: Provisioned tenant AS2 hostname, or `null` while the tenant runtime has not published one.
          example: edi.customer.example
        environments:
          type: object
          description: Environment-specific inbound endpoints and ModernEDI sender identities.
          required:
            - production
            - test
          properties:
            production:
              description: Production endpoints and sender identity; individual fields may be `null` while provisioning is incomplete.
              $ref: '#/components/schemas/As2EnvironmentProfile'
            test:
              description: Isolated test endpoints and sender identity; fields may be `null` when no test runtime is available.
              $ref: '#/components/schemas/As2EnvironmentProfile'
        network:
          description: Provisioning, TLS, and static-address capabilities customers should share with partner network teams.
          $ref: '#/components/schemas/As2NetworkProfile'
        certificates:
          type: object
          description: Public signing/encryption certificates ModernEDI may present for this workspace.
          required:
            - active
            - next
          properties:
            active:
              type: object
              nullable: true
              description: Current certificate to configure at partners, or `null` before certificate provisioning completes.
              allOf:
                - $ref: '#/components/schemas/As2PublicCertificate'
            next:
              type: object
              nullable: true
              description: Staged rollover certificate, or `null` when no certificate rotation is in progress.
              allOf:
                - $ref: '#/components/schemas/As2PublicCertificate'
    As2EnvironmentProfile:
      description: ModernEDI endpoint and X12 sender identity for one workspace environment.
      type: object
      required:
        - as2Url
        - as2Identifier
        - x12Sender
      properties:
        as2Url:
          type: string
          format: uri
          nullable: true
          description: HTTPS AS2 receive URL to configure at the partner, or `null` while the endpoint is unavailable.
        httpAs2Url:
          type: string
          format: uri
          description: Plain-HTTP endpoint when included in the tenant's plan and provisioned.
        as2Identifier:
          type: string
          nullable: true
          description: ModernEDI AS2 identifier sent as `AS2-From` and expected as inbound `AS2-To`, or `null` while unprovisioned.
        x12Sender:
          type: object
          description: ModernEDI X12 envelope identity for documents sent from this environment.
          required:
            - isaQualifier
            - isaId
            - gsId
          properties:
            isaQualifier:
              type: string
              nullable: true
              description: ISA05/ISA07 qualifier for ModernEDI's environment identity, or `null` while unprovisioned.
            isaId:
              type: string
              nullable: true
              description: ISA06/ISA08 identifier for ModernEDI's environment identity, or `null` while unprovisioned.
            gsId:
              type: string
              nullable: true
              description: GS02/GS03 identifier for ModernEDI's environment identity, or `null` while unprovisioned.
    As2NetworkProfile:
      description: Current tenant-runtime network and certificate provisioning state.
      type: object
      required:
        - provisioningStatus
        - tlsCertificateStatus
        - staticInbound
        - staticOutbound
      properties:
        provisioningStatus:
          type: string
          nullable: true
          description: Latest tenant-runtime provisioning state, or `null` before a status has been recorded.
        tlsCertificateStatus:
          type: string
          nullable: true
          description: Latest TLS certificate deployment state for the AS2 hostname, or `null` when unavailable.
        staticInbound:
          description: Fixed public destination addresses available for partners that require inbound IP allowlisting.
          $ref: '#/components/schemas/As2NetworkCapability'
        staticOutbound:
          description: Fixed public source addresses seen by partners receiving ModernEDI AS2 traffic.
          $ref: '#/components/schemas/As2NetworkCapability'
    As2NetworkCapability:
      description: Availability and advertised addresses for one static-network capability.
      type: object
      required:
        - status
        - addresses
      properties:
        status:
          type: string
          description: '`ready` means addresses may be allowlisted, `pending` means provisioning is incomplete, and `not_included` means the plan does not include the capability.'
          enum:
            - ready
            - pending
            - not_included
        addresses:
          type: array
          description: Public IP addresses to give the partner; empty until ready or when the capability is not included.
          items:
            type: string
            description: Public IPv4 or IPv6 address for partner allowlists.
    As2PublicCertificate:
      description: Public half of a ModernEDI AS2 signing/encryption certificate; private keys are never exposed.
      type: object
      required:
        - slot
        - publicCertPem
      properties:
        slot:
          type: string
          description: 'Certificate lifecycle slot: `active` is in service and `next` is staged for partner-by-partner rollover.'
          enum:
            - active
            - next
        subjectDn:
          type: string
          nullable: true
          description: X.509 subject distinguished name, or `null` when certificate parsing did not provide it.
        issuerDn:
          type: string
          nullable: true
          description: X.509 issuer distinguished name, or `null` when certificate parsing did not provide it.
        serialNumber:
          type: string
          nullable: true
          description: Certificate serial number rendered for partner correlation, or `null` when unavailable.
        fingerprintSha256:
          type: string
          nullable: true
          description: SHA-256 certificate fingerprint for out-of-band verification, or `null` when unavailable.
        notBefore:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        notAfter:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        publicCertPem:
          type: string
          description: PEM-encoded public certificate safe to share with trading partners.
    As2ConnectionListResponse:
      description: Successful response containing every AS2 connection configured in the authenticated workspace.
      type: object
      required:
        - success
        - connections
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        connections:
          type: array
          description: Complete AS2 connection configurations, including environment profiles, transport settings, and configuration ETags.
          items:
            $ref: '#/components/schemas/As2ConnectionConfiguration'
    As2ConnectionResponse:
      description: Successful response containing one complete AS2 connection configuration.
      type: object
      required:
        - success
        - connection
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        connection:
          description: Current persisted connection after defaults have been resolved.
          $ref: '#/components/schemas/As2ConnectionConfiguration'
    As2ConnectionMutationResponse:
      allOf:
        - $ref: '#/components/schemas/As2ConnectionResponse'
        - type: object
          required:
            - runtimePublication
          properties:
            runtimePublication:
              $ref: '#/components/schemas/RuntimePublication'
    As2ConnectionConfiguration:
      description: Complete persisted AS2 connection returned by configuration operations.
      type: object
      additionalProperties: false
      required:
        - connectionId
        - environments
        - outbound
        - functionalAcknowledgment
        - mdn
        - cmsAlgorithmProtection
        - digestCanonicalizationPolicy
        - etag
      properties:
        connectionId:
          type: integer
          minimum: 1
          description: Stable workspace-scoped identifier used when attaching partners or updating this connection.
        environments:
          $ref: '#/components/schemas/As2ConnectionResolvedEnvironments'
        outbound:
          $ref: '#/components/schemas/As2ResolvedOutboundSettings'
        functionalAcknowledgment:
          $ref: '#/components/schemas/As2ResolvedFunctionalAcknowledgmentSettings'
        mdn:
          $ref: '#/components/schemas/As2ResolvedMdnSettings'
        cmsAlgorithmProtection:
          type: boolean
          description: Effective RFC 6211 `cmsAlgorithmProtect` compatibility setting for signed outbound messages and MDNs.
        digestCanonicalizationPolicy:
          type: string
          enum:
            - AUTO
            - CANONICALIZE
            - PRESERVE
          description: Effective inbound signature-verification treatment of MIME line endings.
        etag:
          type: string
          description: Quoted SHA-256 configuration ETag required in `If-Match` for safe updates and deletion.
    As2ResolvedOutboundSettings:
      description: Fully resolved outbound algorithms and compatibility settings; all fields are present in responses.
      allOf:
        - $ref: '#/components/schemas/As2OutboundTransportSettings'
        - type: object
          required:
            - signingAlgorithm
            - encryptionAlgorithm
            - compressionAlgorithm
            - micAlgorithm
            - micAlgorithmFormat
    As2ResolvedFunctionalAcknowledgmentSettings:
      description: Fully resolved MIME packaging for automatic X12 acknowledgments (997 or partner-enabled 999).
      allOf:
        - $ref: '#/components/schemas/As2FunctionalAcknowledgmentSettings'
        - type: object
          required:
            - messageStructure
    As2ResolvedMdnSettings:
      description: Fully resolved Message Disposition Notification compatibility settings.
      allOf:
        - $ref: '#/components/schemas/As2MdnSettings'
        - type: object
          required:
            - encrypt
            - forceSynchronousForErrors
    As2ConnectionCreateRequest:
      type: object
      additionalProperties: false
      description: Sparse AS2 connection input. Only `environments.production` is required; omitted transport fields use the documented ModernEDI defaults.
      required:
        - environments
      properties:
        environments:
          type: object
          required:
            - production
          description: The production identifier and certificate are required; its destination URL is optional for inbound-only operation. Test may be omitted or `null`; when present, its identifier and certificate are required together and its destination URL is optional.
          properties:
            production:
              allOf:
                - $ref: '#/components/schemas/As2PartnerEnvironment'
              description: Required production partner identity, public certificate, and optional outbound destination.
            test:
              description: Optional test partner profile. Use `null` or omit it on create when the partner has no separate test configuration.
              oneOf:
                - $ref: '#/components/schemas/As2PartnerEnvironment'
                - type: object
                  nullable: true
                  enum:
                    - null
        outbound:
          allOf:
            - $ref: '#/components/schemas/As2OutboundTransportSettings'
          description: Algorithms and signed-message compatibility formatting ModernEDI uses for AS2 messages, automatic X12 acknowledgments (997 or partner-enabled 999), and signed MDNs sent to this partner. Omitted values use the documented defaults.
        functionalAcknowledgment:
          allOf:
            - $ref: '#/components/schemas/As2FunctionalAcknowledgmentSettings'
          description: AS2 packaging used when ModernEDI automatically returns an X12 acknowledgment to this partner. It applies to the default 997 and to a partner-enabled 999.
        mdn:
          allOf:
            - $ref: '#/components/schemas/As2MdnSettings'
          description: Message Disposition Notification delivery-receipt interoperability settings.
        cmsAlgorithmProtection:
          type: boolean
          default: false
          description: Advanced partner-compatibility switch for signed outbound AS2 messages and signed MDNs. When `true`, ModernEDI includes the RFC 6211 `cmsAlgorithmProtect` signed attribute, which binds the digest and signature algorithm identifiers into the signature. The default is `false` because some older AS2/S/MIME engines—including older IBM Sterling/B2B Integrator installations—do not support that attribute's OID (`1.2.840.113549.1.9.52`) even though they can verify the underlying signature. Enable it only when the partner explicitly requires or has successfully tested the attribute. This setting does not turn message signing on or off and does not change how inbound signatures are validated.
        digestCanonicalizationPolicy:
          type: string
          enum:
            - AUTO
            - CANONICALIZE
            - PRESERVE
          default: AUTO
          description: Advanced inbound-signature compatibility policy for partners that calculate the signed MIME digest over line endings differently. `AUTO` (recommended default) verifies the MIME-canonical CRLF form first and, only after a digest mismatch when retrying is safe, tries the exact body bytes received. `CANONICALIZE` accepts only the canonical CRLF calculation; `PRESERVE` accepts only the received-byte calculation. Leave `AUTO` unless partner testing or ModernEDI Support identifies a consistent engine-specific requirement. This setting affects incoming signature verification only; it does not rewrite X12 or change outbound message formatting.
    As2ConnectionPatchRequest:
      type: object
      description: Any subset of AS2 connection fields. Nested omitted values remain unchanged. Set an `endpointUrl` to `null` to remove only that outbound destination. Set `environments.test` to `null` to remove the complete test profile, unless an attached partner still has test X12 identity fields. Test protection flags may be changed only when a test profile already exists or in the same patch that supplies a complete test identifier and certificate; removing a test profile resets both protections to their secure `true` defaults.
      properties:
        environments:
          type: object
          description: Partial production and test partner profiles. Nested omitted fields retain their current values.
          properties:
            production:
              allOf:
                - $ref: '#/components/schemas/As2PartnerEnvironmentPatch'
              description: Partial production partner profile. Omitted identifier, URL, and certificate values remain unchanged.
            test:
              description: Partial updates merge with an existing test profile. Null removes the complete test profile when no attached partner still has test X12 identity fields and resets both test protections to `true`. `requireSignature` and `requireEncryption` are accepted only for an existing test profile or when this object also creates a complete test profile.
              oneOf:
                - $ref: '#/components/schemas/As2PartnerEnvironmentPatch'
                - type: object
                  nullable: true
                  enum:
                    - null
        outbound:
          allOf:
            - $ref: '#/components/schemas/As2OutboundTransportSettingsPatch'
          description: Partial outbound cryptographic, compression, and signed-message compatibility settings. Omitted values remain unchanged.
        functionalAcknowledgment:
          allOf:
            - $ref: '#/components/schemas/As2FunctionalAcknowledgmentSettingsPatch'
          description: Partial automatic X12 acknowledgment AS2 packaging settings for 997s and partner-enabled 999s. Omitted values remain unchanged.
        mdn:
          allOf:
            - $ref: '#/components/schemas/As2MdnSettingsPatch'
          description: Partial Message Disposition Notification settings. Omitted values remain unchanged.
        cmsAlgorithmProtection:
          type: boolean
          description: Whether signed outbound AS2 messages and signed MDNs include the RFC 6211 `cmsAlgorithmProtect` signed attribute. Use `false` for older engines—including older IBM Sterling/B2B Integrator installations—that do not support OID `1.2.840.113549.1.9.52`; use `true` only when the partner requires or has successfully tested it. This does not turn message signing on or off or change inbound validation. Omit the field to preserve the current setting.
        digestCanonicalizationPolicy:
          type: string
          enum:
            - AUTO
            - CANONICALIZE
            - PRESERVE
          description: Inbound signature-verification treatment of MIME line endings. `AUTO` tries canonical CRLF bytes first and safely falls back to the exact received bytes after a digest mismatch; `CANONICALIZE` and `PRESERVE` force only one form. Omit the field to preserve the current setting.
    As2PartnerEnvironment:
      type: object
      required:
        - as2Identifier
        - publicCertificatePem
      properties:
        as2Identifier:
          type: string
          minLength: 1
          description: Partner's environment-specific AS2 identifier. ModernEDI matches it as inbound `AS2-From` and sends it as outbound `AS2-To`.
          example: RETAILER_PROD
        endpointUrl:
          type: string
          format: uri
          maxLength: 2000
          nullable: true
          description: Optional outbound destination. Omit it or use `null` for an inbound-only profile. When present, it must be an absolute HTTP or HTTPS partner destination URL without user information or a fragment. Endpoint workspaces must use HTTPS; plain HTTP requires Endpoint Plus, Static Outbound, Static Network, or Enterprise. The host must be publicly routable; local, private, link-local, multicast, carrier-grade NAT, documentation, benchmark, and other reserved address targets are rejected.
          example: https://as2.retailer.example/receive
        publicCertificatePem:
          type: string
          description: Exactly one PEM-encoded partner X.509 public certificate. ModernEDI canonicalizes it before storage.
          example: |-
            -----BEGIN CERTIFICATE-----
            MIIB...partner-public-certificate...
            -----END CERTIFICATE-----
        requireSignature:
          type: boolean
          default: true
          description: When `true` (the secure default), ModernEDI rejects non-MDN inbound messages for this environment unless the sender signature is present and successfully verified with the configured certificate. This policy belongs to the AS2 connection/environment and therefore applies to every attached partner on a shared or VAN connection. Set `false` only for a documented connection-wide exception. Omission on create resolves to `true`; resolved connection responses always include the field.
        requireEncryption:
          type: boolean
          default: true
          description: When `true` (the secure default), ModernEDI rejects non-MDN inbound messages for this environment unless their encrypted content was successfully decrypted. This policy belongs to the AS2 connection/environment and therefore applies to every attached partner on a shared or VAN connection. Set `false` only for a documented connection-wide exception. Omission on create resolves to `true`; resolved connection responses always include the field.
    As2PartnerEnvironmentPatch:
      type: object
      properties:
        as2Identifier:
          type: string
          minLength: 1
          description: Partner's environment-specific AS2 identifier. ModernEDI matches it as inbound `AS2-From` and sends it as outbound `AS2-To`.
        endpointUrl:
          type: string
          format: uri
          maxLength: 2000
          nullable: true
          description: Absolute public HTTP or HTTPS partner destination URL without user information or a fragment. Set to `null` to remove the destination while retaining the AS2 profile for inbound-only operation. Endpoint workspaces must use HTTPS; plain HTTP requires Endpoint Plus, Static Outbound, Static Network, or Enterprise.
        publicCertificatePem:
          type: string
          description: Replacement partner X.509 public certificate. Supply exactly one PEM-encoded certificate; ModernEDI canonicalizes it before storage.
        requireSignature:
          type: boolean
          description: Whether non-MDN inbound messages must carry a signature that ModernEDI successfully verifies. Omit to preserve the current policy.
        requireEncryption:
          type: boolean
          description: Whether non-MDN inbound messages must contain encrypted content that ModernEDI successfully decrypts. Omit to preserve the current policy.
    As2PartnerEnvironmentResolved:
      description: Persisted AS2 partner environment with all secure inbound-protection defaults resolved.
      allOf:
        - $ref: '#/components/schemas/As2PartnerEnvironment'
        - type: object
          required:
            - requireSignature
            - requireEncryption
    As2ConnectionResolvedEnvironments:
      type: object
      additionalProperties: false
      description: Fully resolved partner environments. Every non-null environment includes its effective inbound signature and encryption requirements.
      required:
        - production
        - test
      properties:
        production:
          $ref: '#/components/schemas/As2PartnerEnvironmentResolved'
        test:
          description: Fully resolved test environment, or `null` when no test profile is configured.
          oneOf:
            - $ref: '#/components/schemas/As2PartnerEnvironmentResolved'
            - type: object
              nullable: true
              enum:
                - null
    As2OutboundTransportSettings:
      type: object
      additionalProperties: false
      description: Optional outbound AS2 algorithms and MIME-compatibility controls. Each omitted field receives its documented default.
      properties:
        signingAlgorithm:
          type: string
          enum:
            - SHA256WITHRSA
            - SHA384WITHRSA
            - SHA512WITHRSA
            - SHA1WITHRSA
          default: SHA256WITHRSA
          description: CMS/S/MIME signature algorithm ModernEDI uses for signed outbound payloads, signed automatic X12 acknowledgments, and signed MDNs. Prefer `SHA256WITHRSA`; use `SHA1WITHRSA` only for a legacy partner that cannot verify SHA-2 signatures.
          example: SHA256WITHRSA
        encryptionAlgorithm:
          type: string
          enum:
            - AES256_CBC
            - AES128_CBC
            - DES_EDE3_CBC
          default: AES256_CBC
          description: CMS content-encryption algorithm for outbound AS2 payloads and any encrypted acknowledgments. Prefer `AES256_CBC`; `DES_EDE3_CBC` exists only for legacy partner interoperability.
          example: AES256_CBC
        compressionAlgorithm:
          type: string
          enum:
            - ZLIB
          default: ZLIB
          description: Compression algorithm used when an outbound AS2 message structure includes compression. `ZLIB` is the only supported customer-selectable value.
          example: ZLIB
        micAlgorithm:
          type: string
          enum:
            - SHA_1
            - SHA_256
            - SHA_512
          default: SHA_256
          description: Digest algorithm used to calculate and store ModernEDI's local content MIC for outbound X12 payloads and automatic X12 acknowledgments. This does not choose the CMS signature digest (`signingAlgorithm` does), the signed MIME `micalg` token format (`micAlgorithmFormat` does), or the `Received-content-MIC` algorithm used when ModernEDI returns an MDN for an inbound message; that comes from the sender's receipt request.
        micAlgorithmFormat:
          type: string
          enum:
            - RFC_5751
            - RFC_3851
          default: RFC_3851
          description: Advanced partner-compatibility override for the S/MIME `Content-Type` `micalg` parameter on every signed MIME entity ModernEDI generates for this partner, including outbound X12 messages, automatic signed X12 acknowledgments, and the outer wrapper of signed MDNs. `RFC_5751` uses the newer hyphenated token format—for example, `sha-256`—while `RFC_3851` uses the older token `sha256`. Omit this field to use the compatibility-first `RFC_3851` default. This setting changes only the serialized notation of the signature digest selected by `signingAlgorithm` in that MIME parameter; it does not change the digest itself or the algorithm named inside `Received-content-MIC`. Change it only when the partner's AS2 profile or interoperability testing requires a particular token format.
    As2OutboundTransportSettingsPatch:
      type: object
      additionalProperties: false
      properties:
        signingAlgorithm:
          type: string
          enum:
            - SHA256WITHRSA
            - SHA384WITHRSA
            - SHA512WITHRSA
            - SHA1WITHRSA
          description: CMS/S/MIME signature algorithm used after the patch. Prefer `SHA256WITHRSA`; `SHA1WITHRSA` is retained only for legacy partner interoperability.
        encryptionAlgorithm:
          type: string
          enum:
            - AES256_CBC
            - AES128_CBC
            - DES_EDE3_CBC
          description: Content-encryption algorithm used after the patch. Prefer `AES256_CBC`; select 3DES only when required by a legacy partner.
        compressionAlgorithm:
          type: string
          enum:
            - ZLIB
          description: Compression algorithm used after the patch when a MIME structure includes compression; only `ZLIB` is supported.
        micAlgorithm:
          type: string
          enum:
            - SHA_1
            - SHA_256
            - SHA_512
          description: Digest algorithm used to calculate and store ModernEDI's local content MIC for outbound X12 payloads and automatic X12 acknowledgments. This does not choose the CMS signature digest (`signingAlgorithm` does), the signed MIME `micalg` token format (`micAlgorithmFormat` does), or the `Received-content-MIC` algorithm used when ModernEDI returns an MDN for an inbound message; that comes from the sender's receipt request.
        micAlgorithmFormat:
          type: string
          enum:
            - RFC_5751
            - RFC_3851
          description: S/MIME `Content-Type` `micalg` token format used for signed outbound payloads, signed automatic X12 acknowledgments, and the outer wrapper of signed MDNs. `RFC_5751` emits the newer hyphenated form such as `sha-256`; `RFC_3851` emits the older form such as `sha256`. This changes only the serialized notation of the signature digest selected by `signingAlgorithm`; it does not change the digest itself or the algorithm named inside `Received-content-MIC`. Omit the field to preserve the current setting.
    As2FunctionalAcknowledgmentSettings:
      type: object
      additionalProperties: false
      description: Optional automatic X12 acknowledgment MIME packaging for 997s and partner-enabled 999s. Omit the object or `messageStructure` to use `SIGNED_ENCRYPTED`.
      properties:
        messageStructure:
          type: string
          enum:
            - PLAIN
            - SIGNED
            - ENCRYPTED
            - SIGNED_ENCRYPTED
            - PLAIN_COMPRESSED
            - SIGNED_COMPRESSED
            - ENCRYPTED_COMPRESSED
            - ENCRYPTED_COMPRESSED_SIGNED
          default: SIGNED_ENCRYPTED
          description: MIME signing, encryption, and compression structure used when ModernEDI automatically sends an X12 acknowledgment (997 or partner-enabled 999) to this partner.
    As2FunctionalAcknowledgmentSettingsPatch:
      type: object
      additionalProperties: false
      properties:
        messageStructure:
          type: string
          enum:
            - PLAIN
            - SIGNED
            - ENCRYPTED
            - SIGNED_ENCRYPTED
            - PLAIN_COMPRESSED
            - SIGNED_COMPRESSED
            - ENCRYPTED_COMPRESSED
            - ENCRYPTED_COMPRESSED_SIGNED
          description: MIME signing, encryption, and compression structure used when ModernEDI automatically sends an X12 acknowledgment (997 or partner-enabled 999) to this partner.
    As2MdnSettings:
      type: object
      additionalProperties: false
      description: Optional MDN interoperability controls. Omitted values default to unencrypted MDNs and synchronous error dispositions.
      properties:
        encrypt:
          type: boolean
          default: false
          description: When true, ModernEDI attempts to encrypt MDNs returned for inbound messages with the partner certificate and configured outbound encryption algorithm. If MDN encryption itself fails, ModernEDI returns an unencrypted error MDN so the partner still receives a disposition.
        forceSynchronousForErrors:
          type: boolean
          default: true
          description: When true, an inbound processing failure or error is returned as a synchronous MDN even when the normal receipt flow is asynchronous.
    As2MdnSettingsPatch:
      type: object
      additionalProperties: false
      properties:
        encrypt:
          type: boolean
          description: When true, ModernEDI attempts to encrypt MDNs returned for inbound messages. When false, MDNs remain unencrypted.
        forceSynchronousForErrors:
          type: boolean
          description: When true, an inbound processing failure or error is returned as a synchronous MDN even when the normal receipt flow is asynchronous.
    GeneratedX12Request:
      type: object
      required:
        - x12
      properties:
        x12:
          type: string
          description: Complete X12 interchange to validate and send without mapping.
        businessKey:
          allOf:
            - $ref: '#/components/schemas/OutboundBusinessKey'
          description: Optional business identifier stored for transaction search and reconciliation.
    OutboundTransformEnvelope:
      type: object
      required:
        - contentType
        - input
      properties:
        contentType:
          type: string
          description: >
            Content type of `input` and the outgoing map to select. Use this
            envelope with HTTP `Content-Type:
            application/vnd.modernedi.outbound+json` when the source input is
            XML, text, or JSON with extra transform params. Ordinary
            `application/json` is always treated as the source document itself.
          example: application/xml
        input:
          description: >
            Source document to transform. For XML or text content types this
            must be a string. For JSON content types this may be a JSON object,
            array, string, number, boolean, or null.
          oneOf:
            - type: string
              nullable: true
            - type: object
              additionalProperties: true
            - type: array
              items: {}
            - type: number
            - type: boolean
        businessKey:
          allOf:
            - $ref: '#/components/schemas/OutboundBusinessKey'
          description: >
            Optional business identifier to store on the outbound transaction
            record, such as an invoice number, ASN number, BOL number, shipment
            id, or other value your system uses for reconciliation. This is
            recorded for transaction search and display only; it does not affect
            outgoing-map selection or transform execution.
        params:
          type: object
          additionalProperties: true
          description: >
            Optional transform parameters. For XSLT maps, each key is bound as
            an external stylesheet parameter with the same simple, unqualified
            name. `json` and `text` are reserved by ModernEDI. JSON
            strings map to `xs:string`, integers to integer numbers, decimals
            to decimal numbers, booleans to `xs:boolean`, null to an empty
            sequence, objects to `map(xs:string, item()*)`, and arrays to XDM
            sequences. Arrays of objects therefore work with declarations such
            as `<xsl:param name="pallets" as="map(xs:string, xs:anyAtomicType)*"
            required="yes"/>`. JSLT still uses `.` as its current input, but for
            JSLT maps ModernEDI evaluates the map with a root wrapper object
            shaped as `{ "input": <source>, "params": <params> }`. Source
            fields are therefore read as `.input.invoice.number` instead of
            directly from the root, and params are read as `.params.bolNumber`,
            `.params.pallets[0]`, and so on. When JSLT repeated output needs
            params inside a `for` loop,
            bind `.params` before the loop, such as `let params = .params`, and
            read `$params.bolNumber` inside the loop because `.` is the current
            source item there. Use `required="yes"` for XSLT params that every
            live request must supply. Params JSON files in the mapper editor are
            used only for test-running a map; they are not live defaults for this
            API. In the mapper editor, params are standalone JSON fixture files
            that can be edited like other workspace files and selected when
            test-running the map. While authoring JSLT, the editor uses the
            selected source and params fixture files for completions,
            diagnostics, and quick fixes for wrapper root mistakes, missing
            sample paths, and `get-key` object-key typos.
          example:
            bolNumber: BOL-DEMO-8842
            totalWeightInLbs: 1232.54
            transactionSetControlNumber: '000002321'
            pallets:
              - buyerSku: DEMO-SKU-001
                itemNumber: DEMO-ITEM-001
                numCases: 187
                sscc18: '000000000000000101'
    OutboundBusinessKey:
      type: object
      required:
        - name
        - value
      properties:
        name:
          type: string
          minLength: 1
          description: Stable business-key name, for example `invoiceNumber`, `shipmentId`, or `bolNumber`.
          example: shipmentId
        value:
          oneOf:
            - type: string
              minLength: 1
            - type: number
            - type: boolean
          description: Scalar business-key value. Numbers and booleans in the JSON envelope are accepted and stored as strings.
          example: ASN-DEMO-1001
    SendSuccessResponse:
      description: Confirmation that ModernEDI validated, packaged, and handed an outbound AS2 message to the configured partner endpoint.
      type: object
      required:
        - success
        - messageId
        - x12
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; transport or validation failures use the documented error response instead.
        messageId:
          type: string
          description: AS2 Message-Id assigned to the outbound message.
          example: <generated-message-id@modernedi>
        x12:
          type: string
          description: >
            Final X12 sent downstream after ModernEDI syntax-checks it and wraps
            it for AS2 delivery. For mapped endpoints this is generated output;
            for `/v1/as2/x12/...` endpoints it is the validated X12 supplied by
            the caller.
    OutboundPreviewResponse:
      description: Dry-run result showing map selection, generated X12, validation diagnostics, and partner context without sending AS2.
      type: object
      required:
        - success
        - generatedX12
        - validation
        - mapping
        - partner
        - businessKey
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; map-selection or transform failures use the documented error response instead.
        generatedX12:
          type: string
          description: Complete generated X12 that would be sent by `/v1/as2/send`.
        validation:
          description: X12 syntax and structure diagnostics for the generated output; review `valid` before attempting delivery.
          $ref: '#/components/schemas/X12ValidationResult'
        mapping:
          type: object
          description: Published outgoing map selected from the partner, content type, X12 version, and request route.
          required:
            - id
            - transformType
            - file
            - fileSha256Hash
            - contentType
            - x12Version
          properties:
            id:
              type: integer
              description: Stable workspace-scoped identifier of the selected outgoing map.
            transformType:
              type: string
              description: Transform engine used by the published map, such as `xslt` or `jslt`.
              example: xslt
            file:
              type: string
              description: Customer-visible transform filename recorded for the selected map.
            fileSha256Hash:
              type: string
              description: Base64-encoded SHA-256 hash of the published map contents.
              example: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
            contentType:
              type: string
              description: Source media type expected by the selected outgoing map.
            x12Version:
              type: string
              description: X12 version the selected map generates.
        partner:
          type: object
          description: Source trading partner whose outgoing map and configuration were selected.
          required:
            - partnerId
            - name
          properties:
            partnerId:
              type: integer
              description: Stable workspace-scoped partner id used for exact selection.
            name:
              type: string
              description: Current customer-visible name of the selected partner.
        businessKey:
          type: object
          nullable: true
          description: Business identifier that would be recorded with a real send, or `null` when none was supplied.
          allOf:
            - $ref: '#/components/schemas/OutboundBusinessKey'
    MappedOutputQueueResponse:
      description: One bounded poll of application-facing mapped outputs from the selected environment.
      type: object
      required:
        - success
        - environment
        - messages
        - limit
        - visibilityTimeoutSeconds
        - nextCursor
        - hasMore
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; authentication or queue failures use the documented error response instead.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        messages:
          type: array
          description: Outputs leased to this poll; acknowledge each successfully persisted item using its id and latest receipt handle.
          items:
            $ref: '#/components/schemas/MappedOutputMessage'
        limit:
          type: integer
          description: Maximum number of deliverable messages requested for this poll, after server bounds are applied.
          example: 10
        visibilityTimeoutSeconds:
          type: integer
          description: Lease duration in seconds; unacknowledged messages may be redelivered after this interval.
          example: 120
        nextCursor:
          type: string
          nullable: true
          description: >
            Opaque position for the next bounded scan. Send this value as the
            next poll's `cursor` whenever `hasMore` is true.
        hasMore:
          type: boolean
          description: True when `nextCursor` should be used to continue scanning.
    MappedOutputMessage:
      description: One mapped application document leased from ModernEDI's managed output queue.
      type: object
      required:
        - id
        - receiptHandle
        - deliveryCount
        - environment
        - messageId
        - transactionKey
        - mappedOutputKey
        - sequenceNumber
        - purpose
      properties:
        id:
          type: string
          description: >
            Stable id for this generated output version, used when marking the
            message received. A later durable regeneration can produce a new id
            for the same `messageId` and `mappedOutputKey`.
        receiptHandle:
          type: string
          description: Token from the latest poll response, required when marking the message received.
        deliveryCount:
          type: integer
          description: Number of pull or webhook delivery leases issued for this generated output version.
        leasedUntil:
          type: string
          format: date-time
          description: UTC instant when ModernEDI may return this message again if it has not been marked received.
          nullable: true
        messageId:
          type: string
          description: >
            Original inbound AS2 message id. Use this value as
            `originalMessageId` when sending a reply with `/v1/as2/reply`.
        transactionKey:
          type: string
          description: Transaction identifier within the AS2 message, usually `GS06#ST02`.
        partnerName:
          type: string
          description: Partner name. Omitted when `deliveredMetadata.partner` is `false`.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        partnerId:
          type: integer
          description: Persisted tenant-scoped partner id. Omitted when `deliveredMetadata.partner` is `false`.
        transactionTimestamp:
          allOf:
            - $ref: '#/components/schemas/UtcTimestamp'
          description: Source transaction timestamp. Omitted when `deliveredMetadata.transactionTimestamp` is `false`.
        transactionSet:
          allOf:
            - $ref: '#/components/schemas/TransactionSet'
          description: Transaction-set code and description. Omitted when `deliveredMetadata.transactionSet` is `false`.
        controlNumbers:
          allOf:
            - $ref: '#/components/schemas/TransactionControlNumbers'
          description: >
            X12 transaction and functional-group control numbers. Individual properties are omitted according to
            `deliveredMetadata.transactionControlNumber` and `deliveredMetadata.functionalGroupControlNumber`; the
            object is omitted when both are `false`.
        edi:
          allOf:
            - $ref: '#/components/schemas/TransactionEdiMetadata'
          description: >
            Optional X12 context controlled by `deliveredMetadata.transactionSet`, `x12Version`,
            `functionalIdentifierCode`, and `segmentTerminator`. The object is omitted when all four are `false`.
        mapping:
          description: Published incoming map that produced the payload; metadata fields may be absent when their delivery flag is disabled.
          $ref: '#/components/schemas/MappedOutputMapping'
        mappedOutputKey:
          type: string
          description: Unique mapped-output key inside the transaction.
        sequenceNumber:
          type: integer
          description: Zero-based output order when one source transaction produces multiple mapped documents.
        purpose:
          $ref: '#/components/schemas/MappingPurpose'
        contentType:
          type: string
          nullable: true
          description: Media type for `payload`, such as `application/json` or `application/xml`.
          example: application/json
        createdAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        businessKey:
          type: object
          nullable: true
          description: Map-derived business identifier for customer reconciliation, or `null` when the map did not produce one.
          allOf:
            - $ref: '#/components/schemas/TransactionBusinessKey'
        extraFields:
          type: object
          description: >
            Runtime routing metadata recorded with the generated output, such as
            `{"destination":"managedQueue"}`. This is not the customer-selectable context; use the mapping's
            `deliveredMetadata` flags for that.
          additionalProperties:
            type: string
        payload:
          type: string
          nullable: true
          description: Mapped document body. Parse according to `contentType`.
    MappedOutputMapping:
      description: Identity and source version of the published incoming map that generated a queued output.
      type: object
      properties:
        id:
          type: integer
          nullable: true
          description: Workspace-scoped mapping id, or `null` for historical outputs that predate persisted map identity.
          example: 44
        type:
          type: string
          nullable: true
          description: Runtime mapping implementation name, or `null` when it was not recorded with an older output.
          example: ManagedQueueMapping
        file:
          type: string
          nullable: true
          description: Customer-visible source filename, or `null` when unavailable on an older output.
          example: customer-one-850.jslt
        fileSha256Hash:
          type: string
          description: >
            Base64-encoded SHA-256 hash of the published map contents. Omitted when
            `deliveredMetadata.mappingSourceHash` is `false`.
          example: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
        syntaxTreeCatalogRevision:
          type: string
          pattern: '^[0-9a-f]{64}$'
          description: Immutable grammar-catalog revision declared by the mapping execution; omitted for legacy outputs.
        syntaxTreeSha256:
          type: string
          pattern: '^[0-9a-f]{64}$'
          description: SHA-256 of the exact transaction-set grammar bytes used by the mapping execution; omitted for legacy outputs.
    MappedOutputAckRequest:
      type: object
      required:
        - receiptHandle
      properties:
        receiptHandle:
          type: string
          description: Token from the latest poll response for this mapped output id.
    MappedOutputAckResponse:
      description: Confirmation that one leased mapped output moved into acknowledged-by-your-integration custody.
      type: object
      required:
        - success
        - environment
        - acknowledgment
        - id
        - messageId
        - mappedOutputKey
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; stale handles or unknown outputs use the documented error response instead.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        acknowledgment:
          description: Canonical identity and acknowledgment timestamp for the output now held by your integration.
          $ref: '#/components/schemas/MappedOutputAcknowledgment'
        id:
          type: string
          description: Mapped output id that was marked received.
        messageId:
          type: string
          description: Original inbound AS2 message id for the mapped output.
        mappedOutputKey:
          type: string
          description: Unique mapped-output key inside the transaction.
        ackedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: UTC instant when the mapped output was acknowledged.
    MappedOutputAcknowledgment:
      description: Durable receipt record proving when your integration acknowledged one mapped output version.
      type: object
      required:
        - id
        - messageId
        - mappedOutputKey
      properties:
        id:
          type: string
          description: Stable generated-output version id that was acknowledged.
        messageId:
          type: string
          description: Original inbound AS2 message id associated with the acknowledged output.
        mappedOutputKey:
          type: string
          description: Unique mapped-output key within the source transaction.
        ackedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: UTC instant when the mapped output was acknowledged.
    MappedOutputBulkAckRequest:
      type: object
      required:
        - acks
      properties:
        acks:
          type: array
          minItems: 1
          maxItems: 100
          description: One to 100 mapped-output id and receipt-handle pairs from the selected environment. The batch is atomic; if any pair is invalid, none are acknowledged.
          items:
            type: object
            required:
              - id
              - receiptHandle
            properties:
              id:
                type: string
                description: Mapped-output id returned by the poll response.
              receiptHandle:
                type: string
                description: Receipt handle from the same poll response.
    MappedOutputBulkAckResponse:
      description: Atomic confirmation that every requested mapped-output lease was acknowledged.
      type: object
      required:
        - success
        - environment
        - acknowledgedCount
        - acknowledgments
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; if any lease is invalid the entire request fails and no output is acknowledged.
        environment:
          allOf:
            - $ref: '#/components/schemas/TransactionEnvironmentValue'
          description: Selects the isolated transaction history containing the original transaction. Defaults to `production` when omitted.
        acknowledgedCount:
          type: integer
          minimum: 1
          maximum: 100
          description: Number of outputs acknowledged by this atomic batch.
        acknowledgments:
          type: array
          description: Canonical acknowledgment records in the same successful batch.
          items:
            $ref: '#/components/schemas/MappedOutputAcknowledgment'
    MappingListResponse:
      description: Successful response containing all publicly manageable and read-only legacy maps in the workspace.
      type: object
      required:
        - success
        - mappings
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        mappings:
          type: array
          description: Current published mapping configurations, including source text, output contract, and ETags.
          items:
            $ref: '#/components/schemas/MappingConfiguration'
    MappingResponse:
      description: Successful response containing one current mapping configuration.
      type: object
      required:
        - success
        - mapping
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        mapping:
          description: Complete current mapping configuration after defaults and server-managed delivery behavior are resolved.
          $ref: '#/components/schemas/MappingConfiguration'
    MappingMutationResponse:
      allOf:
        - $ref: '#/components/schemas/MappingResponse'
        - type: object
          required:
            - runtimePublication
          properties:
            runtimePublication:
              $ref: '#/components/schemas/RuntimePublication'
    MappingSourceVersionListResponse:
      description: Newest-first immutable source history plus the complete currently published mapping source.
      type: object
      required:
        - success
        - mappingId
        - currentEtag
        - currentSourceVersion
        - nextCursor
        - hasMore
        - sourceVersions
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        mappingId:
          type: integer
          minimum: 1
          description: Stable workspace-scoped mapping id whose source history was requested.
        currentEtag:
          type: string
          description: Quoted ETag for the complete currently published mapping. Send this exact value in `If-Match` when restoring a source version.
        currentSourceVersion:
          allOf:
            - $ref: '#/components/schemas/MappingSourceVersionDetail'
          description: Complete currently published transform source from the same locked configuration snapshot as `currentEtag`. This is present even when its chronological source-version entry is outside the current page.
        nextCursor:
          type: string
          nullable: true
          description: Opaque cursor for the next chronological page, or `null` when no older source versions remain.
        hasMore:
          type: boolean
          description: Whether another page is available through `nextCursor`.
        sourceVersions:
          type: array
          description: One newest-first page of unique immutable transform-source summaries. Identical source text is represented once even if it was published more than once.
          items:
            $ref: '#/components/schemas/MappingSourceVersionSummary'
    MappingSourceVersionResponse:
      description: Successful response containing one immutable historical mapping source revision.
      type: object
      required:
        - success
        - sourceVersion
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        sourceVersion:
          description: Complete immutable source revision suitable for preview, diff, or restore.
          $ref: '#/components/schemas/MappingSourceVersionDetail'
    MappingSourceVersionSummary:
      type: object
      required:
        - sourceVersionId
        - createdAt
        - sourceHash
        - current
        - transform
      properties:
        sourceVersionId:
          type: integer
          minimum: 1
          description: Immutable id for this unique stored transform source.
        createdAt:
          $ref: '#/components/schemas/UtcTimestamp'
        sourceHash:
          type: string
          description: Base64-encoded SHA-256 hash of the transform source text. This identifies source content; it is not a concurrency-control ETag.
          example: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
        current:
          type: boolean
          description: Whether this source hash matches the mapping source that is currently published.
        syntaxTreeCatalog:
          description: Immutable grammar identifiers recorded when this source was approved; omitted for legacy revisions.
          $ref: '#/components/schemas/SyntaxTreeCatalogBinding'
        transform:
          description: Transform type and original archived filename for this revision.
          $ref: '#/components/schemas/MappingSourceVersionTransformSummary'
    MappingSourceVersionDetail:
      type: object
      required:
        - sourceVersionId
        - createdAt
        - sourceHash
        - current
        - transform
      properties:
        sourceVersionId:
          type: integer
          minimum: 1
          description: Immutable id for this unique stored transform source.
        createdAt:
          $ref: '#/components/schemas/UtcTimestamp'
        sourceHash:
          type: string
          description: Base64-encoded SHA-256 hash of the transform source text. This identifies source content; it is not a concurrency-control ETag.
          example: 5vG51TfOLEo9YN0WSMf0bj+xzluq2UptTm4flVSo8EE=
        current:
          type: boolean
          description: Whether this source hash matches the mapping source that is currently published.
        syntaxTreeCatalog:
          description: Immutable grammar identifiers recorded when this source was approved; omitted for legacy revisions.
          $ref: '#/components/schemas/SyntaxTreeCatalogBinding'
        transform:
          description: Transform type, archived filename, and complete immutable source text.
          $ref: '#/components/schemas/MappingSourceVersionTransformDetail'
    MappingSourceVersionTransformSummary:
      type: object
      required:
        - type
        - fileName
      properties:
        type:
          type: string
          description: Transform runtime that compiled or interpreted this archived source.
          enum:
            - X12_MAPPER
            - XSLT
            - JSLT
        fileName:
          type: string
          description: Transform filename recorded when this source was first archived. Restore keeps the currently published filename.
    MappingSourceVersionTransformDetail:
      type: object
      required:
        - type
        - fileName
        - source
      properties:
        type:
          type: string
          description: Transform runtime that compiled or interpreted this archived source.
          enum:
            - X12_MAPPER
            - XSLT
            - JSLT
        fileName:
          type: string
          description: Transform filename recorded when this source was first archived. Restore keeps the currently published filename.
        source:
          type: string
          description: Complete immutable historical transform source, suitable for previewing or diffing against the current mapping source.
    MappingConfiguration:
      description: Complete published map, transform source, output contract, provenance controls, and concurrency ETag.
      type: object
      required:
        - mappingId
        - partnerId
        - direction
        - x12Version
        - functionalIdentifierCode
        - transactionSetIdentifierCode
        - transform
        - output
        - etag
      properties:
        mappingId:
          type: integer
          minimum: 1
          description: Stable workspace-scoped mapping id used for reads, updates, history, restore, and deletion.
        partnerId:
          type: integer
          minimum: 1
          description: Stable workspace-scoped partner id whose X12 traffic this map handles.
        direction:
          type: string
          description: '`INCOMING` transforms partner X12 to application data; `OUTGOING` transforms application data to partner X12.'
          enum:
            - INCOMING
            - OUTGOING
        x12Version:
          type: string
          description: Normalized X12 version, such as `4010`.
          example: '4010'
        functionalIdentifierCode:
          type: string
          description: X12 GS01 functional identifier enum name.
          example: PO
        transactionSetIdentifierCode:
          type: string
          description: X12 ST01 transaction-set identifier without a leading underscore.
          example: '850'
        syntaxTreeCatalog:
          description: Immutable grammar identifiers bound when this mapping configuration was approved.
          $ref: '#/components/schemas/SyntaxTreeCatalogBinding'
        transform:
          description: Executable source and filename currently published for this map.
          $ref: '#/components/schemas/MappingTransform'
        output:
          description: Content type, business purpose, and server-selected delivery boundary for this map.
          $ref: '#/components/schemas/MappingOutputConfiguration'
        businessKey:
          description: Searchable value extractor for incoming transactions; omitted on outgoing mappings.
          $ref: '#/components/schemas/MappingBusinessKey'
        deliveredMetadata:
          allOf:
            - $ref: '#/components/schemas/MappingDeliveredMetadata'
          description: Present only for incoming mappings.
        etag:
          type: string
          description: Quoted SHA-256 configuration ETag.
    SyntaxTreeCatalogBinding:
      type: object
      readOnly: true
      description: >
        Content-addressed identifiers for the exact X12 grammar used to validate and execute a mapping.
        These values support reproducibility and diagnostics and do not expose internal storage locations.
      required:
        - schemaVersion
        - catalogRevision
        - manifestSha256
        - syntaxTreeSha256
      properties:
        schemaVersion:
          type: integer
          enum:
            - 1
          description: Version of this catalog-binding metadata contract, used by clients to interpret the immutable grammar identifiers safely.
        catalogRevision:
          type: string
          pattern: '^[0-9a-f]{64}$'
          description: >
            SHA-256 identity of the complete immutable syntax-tree catalog at approval time. This approval
            revision can differ from a later active platform catalog when syntaxTreeSha256 proves that the
            exact grammar for this mapping's X12 version and transaction set is unchanged.
        manifestSha256:
          type: string
          pattern: '^[0-9a-f]{64}$'
          description: SHA-256 of the canonical catalog manifest.
        syntaxTreeSha256:
          type: string
          pattern: '^[0-9a-f]{64}$'
          description: SHA-256 of the exact normalized grammar bytes for this X12 version and transaction set.
    MappingWriteRequest:
      oneOf:
        - $ref: '#/components/schemas/IncomingMappingWriteRequest'
        - $ref: '#/components/schemas/OutgoingMappingWriteRequest'
    IncomingMappingWriteRequest:
      type: object
      required:
        - partnerId
        - direction
        - x12Version
        - functionalIdentifierCode
        - transactionSetIdentifierCode
        - transform
        - output
        - businessKey
      properties:
        partnerId:
          type: integer
          minimum: 1
          description: Tenant-scoped partner id returned by `GET /v1/partners`. The mapping is published only for this partner.
        direction:
          type: string
          enum:
            - INCOMING
          description: Mapping-direction discriminator. `INCOMING` consumes X12 and requires an `X12_MAPPER` transform.
        x12Version:
          type: string
          description: X12 reference version for parsing and validation, such as `4010`. The selected version and transaction set must exist in ModernEDI's syntax-tree catalog.
        functionalIdentifierCode:
          type: string
          description: X12 GS01 functional identifier code, such as `PO`.
        transactionSetIdentifierCode:
          type: string
          description: X12 ST01 transaction-set identifier without a leading underscore, such as `850`.
        transform:
          description: Executable X12 Mapper source used to convert each matching inbound X12 transaction into the configured output payload.
          allOf:
            - $ref: '#/components/schemas/MappingTransform'
            - type: object
              properties:
                type:
                  type: string
                  enum:
                    - X12_MAPPER
                  description: Incoming mappings use ModernEDI's X12 Mapper language.
        output:
          allOf:
            - $ref: '#/components/schemas/MappingOutput'
          description: Content type and business purpose of the payload produced by the incoming map.
        businessKey:
          allOf:
            - $ref: '#/components/schemas/MappingBusinessKey'
          description: Searchable business identifier extracted from each inbound transaction, such as a purchase-order or invoice number.
        deliveredMetadata:
          allOf:
            - $ref: '#/components/schemas/MappingDeliveredMetadata'
          description: Optional mapped-output context controls. Omitted keys default to `true`.
    OutgoingMappingWriteRequest:
      type: object
      required:
        - partnerId
        - direction
        - x12Version
        - functionalIdentifierCode
        - transactionSetIdentifierCode
        - transform
        - output
      properties:
        partnerId:
          type: integer
          minimum: 1
          description: Tenant-scoped partner id returned by `GET /v1/partners`. The mapping is selected only for this partner.
        direction:
          type: string
          enum:
            - OUTGOING
          description: Mapping-direction discriminator. `OUTGOING` transforms application data into X12 and requires an `XSLT` or `JSLT` transform.
        x12Version:
          type: string
          description: X12 reference version for generated output, such as `4010`. The selected version and transaction set must exist in ModernEDI's syntax-tree catalog.
        functionalIdentifierCode:
          type: string
          description: X12 GS01 functional identifier code to generate, such as `IN`.
        transactionSetIdentifierCode:
          type: string
          description: X12 ST01 transaction-set identifier to generate without a leading underscore, such as `810`.
        transform:
          description: Executable XSLT or JSLT source used to convert application input into the selected X12 transaction.
          allOf:
            - $ref: '#/components/schemas/MappingTransform'
            - type: object
              properties:
                type:
                  type: string
                  enum:
                    - XSLT
                    - JSLT
                  description: Outgoing XML or JSON transform runtime. XSLT supports XML and Saxon `json-to-xml`; JSLT consumes the JSON wrapper documented by the send endpoints.
        output:
          description: Source media type used to select this outgoing map. Outgoing mappings always use the `PROCESSING` purpose.
          allOf:
            - $ref: '#/components/schemas/MappingOutput'
            - type: object
              properties:
                purpose:
                  type: string
                  enum:
                    - PROCESSING
                  description: Outgoing maps always generate normal processing documents.
    MappingPatchRequest:
      type: object
      description: Deep partial mapping configuration. `mappingId`, `etag`, and `output.delivery` are server-managed and rejected in the body.
      properties:
        partnerId:
          type: integer
          minimum: 1
          description: Reassigns the mapping to another tenant-scoped partner id returned by `GET /v1/partners`.
        direction:
          type: string
          enum:
            - INCOMING
            - OUTGOING
          description: Existing mapping direction. It may be supplied unchanged, but cannot be changed; create a new mapping to reverse direction.
        x12Version:
          type: string
          description: X12 reference version for the complete resulting mapping, such as `4010`. The version and transaction set must exist together.
        functionalIdentifierCode:
          type: string
          description: X12 GS01 functional identifier code for the complete resulting mapping.
        transactionSetIdentifierCode:
          type: string
          description: X12 ST01 transaction-set identifier without a leading underscore for the complete resulting mapping.
        transform:
          type: object
          description: Partial transform update. Omitted nested fields retain their current values; the complete resulting source is parsed or compiled before publication.
          properties:
            type:
              type: string
              enum:
                - X12_MAPPER
                - XSLT
                - JSLT
              description: Transform runtime. Incoming mappings support `X12_MAPPER`; outgoing mappings support `XSLT` and `JSLT`.
            fileName:
              type: string
              maxLength: 255
              description: Source-controlled transform filename shown in the workspace and transaction provenance.
            source:
              type: string
              maxLength: 524288
              description: Complete replacement map source text. Source-only patches are supported and validated before the current revision changes.
        output:
          type: object
          description: Partial output contract update. Omitted nested fields retain their current values.
          properties:
            contentType:
              type: string
              maxLength: 255
              description: Mapped payload content type for incoming maps, or source content type used to select outgoing maps.
            purpose:
              $ref: '#/components/schemas/MappingPurpose'
        businessKey:
          type: object
          description: Partial searchable business-key update for an incoming mapping. Omitted nested fields retain their current values.
          properties:
            name:
              type: string
              maxLength: 128
              description: Stable customer-facing label for the extracted value, such as `purchaseOrderNumber`.
            extractor:
              type: string
              maxLength: 4096
              description: X12 Mapper expression that extracts the searchable business-key value from each inbound transaction.
        deliveredMetadata:
          allOf:
            - $ref: '#/components/schemas/MappingDeliveredMetadata'
          description: Incoming mappings only. Supplying this field for an outgoing mapping is rejected.
    MappingTransform:
      type: object
      required:
        - type
        - fileName
        - source
      properties:
        type:
          type: string
          enum:
            - X12_MAPPER
            - XSLT
            - JSLT
          description: Transform runtime selected by mapping direction. Incoming mappings use `X12_MAPPER`; outgoing mappings use `XSLT` or `JSLT`.
        fileName:
          type: string
          minLength: 1
          maxLength: 255
          description: Source-controlled transform filename shown in the workspace and transaction provenance.
        source:
          type: string
          minLength: 1
          maxLength: 524288
          description: Complete map source text, limited to 524,288 characters (512 KiB) by the executable mapping runtime. This value is returned on reads for configuration-as-code workflows.
    MappingOutput:
      type: object
      required:
        - contentType
      properties:
        contentType:
          type: string
          minLength: 1
          maxLength: 255
          description: Mapped payload content type for incoming maps; source content type selected by outgoing maps.
        purpose:
          allOf:
            - $ref: '#/components/schemas/MappingPurpose'
          default: PROCESSING
          description: Defaults to `PROCESSING` when omitted. Incoming mappings may also use `ACKNOWLEDGMENT`; outgoing mappings use `PROCESSING`.
    MappingOutputConfiguration:
      allOf:
        - $ref: '#/components/schemas/MappingOutput'
        - type: object
          required:
            - delivery
          properties:
            delivery:
              allOf:
                - $ref: '#/components/schemas/MappingOutputDelivery'
              readOnly: true
              description: Server-selected delivery behavior. New incoming public mappings use `MAPPED_OUTPUTS`; outgoing maps use `OUTBOUND_AS2`.
    MappingOutputDelivery:
      type: string
      readOnly: true
      description: |
        Safe delivery category without infrastructure identifiers:

        - `MAPPED_OUTPUTS`: managed polling and per-partner webhook delivery
        - `TRANSACTION_RECORD`: incoming result retained on the transaction record
        - `OUTBOUND_AS2`: outbound source-to-X12 transform used by AS2 send APIs
      enum:
        - MAPPED_OUTPUTS
        - TRANSACTION_RECORD
        - OUTBOUND_AS2
    MappingBusinessKey:
      type: object
      required:
        - name
        - extractor
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 128
          description: Stable customer-facing label for the extracted value, such as `purchaseOrderNumber`.
          example: purchaseOrderNumber
        extractor:
          type: string
          minLength: 1
          maxLength: 4096
          description: Incoming X12 mapper expression used to persist the searchable business-key value.
          example: BEG03
    MappingDeliveredMetadata:
      type: object
      additionalProperties: false
      description: >
        Selects optional source and mapping context included in `GET /v1/mapped-outputs` message objects and the
        webhook's nested `message` object. Every field defaults to `true`. Setting a field to `false` omits its
        corresponding message property; queue identifiers, receipt handles, payload, content type, purpose, and
        business key remain present. Webhook-envelope routing fields such as `tenantId` and `partnerId` also remain
        present.
      properties:
        partner:
          type: boolean
          default: true
          description: Include `partnerName` and tenant-scoped `partnerId` in the mapped-output message.
        transactionTimestamp:
          type: boolean
          default: true
          description: Include the source transaction's persisted `transactionTimestamp`.
        transactionSet:
          type: boolean
          default: true
          description: Include `transactionSet` and the equivalent `edi.transactionGroupType` value.
        transactionControlNumber:
          type: boolean
          default: true
          description: Include `controlNumbers.transaction` (X12 ST02).
        functionalGroupControlNumber:
          type: boolean
          default: true
          description: Include `controlNumbers.functionalGroup` (X12 GS06).
        x12Version:
          type: boolean
          default: true
          description: Include `edi.x12Version`, derived from the parsed interchange version.
        functionalIdentifierCode:
          type: boolean
          default: true
          description: Include `edi.functionalIdentifierCode` (X12 GS01).
        segmentTerminator:
          type: boolean
          default: true
          description: Include `edi.segmentTerminator`.
        mappingSourceHash:
          type: boolean
          default: true
          description: Include `mapping.fileSha256Hash`, the Base64-encoded SHA-256 hash of the map source that generated this output.
    TransactionListResponse:
      description: Paginated transaction summaries plus an environment-wide operator-attention count and freshness state.
      type: object
      required:
        - success
        - environment
        - transactions
        - hasMore
        - window
        - attentionSummary
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; query or authorization failures use the documented error response instead.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        transactions:
          type: array
          description: Transactions matching the requested filters and cursor page, ordered newest first.
          items:
            $ref: '#/components/schemas/TransactionSummary'
        nextCursor:
          type: string
          nullable: true
          description: Opaque cursor for the next page, or `null` when no further matching transactions remain.
        hasMore:
          type: boolean
          description: True when `nextCursor` should be sent unchanged to retrieve another page.
        window:
          description: Normalized UTC date/time window applied to this transaction query.
          $ref: '#/components/schemas/TransactionWindow'
        attentionSummary:
          $ref: '#/components/schemas/TransactionAttentionSummary'
    TransactionDetailResponse:
      description: Metadata-first transaction record with a document index, mapping results, delivery state, acknowledgments, events, and compact linked-reply summaries.
      type: object
      required:
        - success
        - environment
        - transaction
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown transactions or authorization failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        transaction:
          description: Full operator-facing transaction detail for the requested message and transaction key.
          $ref: '#/components/schemas/TransactionDetail'
    TransactionWatchResponse:
      description: Resulting operator-watchlist state after an idempotent watch or unwatch operation.
      type: object
      required:
        - success
        - environment
        - messageId
        - transactionKey
        - onWatchlist
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown transactions or authorization failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        messageId:
          type: string
          description: AS2 message id of the transaction whose watch state changed.
          example: msg-850-api
        transactionKey:
          type: string
          description: Transaction identifier within the AS2 message, usually `GS06#ST02`.
          example: 17#0001
        onWatchlist:
          type: boolean
          description: Resulting watchlist state after the operation.
    TransactionDocumentsResponse:
      description: Metadata index of documents retained for one transaction, including X12, mapped outputs, acknowledgments, and HTTP response artifacts.
      type: object
      required:
        - success
        - environment
        - documents
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown transactions or authorization failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        documents:
          type: array
          description: Retained document metadata in display order. Fetch an individual document to obtain its body.
          items:
            $ref: '#/components/schemas/TransactionDocumentMetadata'
    TransactionEventsResponse:
      description: Chronological operational timeline for one transaction and its acknowledgments.
      type: object
      required:
        - success
        - environment
        - events
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown transactions or authorization failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        events:
          type: array
          description: Derived transaction, mapping, delivery, MDN, and acknowledgment events in chronological order.
          items:
            $ref: '#/components/schemas/TransactionEvent'
    TransactionDocumentResponse:
      description: One complete retained transaction artifact selected from the document index.
      type: object
      required:
        - success
        - environment
        - document
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; missing transactions or documents use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        document:
          $ref: '#/components/schemas/TransactionDocument'
    TransactionX12ValidationResponse:
      description: Structured validation of the X12 content retained for one visible transaction.
      type: object
      required:
        - success
        - environment
        - messageId
        - transactionKey
        - validation
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; invalid retained X12 is represented by `validation.valid=false`.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        messageId:
          type: string
          description: Message id from the requested transaction reference.
        transactionKey:
          type: string
          description: Transaction key from the requested transaction reference.
        validation:
          $ref: '#/components/schemas/X12ValidationResult'
    MappingRuntimeHealthResponse:
      description: Environment-wide summary of retained mapping failures and recoveries.
      type: object
      required:
        - success
        - environment
        - generatedAt
        - truncated
        - totals
        - mappings
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; authorization, billing, or runtime-read failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        generatedAt:
          $ref: '#/components/schemas/UtcTimestamp'
        truncated:
          type: boolean
          description: True when the bounded health scan could not summarize every retained attempt.
        totals:
          description: Aggregate unresolved-current, unmatched, and recovered mapping-attempt counts.
          $ref: '#/components/schemas/MappingRuntimeHealthTotals'
        mappings:
          type: array
          description: Mapping- or unmatched-request-level groups with failure or recovery activity.
          items:
            $ref: '#/components/schemas/MappingRuntimeMappingHealth'
    MappingRuntimeHealthTotals:
      type: object
      required:
        - failed
        - currentRevisionFailed
        - unmappedFailed
        - recovered
      properties:
        failed:
          type: integer
          minimum: 0
          description: Unresolved failures across all retained mapping revisions and unmatched requests.
        currentRevisionFailed:
          type: integer
          minimum: 0
          description: Unresolved failures produced by currently published mapping revisions.
        unmappedFailed:
          type: integer
          minimum: 0
          description: Unresolved failures for which no published mapping was resolved.
        recovered:
          type: integer
          minimum: 0
          description: Failures marked resolved by a later successful equivalent attempt.
    MappingRuntimeMappingHealth:
      type: object
      required:
        - mappingId
        - mapFile
        - mapFileSha256Hash
        - currentRevision
        - direction
        - partnerId
        - partnerName
        - latestAt
        - failureCount
        - recoveredCount
      properties:
        mappingId:
          type: integer
          minimum: 1
          nullable: true
          description: Mapping id, or `null` for a request that failed before map selection.
        mapFile:
          type: string
          nullable: true
          description: Transform filename, or `null` when no map was selected.
        mapFileSha256Hash:
          type: string
          nullable: true
          description: Base64 SHA-256 hash of the attempted mapping source, when known.
        currentRevision:
          type: boolean
          description: Whether the grouped attempt hash is still the currently published source.
        direction:
          type: string
          nullable: true
          enum:
            - inbound
            - outbound
          description: Mapping direction, or `null` when it was not attributable.
        partnerId:
          type: integer
          minimum: 1
          nullable: true
          description: Tenant-scoped partner id, or `null` when no partner was resolved.
        partnerName:
          type: string
          nullable: true
          description: Partner name captured for the attempt, when known.
        latestAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        failureCount:
          type: integer
          minimum: 0
          description: Unresolved failures in this group.
        recoveredCount:
          type: integer
          minimum: 0
          description: Resolved failures in this group.
    MappingRuntimeFailuresResponse:
      type: object
      required:
        - success
        - environment
        - failures
        - nextCursor
        - hasMore
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; invalid filters, cursors, or runtime-read failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        failures:
          type: array
          description: Reverse-chronological safe diagnostics matching the supplied environment and filters.
          items:
            $ref: '#/components/schemas/TransactionMappingAttempt'
        nextCursor:
          type: string
          nullable: true
          description: Opaque cursor for the next page, or `null` when this page is complete.
        hasMore:
          type: boolean
          description: True when `nextCursor` should be sent back for another page.
    MappingRuntimeFailureResponse:
      type: object
      required:
        - success
        - failure
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; an unknown or tenant-inaccessible failure id uses an error response.
        failure:
          $ref: '#/components/schemas/TransactionMappingAttempt'
    IntegrationChangeEventsResponse:
      description: Bootstrap cursor or chronological page of transaction-state invalidations.
      type: object
      required:
        - success
        - environment
        - events
        - nextCursor
        - hasMore
        - bootstrap
        - retentionSeconds
        - freshness
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; invalid or expired cursors use a structured error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        events:
          type: array
          description: Events strictly after the supplied cursor, ordered by detection sequence.
          items:
            $ref: '#/components/schemas/IntegrationChangeEvent'
        nextCursor:
          type: string
          description: >
            Opaque, integrity-protected cursor bound to this tenant and
            environment. Return it unchanged on the next poll, including after
            an empty page. Editing it or using it for another tenant or
            environment returns HTTP 400.
        hasMore:
          type: boolean
          description: True when another page is already available after `nextCursor`.
        bootstrap:
          type: boolean
          description: True only when the request omitted `cursor` and established a high-water mark.
        retentionSeconds:
          type: integer
          minimum: 1
          description: Rolling retention of this invalidation feed; independent of transaction-document retention.
          example: 2592000
        freshness:
          $ref: '#/components/schemas/TransactionAttentionFreshness'
    IntegrationChangeEvent:
      type: object
      required:
        - eventId
        - type
        - observedAt
        - transaction
        - changedFields
      properties:
        eventId:
          type: string
          description: Opaque event identifier for logging and deduplication; ordering comes from the cursor.
          example: evt_MTIz
        type:
          type: string
          enum:
            - transaction.created
            - transaction.changed
          description: Whether reconciliation first observed the transaction or detected a later state change.
        observedAt:
          $ref: '#/components/schemas/UtcTimestamp'
        transaction:
          description: Transaction identity to refetch after receiving this invalidation event.
          $ref: '#/components/schemas/IntegrationChangeTransactionReference'
        changedFields:
          type: array
          minItems: 1
          uniqueItems: true
          description: Public state components that changed; refetch transaction detail for their current values.
          items:
            $ref: '#/components/schemas/IntegrationChangeField'
    IntegrationChangeTransactionReference:
      type: object
      required:
        - messageId
        - transactionKey
        - replyToMessageId
      properties:
        messageId:
          type: string
          description: AS2 Message-Id of the transaction whose public state changed.
        transactionKey:
          type: string
          description: Transaction-local `GS06#ST02` key identifying the changed row.
        replyToMessageId:
          type: string
          nullable: true
          description: Source inbound message for an outbound reply, or `null`.
    IntegrationChangeField:
      type: string
      enum:
        - transaction
        - mappingStatus
        - functionalAcknowledgment
        - implementationAcknowledgment
        - technicalAcknowledgment
        - mdn
        - mappedOutputs
        - attention
      description: Stable public transaction component whose fingerprint changed.
    RelatedTransactionsResponse:
      description: Selected transaction plus outbound replies linked to its inbound AS2 message id.
      type: object
      required:
        - success
        - environment
        - transaction
        - relatedTransactions
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown transactions or authorization failures use an error response.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        transaction:
          description: Summary of the source transaction used to resolve related replies.
          $ref: '#/components/schemas/TransactionSummary'
        relatedTransactions:
          type: array
          description: Compact summaries of linked outbound reply transactions; empty when no replies are recorded. Fetch a selected reply's detail for its acknowledgment and document index.
          items:
            $ref: '#/components/schemas/TransactionSummary'
    TransactionWindow:
      type: object
      required:
        - startDate
        - endDate
        - timeZone
      properties:
        startDate:
          $ref: '#/components/schemas/UtcTimestamp'
        endDate:
          $ref: '#/components/schemas/UtcTimestamp'
        timeZone:
          type: string
          enum:
            - UTC
          description: Time zone used for transaction timestamps and normalized query windows.
    TransactionAttentionReason:
      type: string
      enum:
        - mapping_failure
        - functional_ack_issue
        - implementation_ack_issue
        - x12_ack_overdue
        - technical_ack_issue
        - technical_ack_overdue
        - as2_mdn_attention
        - mapped_output_not_collected
        - mapped_output_ack_overdue
        - watchlist
      description: >
        Machine-readable reason that a transaction needs operator attention.
        `functional_ack_issue` means a 997 was received but was not cleanly
        accepted. `implementation_ack_issue` means a 999 was received but the
        transaction-specific IK5 result or conservative AK9 group result was
        not cleanly accepted. `x12_ack_overdue` means neither a 997 nor
        a 999 was received for an
        eligible outbound business transaction by `x12AcknowledgmentExpectedBy`;
        outbound 997 and 999 acknowledgment documents are excluded. The overdue
        signal does not automatically resend the original X12.
        `technical_ack_issue` means a requested TA1 was received but rejected
        the interchange, reported errors, or could not be classified.
        `technical_ack_overdue` means ISA14 requested a TA1 but none was
        received by `technicalAckExpectedBy`. Neither technical-acknowledgment
        reason automatically resends the original X12.
        `as2_mdn_attention` means the partner's AS2 receipt is overdue, rejected,
        invalid, contains a warning, or its returned content MIC does not match
        the content ModernEDI sent. ModernEDI never automatically resends a
        document in response to an MDN issue because the partner may already
        have processed it.
        `mapped_output_not_collected` means a managed output remained available
        beyond the 15-minute pickup grace period without a first delivery lease.
        `mapped_output_ack_overdue` means a delivered output was not acknowledged
        before its lease expired or was delivered more than once. One transaction
        can have more than one active reason.
    TransactionAttentionSummary:
      type: object
      required:
        - needsAttentionCount
        - reasonCounts
        - freshness
      description: >
        Environment-wide operator-inbox summary. Counts are independent of the
        transaction list's date window, row limit, cursor, and other filters.
        A transaction with more than one reason is counted once in
        `needsAttentionCount` and once in each applicable reason count. Its
        `freshness` also applies to `mappingStatus`, `functionalAckStatus`,
        `implementationAckStatus`, and `mdnStatus` list filtering and to
        list-level projected MDN status.
      properties:
        needsAttentionCount:
          type: integer
          minimum: 0
          description: Distinct transactions currently projected as needing attention.
        reasonCounts:
          type: object
          description: Active transaction counts by independently applicable attention reason.
          required:
            - mappingFailure
            - functionalAckIssue
            - implementationAckIssue
            - x12AckOverdue
            - technicalAckIssue
            - technicalAckOverdue
            - as2MdnAttention
            - mappedOutputNotCollected
            - mappedOutputAckOverdue
            - watchlist
          properties:
            mappingFailure:
              type: integer
              minimum: 0
              description: Transactions with one or more unresolved mapping attempts.
            functionalAckIssue:
              type: integer
              minimum: 0
              description: Transactions with a received 997 that was not cleanly accepted.
            implementationAckIssue:
              type: integer
              minimum: 0
              description: Transactions with a received 999 whose selected IK5 or AK9 result was not cleanly accepted.
            x12AckOverdue:
              type: integer
              minimum: 0
              description: Eligible outbound transactions with neither a 997 nor a 999 received by their response deadline.
            technicalAckIssue:
              type: integer
              minimum: 0
              description: Outbound transactions whose requested TA1 rejected the interchange, reported errors, or could not be classified.
            technicalAckOverdue:
              type: integer
              minimum: 0
              description: Outbound transactions whose ISA14 requested a TA1 that was not received by its response deadline.
            as2MdnAttention:
              type: integer
              minimum: 0
              description: Outbound transactions whose AS2 MDN is overdue or was received with a warning, rejection, validation failure, or content-MIC mismatch.
            mappedOutputNotCollected:
              type: integer
              minimum: 0
              description: Transactions with at least one managed output that was not collected within the 15-minute pickup grace period.
            mappedOutputAckOverdue:
              type: integer
              minimum: 0
              description: Transactions with an expired unacknowledged output lease or an unacknowledged redelivery.
            watchlist:
              type: integer
              minimum: 0
              description: Transactions placed on an active operator watchlist independently of automated failure signals.
        freshness:
          $ref: '#/components/schemas/TransactionAttentionFreshness'
    TransactionAttentionFreshness:
      type: object
      required:
        - status
        - complete
        - lastCompletedAt
        - reconciliationStartedAt
        - message
      description: >
        Reconciliation state for the selected environment. Until the first
        complete sweep, attention-filtered or exact-status-filtered rows and
        counts can be partial or empty;
        `complete: false` means an empty result is not proof of zero. An
        incomplete or failed sweep does not clear previously observed active
        attention items.
      properties:
        status:
          type: string
          description: 'Reconciliation lifecycle: pending, actively reconciling, current, or stale.'
          enum:
            - pending
            - reconciling
            - current
            - stale
        complete:
          type: boolean
          description: >
            Whether the currently reported projection is complete and current.
            This is false while the first sweep is pending, while a refresh is
            reconciling, or when reconciliation is stale; previously observed
            active items remain visible during those states.
        lastCompletedAt:
          type: string
          format: date-time
          nullable: true
          description: UTC instant of the latest completed full attention sweep, or `null` before the first completion.
        reconciliationStartedAt:
          type: string
          format: date-time
          nullable: true
          description: UTC instant when the current reconciliation began, or `null` when no sweep is running.
        message:
          type: string
          nullable: true
          description: Safe operator-facing freshness or retry guidance; internal errors are not exposed.
    FilterableTransactionMappingStatus:
      type: string
      enum:
        - NOT_RECORDED
        - SUCCEEDED
        - FAILED
        - COMPLETED_WITH_ERRORS
        - RECOVERED
      description: >
        Durable consolidated mapping states available to exact list filtering.
        `UNAVAILABLE` is intentionally excluded because it describes a
        request-local telemetry read failure rather than an indexed transaction
        state.
    FilterableFunctionalAcknowledgmentStatus:
      type: string
      enum:
        - accepted
        - accepted_with_errors
        - partially_accepted
        - rejected
        - unknown
      description: >
        Closed set of normalized 997 statuses accepted by exact transaction-list
        filtering. Response models use a separate forward-compatible enum so a
        newer response status does not prevent an older SDK from reading the row.
    FilterableImplementationAcknowledgmentStatus:
      type: string
      enum:
        - accepted
        - accepted_with_errors
        - partially_accepted
        - rejected
        - unknown
      description: >
        Closed set of normalized 999 statuses accepted by exact transaction-list
        filtering. Response models use a separate forward-compatible enum so a
        newer response status does not prevent an older SDK from reading the row.
    FilterableTransactionMdnStatus:
      type: string
      enum:
        - pending
        - processed
        - warning
        - rejected
        - invalid
        - mic_mismatch
        - overdue
      description: >
        Closed set of normalized AS2 receipt-assurance statuses accepted by
        exact transaction-list filtering. Response models use a separate
        forward-compatible enum so a newer response status does not prevent an
        older SDK from reading the row.
    TransactionMappingStatusSummary:
      type: object
      required:
        - status
        - latestAttemptAt
        - failureCount
      properties:
        status:
          type: string
          enum:
            - NOT_RECORDED
            - UNAVAILABLE
            - SUCCEEDED
            - FAILED
            - COMPLETED_WITH_ERRORS
            - RECOVERED
          description: >
            Consolidated mapping outcome. `NOT_RECORDED` means no mapping runtime
            result was found; it does not claim that a map ran successfully.
            `UNAVAILABLE` means mapping telemetry could not be read while this
            response was built. It is fail-soft, has `failureCount: 0`, and does
            not by itself set `needsAttention`; retry before drawing a conclusion.
            `RECOVERED` means earlier failures were resolved by a later successful
            attempt. `COMPLETED_WITH_ERRORS` means at least one attempt succeeded
            while another failure remains unresolved.
        latestAttemptAt:
          type: string
          format: date-time
          nullable: true
          description: Timestamp of the latest mapping attempt or fallback post-process status.
        failureCount:
          type: integer
          minimum: 0
          description: Number of unresolved mapping failures for this transaction.
    TransactionMappingStatus:
      allOf:
        - $ref: '#/components/schemas/TransactionMappingStatusSummary'
        - type: object
          required:
            - attempts
          properties:
            attempts:
              type: array
              description: Mapping attempts in reverse chronological order. This is empty when only fallback post-process status is available.
              items:
                $ref: '#/components/schemas/TransactionMappingAttempt'
    TransactionMappingAttempt:
      description: One persisted mapping execution result with source revision, diagnostic location, replay linkage, and resolution state.
      type: object
      required:
        - correlationId
        - transactionReference
        - failureId
        - attemptId
        - transactionKey
        - direction
        - environment
        - currentRevision
        - stage
        - status
        - code
        - fallback
        - timestamp
        - resolved
      properties:
        correlationId:
          type: string
          description: >
            ModernEDI correlation id for the mapping operation. For a normal
            transaction-backed attempt this is the AS2 Message-Id. For a
            pre-transaction outbound failure it is an opaque request
            correlation id and must not be presented as an AS2 Message-Id.
        transactionReference:
          description: >
            Transaction that owns this attempt, or `null` when mapping failed
            before ModernEDI could create a transaction.
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/MappingRuntimeTransactionReference'
        failureId:
          type: string
          nullable: true
          description: >
            Opaque identifier for correlating and retrieving a failed attempt.
            This is `null` for successful attempts because the failure-detail
            endpoint intentionally exposes only retained failures.
        attemptId:
          type: string
          description: Opaque identifier for this individual mapping execution attempt.
        transactionKey:
          type: string
          description: >
            Source transaction key shown in the transaction viewer.
            Pre-transaction outbound failures use the sentinel
            `outbound-request`; internal mapping-attempt persistence keys are
            never exposed.
        direction:
          type: string
          description: Whether this attempt processed inbound X12 or generated outbound X12.
          enum: [inbound, outbound]
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        partnerName:
          type: string
          nullable: true
          description: Partner name captured at execution time, or `null` when attribution was unavailable.
        partnerId:
          type: integer
          nullable: true
          description: Stable workspace-scoped partner id, or `null` when the attempt could not be attributed.
        mappingId:
          type: integer
          nullable: true
          description: Workspace-scoped mapping id, or `null` when no published map was resolved.
        mapFile:
          type: string
          nullable: true
          description: Transform filename attempted, or `null` when selection failed before a file was resolved.
        mapFileSha256Hash:
          type: string
          nullable: true
          description: Base64 SHA-256 hash of the transform source actually attempted, or `null` when unavailable.
        currentMapFileSha256Hash:
          type: string
          nullable: true
          description: Base64 SHA-256 hash of the currently published source, or `null` when it cannot be resolved.
        currentRevision:
          type: boolean
          description: Whether the attempted map hash is still the currently published revision.
        transactionSetIdentifierCode:
          type: string
          nullable: true
          description: ST01 transaction-set identifier associated with the attempt, or `null` when unknown.
        transactionControlNumber:
          type: string
          nullable: true
          description: ST02 transaction control number associated with the attempt, or `null` when unknown.
        functionalIdentifierCode:
          type: string
          nullable: true
          description: GS01 functional identifier associated with the attempt, or `null` when unknown.
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: GS06 functional-group control number associated with the attempt, or `null` when unknown.
        x12Version:
          type: string
          nullable: true
          description: X12 implementation version used by the attempt, or `null` when unresolved.
        stage:
          type: string
          description: Mapping pipeline stage that produced the result.
        status:
          type: string
          description: Whether this individual mapping attempt succeeded or failed.
          enum: [FAILED, SUCCEEDED]
        code:
          type: string
          description: Stable machine-readable mapping result code.
        safeMessage:
          type: string
          nullable: true
          description: Sanitized diagnostic message safe to display to workspace operators.
        line:
          type: integer
          nullable: true
          description: One-based source line for a transform diagnostic, or `null` when no precise location exists.
        column:
          type: integer
          nullable: true
          description: One-based source column for a transform diagnostic, or `null` when no precise location exists.
        fallback:
          type: string
          description: Fallback behavior used after this attempt, or `NONE`.
        timestamp:
          type: string
          format: date-time
          description: UTC instant when this mapping attempt was recorded.
        replayId:
          type: string
          nullable: true
          description: Replay operation id that created this attempt, or `null` for ordinary processing.
        replayOfAttemptId:
          type: string
          nullable: true
          description: Original failed attempt targeted by this replay, or `null` when the attempt was not a replay.
        resolved:
          type: boolean
          description: Whether a later successful attempt has resolved this failure for operator-attention purposes.
        resolvedAt:
          type: string
          format: date-time
          nullable: true
          description: UTC instant when the failure was resolved, or `null` while unresolved or not applicable.
        resolvedByAttemptId:
          type: string
          nullable: true
          description: Successful attempt id that resolved this failure, or `null` while unresolved or not applicable.
    MappingRuntimeTransactionReference:
      type: object
      required:
        - messageId
        - transactionKey
      properties:
        messageId:
          type: string
          description: AS2 Message-Id of the retained transaction.
        transactionKey:
          type: string
          description: Transaction key, normally `GS06#ST02`.
    TransactionDetail:
      description: Metadata-first operator aggregate spanning mapping provenance, queue custody, normalized acknowledgments, a document index, and compact related-reply summaries.
      type: object
      required:
        - needsAttention
        - attentionReasons
        - mappingStatus
        - summary
        - mappedOutputs
        - mdn
        - functionalAck
        - implementationAck
        - technicalAck
        - documents
        - events
        - relatedTransactions
      properties:
        needsAttention:
          type: boolean
          description: >
            True when the transaction has an active operational watch, an
            unresolved mapping failure, or a 997 or 999 acknowledgment outcome
            other than `accepted`, when neither acknowledgment was received for an eligible
            outbound transaction by `x12AcknowledgmentExpectedBy`, when a requested
            TA1 rejected the interchange, reported errors, could not be classified,
            or was not received by `technicalAckExpectedBy`, when a managed output remained uncollected
            beyond its 15-minute pickup grace period, or when a delivered output was not
            acknowledged before its lease expired or was redelivered. A newly
            ready output inside the grace period and an active first lease are
            normal handoff progress and do not set this signal by themselves.
        attentionReasons:
          type: array
          uniqueItems: true
          description: Active machine-readable reasons behind `needsAttention`.
          items:
            $ref: '#/components/schemas/TransactionAttentionReason'
        mappingStatus:
          description: Complete mapping history and unresolved failure state for this transaction.
          $ref: '#/components/schemas/TransactionMappingStatus'
        summary:
          description: Stable transaction identity, partner, X12 envelope context, and list-level attention state.
          $ref: '#/components/schemas/TransactionSummary'
        mappedOutputs:
          type: array
          description: Metadata, mapping provenance, and managed-delivery state for inbound mapped outputs. Payload bodies are available through the document endpoints. Outbound reply transactions return an empty array.
          items:
            $ref: '#/components/schemas/StoredTransactionMappedOutput'
        mdn:
          type: object
          nullable: true
          description: Normalized AS2 receipt metadata without the report body. Fetch `mdn-report` from the document endpoint to inspect that body.
          allOf:
            - $ref: '#/components/schemas/TransactionMdn'
        functionalAck:
          type: object
          nullable: true
          description: Normalized X12 functional-acknowledgment metadata without the X12 body. Fetch `functional-ack-x12` from the document endpoint to inspect it.
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentDetail'
        implementationAck:
          type: object
          nullable: true
          description: Normalized X12 999 implementation-acknowledgment metadata without the X12 body. Fetch `implementation-ack-x12` from the document endpoint to inspect it.
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentDetail'
        technicalAck:
          type: object
          nullable: true
          description: Technical-acknowledgment transport metadata without X12 or HTTP response bodies, or `null` when none was recorded. Fetch the indexed document to inspect a body.
          allOf:
            - $ref: '#/components/schemas/TechnicalAcknowledgmentDetail'
        documents:
          type: array
          description: Metadata index of retained source, mapped-output, acknowledgment, and HTTP-response documents.
          items:
            $ref: '#/components/schemas/TransactionDocumentMetadata'
        events:
          type: array
          description: Chronological operational timeline derived from persisted transaction artifacts.
          items:
            $ref: '#/components/schemas/TransactionEvent'
        relatedTransactions:
          type: array
          description: Compact summaries of outbound replies linked to this inbound transaction. Fetch a selected reply's detail on demand.
          items:
            $ref: '#/components/schemas/TransactionSummary'
    TransactionSummary:
      description: Stable list-level transaction identity, partner context, acknowledgment state, and operator-attention projection.
      type: object
      required:
        - id
        - messageId
        - transactionKey
        - replyToMessageId
        - replyToTransactionKey
        - direction
        - partnerName
        - partnerId
        - partnerConfigurationSha256
        - timestamp
        - transactionSet
        - controlNumbers
        - edi
        - businessKey
        - environment
        - needsAttention
        - attentionReasons
        - onWatchlist
        - mappingStatus
        - functionalAckStatus
        - implementationAckStatus
        - mdnStatus
        - functionalAckOutcome
        - functionalAckTransactionOutcome
        - functionalAckGroupOutcome
        - functionalAckEvaluationScope
        - implementationAckOutcome
        - implementationAckTransactionOutcome
        - implementationAckEvaluationScope
        - x12AcknowledgmentExpectedBy
        - technicalAckRequested
        - technicalAckStatus
        - technicalAckExpectedBy
        - technicalAckOutcome
      properties:
        id:
          type: string
          description: Convenience id formatted as `<messageId>/<transactionKey>`.
          example: msg-850-api/17#0001
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        needsAttention:
          type: boolean
          description: >
            Stable operator-inbox signal. True when an unexpired watchlist entry
            is active, a mapping failure remains unresolved, or
            the 997 outcome selected by `functionalAckEvaluationScope` or the
            999 outcome selected by `implementationAckEvaluationScope` is
            present and is not `accepted`, or neither a 997 nor a 999 was
            received for an eligible outbound transaction by
            `x12AcknowledgmentExpectedBy`, or a requested TA1 rejected the interchange,
            reported errors, could not be classified, or was not received by
            `technicalAckExpectedBy`, or
            when a managed output remained uncollected beyond its 15-minute pickup
            grace period, or when a delivered output was not acknowledged before its
            lease expired or was redelivered. A newly ready output inside the
            grace period and an active first lease are normal handoff progress
            and do not set this signal by themselves.
        attentionReasons:
          type: array
          uniqueItems: true
          description: Active machine-readable reasons behind `needsAttention`.
          items:
            $ref: '#/components/schemas/TransactionAttentionReason'
        onWatchlist:
          type: boolean
          description: >
            True while an active watchlist entry exists for this transaction.
            Entries created through the Integration API remain active until
            `DELETE /v1/integration/transactions/{messageId}/{transactionKey}/watch`
            removes them. An active watch is also represented by the
            `watchlist` attention reason.
        mappingStatus:
          description: Consolidated mapping result and unresolved failure count for this transaction.
          $ref: '#/components/schemas/TransactionMappingStatusSummary'
        functionalAckStatus:
          type: string
          nullable: true
          enum:
            - accepted
            - accepted_with_errors
            - partially_accepted
            - rejected
            - unknown
          description: >
            Compact 997 status selected for this transaction. ModernEDI uses a
            uniquely matched AK2/AK5 outcome when possible, otherwise the
            uniquely matched AK1/AK9 functional-group outcome, and only then
            the conservative whole-997 aggregate. Null means no
            attributable 997 status is currently available. Use
            `x12_ack_overdue` for an actionable missing X12 acknowledgment.
        implementationAckStatus:
          oneOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
            - type: object
              nullable: true
              enum:
                - null
          description: >
            Compact 999 status selected for this transaction. ModernEDI uses a
            uniquely matched AK2/IK5 result when possible. Group fallback conservatively reduces the matching AK9
            status with every nested IK5 status, and whole-999 fallback reduces the aggregate with every flattened
            IK5 status. A non-accepted primary fallback remains authoritative. An accepted primary with any nested
            `unknown` becomes `unknown`; an accepted primary with any definitive non-clean nested result becomes
            `accepted_with_errors`, not the sibling's rejection or partial disposition. This prevents a raw accepted
            fallback from hiding a non-clean result or falsely assigning a sibling's disposition to this row, without
            changing the raw AK9 or IK5 fields. Null means no attributable 999 status is currently available.
        mdnStatus:
          type: string
          nullable: true
          enum:
            - pending
            - processed
            - warning
            - rejected
            - invalid
            - mic_mismatch
            - overdue
          description: >
            Compact normalized AS2 receipt-assurance status. Null means no MDN
            status applies or the asynchronous status projection has not
            indexed this row yet. Check `attentionSummary.freshness` on list
            responses before interpreting a null during projection bootstrap.
        messageId:
          type: string
          description: AS2 Message-Id for this transaction.
          example: msg-850-api
        transactionKey:
          type: string
          description: Transaction identifier within the AS2 message, usually `GS06#ST02`.
          example: 17#0001
        replyToMessageId:
          type: string
          nullable: true
          description: Present on outbound replies and points back to the inbound AS2 message id.
        replyToTransactionKey:
          type: string
          nullable: true
          description: >
            Exact inbound transaction key for an outbound reply, or `null` for
            a transaction that is not a reply. Related-transaction queries
            attach the reply only to this transaction inside
            `replyToMessageId`.
        direction:
          type: string
          description: 'Direction across the ModernEDI boundary: inbound from the partner or outbound to the partner.'
          enum:
            - inbound
            - outbound
          example: inbound
        partnerName:
          type: string
          description: Partner name captured for display; use `partnerId` for stable automation across renames.
          example: Customer One
        partnerId:
          type: integer
          nullable: true
          description: Persisted tenant-scoped partner id that authorizes this transaction and remains stable across partner renames.
          example: 1
        partnerConfigurationSha256:
          $ref: '#/components/schemas/PartnerConfigurationSha256'
        timestamp:
          $ref: '#/components/schemas/UtcTimestamp'
        transactionSet:
          description: ST01 code and reference description, with nullable fields when X12 metadata was unavailable.
          $ref: '#/components/schemas/TransactionSet'
        controlNumbers:
          description: ST02 and GS06 control numbers used to correlate the transaction with partner records.
          $ref: '#/components/schemas/TransactionControlNumbers'
        edi:
          description: X12 version, GS01/ST01 codes, and segment delimiter captured from the runtime.
          $ref: '#/components/schemas/TransactionEdiMetadata'
        businessKey:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TransactionBusinessKey'
          description: >
            Business key recorded on this transaction. Inbound keys come from
            the incoming map. Outbound keys are present when `/send`, `/reply`,
            or `/carbonCopy` supplied `businessKey` in the JSON request envelope;
            otherwise this is `null`.
        functionalAckOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentSummary'
          description: >
            Compact normalized whole-997 aggregate. Distinct AK1/AK9 groups are intentionally omitted from list
            responses; use `functionalAckGroupOutcome` for this row's selected compact group and transaction detail
            or the `functional-ack-x12` document metadata for every full group. A null value means no compact outcome was available, normally because
            no 997 is stored; list enrichment is fail-soft, so callers should use transaction detail before treating
            null as proof that no acknowledgment exists. Do not use the aggregate status as this row's status; use
            `functionalAckStatus` and `functionalAckEvaluationScope`.
        functionalAckTransactionOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
          description: >
            Exact AK2/AK5 result matched to this row by GS06/AK102 and
            ST02/AK202, with a leading-zero-insensitive control-number fallback
            only when it yields one unique match. Null means no unique
            transaction-set result could be attributed.
        functionalAckGroupOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentGroupSummary'
          description: >
            Exact AK1/AK9 group matched to this row by GS06/AK102 and GS01/AK101. Exact control-number identity is
            preferred; a leading-zero-insensitive fallback is used only when it yields one unique group. Null means
            no group was uniquely attributable. This row-level projection omits the group's nested AK2 results to keep
            list, reply, and event payloads bounded; fetch transaction detail for the complete group tree.
        functionalAckEvaluationScope:
          type: string
          nullable: true
          enum:
            - transaction_set
            - functional_group
            - functional_acknowledgment
          description: >
            Outcome level ModernEDI used for `functional_ack_issue`.
            `transaction_set` uses a unique AK2/AK5 disposition while retaining the matching AK9 group separately.
            `functional_group` is used when AK2 is omitted or no unique transaction result exists.
            `functional_acknowledgment` is the conservative whole-997 fallback only when no AK1 group can be matched
            uniquely. Null means no 997 outcome was available.
        implementationAckOutcome:
          oneOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentSummary'
            - type: object
              nullable: true
              enum:
                - null
          description: >
            Compact normalized whole-999 result plus distinct AK1/AK9 group
            outcomes. A null value normally means no 999 is stored. This
            remains the acknowledgment-wide context even when ModernEDI can
            evaluate this row against a narrower group or transaction result.
        implementationAckTransactionOutcome:
          oneOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
            - type: object
              nullable: true
              enum:
                - null
          description: >
            Exact AK2/IK5 result matched uniquely to this row by the
            functional-group and transaction-set identifiers. Null means no
            unique transaction-set result could be attributed.
        implementationAckEvaluationScope:
          oneOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentEvaluationScope'
            - type: object
              nullable: true
              enum:
                - null
          description: >
            Outcome level ModernEDI used for `implementation_ack_issue`.
            `transaction_set` selects a unique AK2/IK5 result;
            `implementation_group` selects a unique AK1/AK9 group and conservatively reduces it with nested IK5 statuses;
            `implementation_acknowledgment` conservatively reduces the aggregate with all flattened IK5 statuses
            when no unique group is attributable. Null means no 999
            outcome was available.
        x12AcknowledgmentExpectedBy:
          type: string
          format: date-time
          nullable: true
          description: >
            Deadline used to classify a still-missing partner X12 acknowledgment for an eligible
            outbound business transaction. Outbound 997 and 999 acknowledgment
            documents are excluded. Receipt of either a correlated 997 or 999
            satisfies the deadline. This is null when no deadline applies. Use
            the `x12_ack_overdue` attention reason, not this timestamp
            alone, as the authoritative active overdue signal. ModernEDI does
            not automatically resend the original X12 when the deadline passes.
        technicalAckRequested:
          type: boolean
          description: True when the outbound ISA14 requested a TA1 interchange acknowledgment. False for inbound traffic, outbound interchanges that did not request TA1, and legacy rows that predate this persisted signal.
        technicalAckStatus:
          $ref: '#/components/schemas/TechnicalAcknowledgmentStatus'
          description: Current TA1 lifecycle for this transaction. `pending` and `overdue` apply only when `technicalAckRequested` is true; `not_requested` means no deadline applies.
        technicalAckExpectedBy:
          type: string
          format: date-time
          nullable: true
          description: Deadline for a TA1 explicitly requested by outbound ISA14, or `null` when none was requested. Use `technical_ack_overdue` as the authoritative active overdue signal. ModernEDI does not automatically resend when this deadline passes.
        technicalAckOutcome:
          oneOf:
            - $ref: '#/components/schemas/TechnicalAcknowledgmentOutcome'
            - type: object
              nullable: true
              enum:
                - null
          description: Parsed TA1 outcome correlated by the original AS2 message id, or `null` while a requested TA1 is still pending or when none was requested.
    TransactionSet:
      description: X12 transaction-set identity captured from ST01 and the reference catalog.
      type: object
      properties:
        code:
          type: string
          nullable: true
          description: ST01 transaction-set identifier, or `null` when the runtime did not record one.
          example: '850'
        description:
          type: string
          nullable: true
          description: Human-readable ST01 document name, or `null` when the code is unavailable or unknown.
          example: Purchase Order
    TransactionControlNumbers:
      type: object
      properties:
        transaction:
          type: string
          nullable: true
          description: ST02 transaction control number.
          example: '0001'
        functionalGroup:
          type: string
          nullable: true
          description: GS06 functional group control number.
          example: '17'
    TransactionEdiMetadata:
      description: X12 envelope and delimiter context captured for a transaction.
      type: object
      properties:
        x12Version:
          type: string
          nullable: true
          description: Numeric X12 implementation version, or `null` when it was not recorded.
          example: '4010'
        functionalIdentifierCode:
          type: string
          nullable: true
          description: GS01 functional identifier code, or `null` when it was not recorded.
          example: PO
        transactionGroupType:
          type: string
          nullable: true
          description: ST01 transaction set identifier code recorded by the runtime.
          example: '850'
        segmentTerminator:
          type: string
          nullable: true
          description: Single-character segment terminator detected from the interchange, or `null` when unavailable.
          example: '~'
    TransactionBusinessKey:
      description: Customer-defined searchable transaction identifier used for reconciliation.
      type: object
      properties:
        name:
          type: string
          nullable: true
          description: Stable customer-facing identifier label, or `null` for older records that stored only a value.
          example: purchaseOrderNumber
        value:
          type: string
          description: Extracted or caller-supplied scalar identifier value stored as text.
          example: PO-100045
    TransactionMappedOutputMetadata:
      description: Metadata and map provenance for an application-facing document produced by an incoming map.
      type: object
      required:
        - id
        - sequenceNumber
        - purpose
      properties:
        id:
          type: string
          description: >
            Artifact identifier within the transaction response, such as
            `mapped-output-1`. This is not the managed-queue id and cannot be
            used with `/v1/mapped-outputs/{id}/ack`. Stored transaction details
            expose the queue correlation id separately as `delivery.outputId`.
          example: mapped-output-1
        sequenceNumber:
          type: integer
          description: One-based display order of this output within the transaction response.
          example: 1
        purpose:
          $ref: '#/components/schemas/MappingPurpose'
        contentType:
          type: string
          nullable: true
          description: Media type of the corresponding mapped-output document body, or `null` for historical artifacts without recorded content type.
          example: application/json
        createdAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        businessKey:
          type: object
          nullable: true
          description: Map-derived reconciliation identifier, or `null` when the map did not produce one.
          allOf:
            - $ref: '#/components/schemas/TransactionBusinessKey'
        mapping:
          description: Map identity and source-revision comparison for this persisted output.
          $ref: '#/components/schemas/TransactionMappedOutputMapping'
        extraFields:
          type: object
          description: Runtime routing metadata captured with the output; this is not the map's selectable delivered context.
          additionalProperties:
            type: string
    TransactionMappedOutput:
      description: Complete response-only replay output, including the regenerated body.
      allOf:
        - $ref: '#/components/schemas/TransactionMappedOutputMetadata'
        - type: object
          required:
            - payload
          properties:
            payload:
              type: string
              nullable: true
              description: Mapped output body. Parse according to `contentType`.
    StoredTransactionMappedOutput:
      description: >
        Metadata for a mapped output persisted on a transaction detail. Unlike
        a response-only replay output, it omits the body and always includes
        delivery applicability and current handoff state. Fetch its indexed
        document to obtain the payload.
      allOf:
        - $ref: '#/components/schemas/TransactionMappedOutputMetadata'
        - type: object
          required:
            - delivery
          properties:
            delivery:
              $ref: '#/components/schemas/TransactionMappedOutputDelivery'
    TransactionMappedOutputDelivery:
      type: object
      description: >
        Handoff state for a mapped output stored on a transaction. This object
        is present on stored transaction-detail mapped outputs and omitted from
        response-only replay results, which do not enter the managed queue.
        `acknowledged` means acknowledged by your integration through the queue
        acknowledgment API or a successful mapped-output webhook; it does not
        prove how another application handled the document afterward.
      required:
        - applicability
        - status
        - availableAt
        - handoffIssue
        - attentionSince
        - outputId
        - deliveryCount
        - redelivered
        - firstDeliveredAt
        - lastDeliveredAt
        - leasedUntil
        - ackedAt
      properties:
        applicability:
          type: string
          enum:
            - managed_queue
            - not_applicable
          description: >
            `managed_queue` exposes a current polling/webhook state;
            `not_applicable` is a transaction-record-only artifact.
        status:
          type: string
          nullable: true
          enum:
            - ready
            - leased
            - acknowledged
          description: >
            Current managed-queue state, or null when applicability is not
            `managed_queue`. `ready` includes a never-leased output and an output
            whose prior lease expired. `leased` means the visibility timeout is
            still active. `acknowledged` means acknowledged by your integration.
        availableAt:
          description: >
            UTC instant when this generated output version became available for
            polling or webhook delivery. A durable replay creates a new output
            version with a new availability instant.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
        handoffIssue:
          type: string
          nullable: true
          enum:
            - not_collected
            - acknowledgment_overdue
            - redelivered
          description: >
            Current actionable managed-output handoff issue, or null while the
            output is progressing normally, acknowledged, or not managed by the
            queue. `not_collected` means no first delivery lease was issued before
            the 15-minute pickup grace period expired. `acknowledgment_overdue` means the
            first lease expired without acknowledgment. `redelivered` means more
            than one delivery lease was issued without a later acknowledgment.
        attentionSince:
          description: >
            UTC instant when the current `handoffIssue` became actionable, or null
            when no handoff issue is active. For `not_collected`, this is 15 minutes
            after `availableAt`; for an overdue acknowledgment it is the
            first lease expiry; for a redelivery it is the most recent transition
            into the redelivered state.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
        outputId:
          type: string
          nullable: true
          description: >
            Managed-queue correlation id for this generated output, or null when
            queue tracking does not apply. It is distinct from the mapped output's
            top-level transaction artifact `id`. It stays stable across ordinary
            processing retries that reproduce the same logical output. A successful
            durable replay creates a new id even when the regenerated content is
            identical. Acknowledgment still requires the latest `receiptHandle`
            returned by `GET /v1/mapped-outputs`; transaction detail does not provide
            that receipt handle.
        deliveryCount:
          type: integer
          minimum: 0
          nullable: true
          description: >
            Number of times the output has been leased for pull or webhook delivery
            attempts, or null when queue tracking does not apply. This count does
            not imply successful downstream processing.
        redelivered:
          type: boolean
          nullable: true
          description: True after more than one lease or delivery attempt; independent of the current status.
        firstDeliveredAt:
          description: UTC instant when the output was first leased for a pull or webhook delivery attempt.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
        lastDeliveredAt:
          description: UTC instant when the output was most recently leased for a pull or webhook delivery attempt.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
        leasedUntil:
          description: UTC instant when the current visibility lease expires, or null when no lease has been issued.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
        ackedAt:
          description: >
            UTC instant when ModernEDI recorded acknowledgment by the customer's
            integration or a successful webhook response. This does not prove
            later ERP or business processing.
          allOf:
            - $ref: '#/components/schemas/NullableUtcTimestamp'
    TransactionMappedOutputMapping:
      description: Mapping identity and revision comparison recorded with a transaction's persisted output.
      type: object
      required:
        - versionStatus
      properties:
        id:
          type: integer
          nullable: true
          description: Workspace-scoped mapping id, or `null` when historical provenance is incomplete.
          example: 44
        type:
          type: string
          nullable: true
          description: Runtime mapping implementation name, or `null` when historical provenance is incomplete.
          example: ManagedQueueMapping
        file:
          type: string
          nullable: true
          description: Transform filename used to create the output, or `null` when not recorded.
          example: customer-one-850.jslt
        fileSha256Hash:
          type: string
          nullable: true
          description: Base64-encoded SHA-256 hash of the map file used when the inbound output was produced.
        currentFileSha256Hash:
          type: string
          nullable: true
          description: Base64-encoded SHA-256 hash of the currently published map file, when it can be resolved.
        versionStatus:
          type: string
          description: Whether the producing source is current, changed, missing, or cannot be compared.
          enum:
            - current
            - changed
            - missing
            - unknown
          example: current
        syntaxTreeCatalogRevision:
          type: string
          nullable: true
          pattern: '^[0-9a-f]{64}$'
          description: Immutable grammar-catalog revision declared by the producing mapping execution; `null` for legacy records.
        syntaxTreeSha256:
          type: string
          nullable: true
          pattern: '^[0-9a-f]{64}$'
          description: SHA-256 of the exact transaction-set grammar bytes used by the producing mapping execution; `null` for legacy records.
    MappingPurpose:
      type: string
      description: >
        Purpose of the runtime map that produced this output. `PROCESSING` means the output is for the normal
        application workflow. `ACKNOWLEDGMENT` means the output is an automatically generated response document.
      enum:
        - PROCESSING
        - ACKNOWLEDGMENT
      example: PROCESSING
    TransactionMdnStatus:
      type: string
      enum:
        - pending
        - processed
        - warning
        - rejected
        - invalid
        - mic_mismatch
        - overdue
      description: >
        Normalized AS2 receipt-assurance status. Only `processed` is a clean
        completed receipt; `pending` is still within the response window and
        every other state requires operator review.
    PartnerConfigurationSha256:
      type: string
      nullable: true
      pattern: '^[0-9a-f]{64}$'
      description: >
        Lowercase SHA-256 of the exact partner runtime configuration recorded
        for this transaction, receipt, or acknowledgment. It is `null` for
        legacy rows written before configuration stamping. Scenario
        verification accepts persisted evidence only when this value exactly
        matches the partner configuration frozen into the applied binding.
      example: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
    TransactionMdn:
      type: object
      required:
        - messageId
        - disposition
        - sent
        - timestamp
        - status
        - asynchronous
        - micMatched
        - receivedContentMic
        - expectedContentMic
        - expectedMicAlgorithm
        - expectedBy
        - validationError
        - partnerConfigurationSha256
      description: >
        AS2 message disposition notification (MDN) metadata without its report
        body. For an outbound
        document ModernEDI normally requests an asynchronous signed receipt.
        While that receipt is outstanding this object has `status: pending`;
        it becomes `overdue` after the platform response deadline, which defaults
        to one hour after send. A received
        receipt is accepted as `processed` only after its Original-Message-ID,
        requested MIC algorithm, returned MIC, and disposition are validated.
        Review `as2_mdn_attention` before resending; ModernEDI does not resend
        automatically because an invalid or missing receipt does not prove the
        partner failed to process the document.
      properties:
        messageId:
          type: string
          nullable: true
          example: mdn-850-api
          description: Message-ID of the MDN itself. Null while an asynchronous receipt is still pending or overdue.
        disposition:
          type: string
          nullable: true
          example: processed
          description: Raw AS2 Disposition field returned by the partner. Use normalized `status` for automation and retain this value for partner troubleshooting.
        sent:
          type: boolean
          nullable: true
          description: True when ModernEDI sent this MDN for an inbound document; false when it received or is awaiting the partner's MDN for an outbound document.
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: Stored MDN timestamp used by the event timeline.
        status:
          $ref: '#/components/schemas/TransactionMdnStatus'
        asynchronous:
          type: boolean
          nullable: true
          description: True when the receipt was requested or delivered through the asynchronous Receipt-Delivery-Option callback rather than the original HTTP response.
        micMatched:
          type: boolean
          nullable: true
          description: Whether the partner's Received-content-MIC digest and algorithm matched the canonical content ModernEDI sent. Null while pending or when comparison was not possible.
        receivedContentMic:
          type: string
          nullable: true
          description: Partner-supplied Received-content-MIC value, including its algorithm token when present.
        expectedContentMic:
          type: string
          nullable: true
          description: Base64 digest ModernEDI calculated over the exact canonical MIME content sent to the partner.
        expectedMicAlgorithm:
          type: string
          nullable: true
          description: Receipt MIC algorithm ModernEDI requested from the partner; currently `sha1` for compatibility with legacy partner connections.
        expectedBy:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: Deadline for a still-pending asynchronous receipt. Null after a receipt is recorded or when no reliable send timestamp is available.
        validationError:
          type: string
          nullable: true
          description: Specific validation or partner-disposition problem that caused `warning`, `rejected`, `invalid`, or `mic_mismatch`.
        partnerConfigurationSha256:
          $ref: '#/components/schemas/PartnerConfigurationSha256'
    FunctionalAcknowledgmentDetail:
      type: object
      description: Metadata and normalized outcome for a stored X12 997. Fetch the indexed functional-acknowledgment document for the X12 body.
      required:
        - messageId
        - sent
        - timestamp
        - partnerConfigurationSha256
        - mdn
        - outcome
        - evaluationScope
        - groupOutcome
        - transactionOutcome
        - evaluatedStatus
      properties:
        messageId:
          type: string
          nullable: true
          description: AS2 Message-Id of the stored 997, or `null` when only partial acknowledgment data was retained.
          example: fa-850-api
        sent:
          type: boolean
          nullable: true
          description: Delivery/persistence completion flag from the retained 997 record. True means its acknowledgment lifecycle completed, false means it did not, and `null` means the state is unavailable. This is not sender direction; use the transaction direction and timeline event type to determine whether ModernEDI sent or received the 997.
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: Stored functional-acknowledgment timestamp used by the event timeline.
        partnerConfigurationSha256:
          $ref: '#/components/schemas/PartnerConfigurationSha256'
        mdn:
          type: object
          nullable: true
          description: AS2 receipt assurance state, or `null` when no MDN applies or was recorded.
          allOf:
            - $ref: '#/components/schemas/TransactionMdn'
        outcome:
          $ref: '#/components/schemas/FunctionalAcknowledgmentOutcome'
        evaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, functional_group, functional_acknowledgment]
          description: Whether this transaction was evaluated against its exact AK2/AK5 result, its uniquely matched AK1/AK9 group, or the whole-997 aggregate because no group was uniquely attributable.
        groupOutcome:
          type: object
          nullable: true
          description: Unique AK1/AK9 group outcome attributable to this transaction, or `null` when group identity is absent or ambiguous.
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentGroupOutcome'
        transactionOutcome:
          type: object
          nullable: true
          description: Exact AK2/AK5 outcome attributable to this transaction, or `null`.
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
        evaluatedStatus:
          type: string
          nullable: true
          description: Status selected for this transaction at `evaluationScope`, or `null` when no evaluation was available.
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
    FunctionalAcknowledgmentOutcome:
      type: object
      description: >
        Normalized whole-997 aggregate. The aggregate does not collapse the distinct AK1/AK9 group results or
        AK2/AK5 transaction-set results. `groups` preserves every AK101/AK102 identity, its AK901 disposition,
        its AK902-AK904 counts, and nested AK5 outcomes. A contradictory AK5/count rollup is reported as unknown
        rather than trusting an internally inconsistent 997. Whenever `status` is `unknown`, inspect `unknownReason` and fetch the
        `functional-ack-x12` document when the original body is needed. A false
        `parsed` value indicates a structural failure; an unsupported AK901, AK501, or syntax-error
        code can be structurally parsed while its status remains unknown. The `unsupported_acknowledgment_code`
        reason does not by itself prove that AK901 was unsupported. Only `accepted` is a clean automation completion.
        `accepted_with_errors` and `unknown` require review; `partially_accepted` and `rejected` are failure or
        rejection outcomes that require action.
      required:
        - status
        - acknowledgmentCode
        - summary
        - parsed
        - unknownReason
        - includedTransactionSets
        - receivedTransactionSets
        - acceptedTransactionSets
        - errorCodes
        - groups
        - transactionSets
      properties:
        status:
          $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Common original AK901 code when every parsed group has the same code; otherwise `null`.
          example: A
        summary:
          type: string
          description: Human-readable whole-997 aggregate result; transaction-scoped displays should use `evaluatedStatus` and the selected group or transaction outcome.
          example: Functional group accepted; 1 of 1 received transaction set was accepted.
        parsed:
          type: boolean
          description: True when AK9 and all three AK902-AK904 counts were structurally valid.
        unknownReason:
          type: string
          nullable: true
          description: Machine-readable reason when `status` is `unknown`.
          enum:
            - missing_x12
            - not_997
            - invalid_structure
            - missing_ak9
            - invalid_ak9
            - unsupported_acknowledgment_code
            - inconsistent_rollup
        includedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Sum of AK902 across every parsed group, or `null` when any group count is unavailable or the sum overflows.
        receivedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Sum of AK903 across every parsed group, or `null` when any group count is unavailable or the sum overflows.
        acceptedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Sum of AK904 across every parsed group, or `null` when any group count is unavailable or the sum overflows.
        errorCodes:
          type: array
          description: De-duplicated union of non-empty AK905 and later functional-group syntax error codes across every parsed group.
          items:
            type: string
        groups:
          type: array
          description: Distinct AK1/AK9 functional-group outcomes in source order; no sibling group is collapsed into another.
          items:
            $ref: '#/components/schemas/FunctionalAcknowledgmentGroupOutcome'
        transactionSets:
          type: array
          description: >
            Transaction-set results from paired AK2 and AK5 segments. Each result repeats its parent AK101/AK102
            identity so flattened results remain attributable when an interchange contains multiple 997 groups.
          items:
            $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
    FunctionalAcknowledgmentGroupOutcome:
      type: object
      required:
        - functionalIdentifierCode
        - functionalGroupControlNumber
        - functionalGroupVersion
        - status
        - acknowledgmentCode
        - includedTransactionSets
        - receivedTransactionSets
        - acceptedTransactionSets
        - errorCodes
        - transactionSets
      properties:
        functionalIdentifierCode:
          type: string
          nullable: true
          description: AK101 functional identifier code for the acknowledged group, such as `PO` or `IN`.
          example: PO
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: AK102 control number for the acknowledged functional group.
          example: '17'
        functionalGroupVersion:
          type: string
          nullable: true
          description: Raw AK103 functional-group version, or `null` when the sender omitted it; ModernEDI does not infer an implementation guide.
          example: '004060'
        status:
          $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Original AK901 acknowledgment code for this functional group, when available.
          example: A
        includedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK902, the number of transaction sets included in this functional group.
        receivedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK903, the number of transaction sets received in this functional group.
        acceptedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK904, the number of received transaction sets accepted in this functional group. This count is not an AK5 transaction disposition.
        errorCodes:
          type: array
          description: Non-empty AK905 and later functional-group syntax error codes.
          items:
            type: string
        transactionSets:
          type: array
          description: AK2/AK5 outcomes belonging to this exact AK1/AK9 group. Empty when AK2 was omitted.
          items:
            $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
    FunctionalAcknowledgmentGroupSummary:
      type: object
      description: Compact AK1/AK9 group selected for one transaction row; nested AK2 results are intentionally omitted.
      required:
        - functionalIdentifierCode
        - functionalGroupControlNumber
        - functionalGroupVersion
        - status
        - acknowledgmentCode
        - includedTransactionSets
        - receivedTransactionSets
        - acceptedTransactionSets
        - errorCodes
      properties:
        functionalIdentifierCode:
          type: string
          nullable: true
          description: AK101 functional identifier code for the acknowledged group.
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: AK102 control number for the acknowledged functional group.
        functionalGroupVersion:
          type: string
          nullable: true
          description: Raw AK103 functional-group version, or `null` when omitted.
        status:
          $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Original AK901 acknowledgment code for this functional group.
        includedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK902 for this functional group.
        receivedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK903 for this functional group.
        acceptedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK904 for this functional group; this count is distinct from an AK5 disposition.
        errorCodes:
          type: array
          description: Non-empty AK905 and later functional-group syntax error codes.
          items:
            type: string
    FunctionalAcknowledgmentTransactionSetOutcome:
      type: object
      required:
        - functionalIdentifierCode
        - functionalGroupControlNumber
        - transactionSetIdentifierCode
        - transactionSetControlNumber
        - implementationConventionReference
        - status
        - acknowledgmentCode
        - errorCodes
      properties:
        functionalIdentifierCode:
          type: string
          nullable: true
          description: AK101 functional identifier code for the acknowledged group, such as `PO` or `IN`.
          example: PO
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: AK102 control number for the acknowledged functional group.
          example: '17'
        transactionSetIdentifierCode:
          type: string
          nullable: true
          description: AK201 transaction set identifier code, such as `850` or `810`.
          example: '850'
        transactionSetControlNumber:
          type: string
          nullable: true
          description: AK202 transaction set control number.
          example: '0001'
        implementationConventionReference:
          type: string
          nullable: true
          description: Raw AK203 implementation convention reference, or `null` when the sender omitted it; it is retained without claiming implementation-guide certification.
          example: '005010UCS'
        status:
          $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: >
            Original AK501 transaction-set acknowledgment code, when available. This raw code is preserved independently
            from `status`: AK501 `A` normalizes to `accepted_with_errors` when its AK2 loop reports AK3/AK4 detail or
            non-empty AK502 and later syntax-error codes. Only a normalized `accepted` status is clean.
          example: A
        errorCodes:
          type: array
          description: Non-empty AK502 and later transaction-set syntax error codes.
          items:
            type: string
    FunctionalAcknowledgmentSummary:
      type: object
      description: >
        Compact whole-997 aggregate included on transaction summaries for list-level monitoring. Full AK1/AK9 and
        AK2/AK5 trees are reserved for detail; use the row's separate `functionalAckGroupOutcome` and
        `functionalAckTransactionOutcome` projections for attribution. Only `accepted` is a
        clean automation completion. `accepted_with_errors` and `unknown` require review; `partially_accepted`
        and `rejected` are failure or rejection outcomes that require action.
      required:
        - status
        - acknowledgmentCode
        - summary
      properties:
        status:
          $ref: '#/components/schemas/FunctionalAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Original AK901 functional-group acknowledgment code, when available.
          example: A
        summary:
          type: string
          description: Human-readable whole-997 aggregate result.
          example: Functional group accepted; 1 of 1 received transaction set was accepted.
    FunctionalAcknowledgmentStatus:
      type: string
      description: >
        Stable normalized acknowledgment status used for group and transaction-set results. This is not a direct alias
        for AK901 or AK501; in particular, an AK501 `A` with AK3/AK4 or AK502 and later error detail is
        `accepted_with_errors`, while the raw `acknowledgmentCode` remains `A`.
      enum:
        - accepted
        - accepted_with_errors
        - partially_accepted
        - rejected
        - unknown
      example: accepted
    ImplementationAcknowledgmentDetail:
      type: object
      description: Metadata and normalized outcome for a stored X12 999. Fetch the indexed implementation-acknowledgment document for the X12 body.
      required:
        - messageId
        - sent
        - timestamp
        - partnerConfigurationSha256
        - mdn
        - outcome
        - evaluationScope
        - transactionOutcome
        - evaluatedStatus
      properties:
        messageId:
          type: string
          nullable: true
          description: AS2 Message-Id of the stored 999, or `null` when only partial acknowledgment data was retained.
          example: implementation-ack-850-api
        sent:
          type: boolean
          nullable: true
          description: Delivery/persistence completion flag from the retained 999 record. True means its acknowledgment lifecycle completed, false means it did not, and `null` means the state is unavailable. This is not sender direction; use the transaction direction and timeline event type to determine whether ModernEDI sent or received the 999.
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: Stored implementation-acknowledgment timestamp used by the event timeline.
        partnerConfigurationSha256:
          $ref: '#/components/schemas/PartnerConfigurationSha256'
        mdn:
          type: object
          nullable: true
          description: AS2 receipt assurance state for the 999, or `null` when no MDN applies or was recorded.
          allOf:
            - $ref: '#/components/schemas/TransactionMdn'
        outcome:
          $ref: '#/components/schemas/ImplementationAcknowledgmentOutcome'
        evaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, implementation_group, implementation_acknowledgment]
          description: Whether this transaction was evaluated against its exact AK2/IK5 result, a unique AK1/AK9 group, or the conservative whole-999 aggregate.
        transactionOutcome:
          type: object
          nullable: true
          description: Exact AK2/IK5 outcome attributable to this transaction, or `null`.
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
        evaluatedStatus:
          type: string
          nullable: true
          description: Status selected for this transaction at `evaluationScope`, or `null` when no evaluation was available.
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
    ImplementationAcknowledgmentOutcome:
      type: object
      description: >
        Normalized X12 999 result. The aggregate status does not collapse the
        distinct AK1/AK9 group results or AK2/IK5 transaction-set results.
        `groups` preserves each AK101/AK102/AK103 identity and its AK9 rollup;
        `transactionSets` provides the same IK5 results as one attributable
        flat list. A 999 reports X12 syntax and relational validation. It does
        not indicate semantic or business acceptance, and it is not HIPAA
        implementation-guide certification.
        Only `accepted` is a clean automation completion.
      required:
        - status
        - acknowledgmentCode
        - summary
        - parsed
        - unknownReason
        - includedTransactionSets
        - receivedTransactionSets
        - acceptedTransactionSets
        - errorCodes
        - groups
        - transactionSets
      properties:
        status:
          $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Aggregate acknowledgment code when one value represents the whole 999, or `null` for mixed or unavailable group results.
          example: A
        summary:
          type: string
          description: Human-readable aggregate result suitable for a transaction timeline or status panel.
          example: Implementation acknowledgment accepted; 1 of 1 received transaction set was accepted.
        parsed:
          type: boolean
          description: True when the 999 structure and required AK9 rollups were parsed successfully.
        unknownReason:
          type: string
          nullable: true
          description: Machine-readable reason when `status` is `unknown`.
          enum:
            - missing_x12
            - not_999
            - invalid_structure
            - missing_ak9
            - invalid_ak9
            - unsupported_acknowledgment_code
            - inconsistent_rollup
        includedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Aggregate count of transaction sets included across the acknowledged groups, when available.
        receivedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Aggregate count of transaction sets received across the acknowledged groups, when available.
        acceptedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: Aggregate count of received transaction sets accepted across the acknowledged groups, when available.
        errorCodes:
          type: array
          description: Distinct non-empty syntax error codes reported by the 999.
          items:
            type: string
        groups:
          type: array
          description: Distinct AK1/AK9 implementation-group outcomes in source order.
          items:
            $ref: '#/components/schemas/ImplementationAcknowledgmentGroupOutcome'
        transactionSets:
          type: array
          description: Flattened AK2/IK5 transaction-set outcomes; each result repeats its parent AK101/AK102 identity for attribution.
          items:
            $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
    ImplementationAcknowledgmentGroupOutcome:
      type: object
      required:
        - functionalIdentifierCode
        - functionalGroupControlNumber
        - functionalGroupVersion
        - status
        - acknowledgmentCode
        - includedTransactionSets
        - receivedTransactionSets
        - acceptedTransactionSets
        - errorCodes
        - transactionSets
      properties:
        functionalIdentifierCode:
          type: string
          nullable: true
          description: AK101 functional identifier code for the acknowledged group, such as `PO` or `IN`.
          example: PO
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: AK102 control number for the acknowledged functional group.
          example: '17'
        functionalGroupVersion:
          type: string
          nullable: true
          description: AK103 version or implementation-convention reference echoed from the acknowledged group.
          example: 005010
        status:
          $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Original AK901 acknowledgment code for this implementation group, when available.
          example: A
        includedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK902, the number of transaction sets included in this functional group.
        receivedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK903, the number of transaction sets received in this functional group.
        acceptedTransactionSets:
          type: integer
          minimum: 0
          nullable: true
          description: AK904, the number of received transaction sets accepted in this functional group.
        errorCodes:
          type: array
          description: Non-empty AK905 and later implementation-group syntax error codes.
          items:
            type: string
        transactionSets:
          type: array
          description: AK2/IK5 results belonging to this AK1/AK9 group.
          items:
            $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
    ImplementationAcknowledgmentTransactionSetOutcome:
      type: object
      required:
        - functionalIdentifierCode
        - functionalGroupControlNumber
        - transactionSetIdentifierCode
        - transactionSetControlNumber
        - implementationConventionReference
        - status
        - acknowledgmentCode
        - errorCodes
      properties:
        functionalIdentifierCode:
          type: string
          nullable: true
          description: AK101 functional identifier code for the acknowledged group, such as `PO` or `IN`.
          example: PO
        functionalGroupControlNumber:
          type: string
          nullable: true
          description: AK102 control number for the acknowledged functional group.
          example: '17'
        transactionSetIdentifierCode:
          type: string
          nullable: true
          description: AK201 transaction-set identifier code, such as `850` or `810`.
          example: '850'
        transactionSetControlNumber:
          type: string
          nullable: true
          description: AK202 transaction-set control number.
          example: '0001'
        implementationConventionReference:
          type: string
          nullable: true
          description: Raw AK203 implementation-convention reference echoed from the acknowledged ST03, or `null` when absent.
          example: 005010X222A1
        status:
          $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: >
            Original IK501 transaction-set acknowledgment code, when available. This raw code is preserved separately
            from normalized `status`; bare IK501 `A` is inconsistent and normalizes to `unknown` when its AK2 loop also
            reports IK3/IK4 error detail.
          example: A
        errorCodes:
          type: array
          description: Non-empty IK502 and later transaction-set syntax error codes.
          items:
            type: string
    ImplementationAcknowledgmentSummary:
      type: object
      description: Compact 999 aggregate and group results included on transaction summaries for list-level monitoring.
      required:
        - status
        - acknowledgmentCode
        - summary
        - groups
      properties:
        status:
          $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
        acknowledgmentCode:
          type: string
          nullable: true
          description: Aggregate acknowledgment code when one value represents the whole 999, or `null` for mixed or unavailable group results.
          example: A
        summary:
          type: string
          description: Human-readable aggregate 999 result.
          example: Implementation acknowledgment accepted; 1 of 1 received transaction set was accepted.
        groups:
          type: array
          description: Compact response retains each AK1/AK9 group so transactions can be evaluated without collapsing sibling groups.
          items:
            $ref: '#/components/schemas/ImplementationAcknowledgmentGroupOutcome'
    ImplementationAcknowledgmentStatus:
      type: string
      description: >
        Stable normalized 999 acknowledgment status used for aggregate, group, and transaction-set results. Raw IK501
        `A` is not clean when its AK2 loop contains IK3/IK4 error detail; that contradictory result is `unknown`.
      enum:
        - accepted
        - accepted_with_errors
        - partially_accepted
        - rejected
        - unknown
      example: accepted
    ImplementationAcknowledgmentEvaluationScope:
      type: string
      description: >
        Outcome level selected for one transaction from a correlated 999. Group and acknowledgment fallbacks use the
        documented primary-aware conservative reduction with nested IK5 statuses; raw AK9 and IK5 objects are unchanged.
      enum:
        - transaction_set
        - implementation_group
        - implementation_acknowledgment
    TechnicalAcknowledgmentStatus:
      type: string
      description: Stable requested-TA1 lifecycle and normalized TA104 outcome.
      enum:
        - not_requested
        - pending
        - received
        - received_with_errors
        - rejected
        - unknown
        - overdue
      example: received
    TechnicalAcknowledgmentOutcome:
      type: object
      description: Parsed TA1 interchange-level result. Only `received` is a clean outcome; every other received status requires operator review.
      required:
        - status
        - acknowledgmentCode
        - errorCode
        - acknowledgedInterchangeControlNumber
        - summary
        - parsed
        - unknownReason
      properties:
        status:
          type: string
          enum: [received, received_with_errors, rejected, unknown]
          description: Normalized TA104 result. `A` becomes `received`, `E` becomes `received_with_errors`, and `R` becomes `rejected`.
        acknowledgmentCode:
          type: string
          nullable: true
          description: Raw TA104 interchange acknowledgment code (`A`, `E`, or `R`) when available.
          example: A
        errorCode:
          type: string
          nullable: true
          description: Raw TA105 interchange note/error code. Interpret it with the partner's X12 implementation guidance; `000` normally accompanies a clean acceptance.
          example: '000'
        acknowledgedInterchangeControlNumber:
          type: string
          nullable: true
          description: TA101 control number identifying the original ISA13 interchange acknowledged by this TA1.
          example: '000000017'
        summary:
          type: string
          description: Customer-readable interpretation of the TA104 outcome.
        parsed:
          type: boolean
          description: True when ModernEDI found a structurally usable TA1 segment and recognized TA104.
        unknownReason:
          type: string
          nullable: true
          enum: [missing_x12, invalid_structure, missing_ta1, unsupported_acknowledgment_code]
          description: Stable reason `status` is `unknown`, or `null` for a recognized outcome.
    TechnicalAcknowledgmentDetail:
      description: Metadata for a stored X12 technical acknowledgment or downstream HTTP response. Fetch the indexed document for the body.
      type: object
      required:
        - sent
        - timestamp
        - responseStatusCode
        - partnerConfigurationSha256
        - outcome
      properties:
        sent:
          type: boolean
          nullable: true
          description: True when ModernEDI sent the technical acknowledgment; false when it received one; `null` when unknown.
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        responseStatusCode:
          type: integer
          nullable: true
          description: Downstream HTTP response status code, or `null` when no raw transport response was retained.
          example: 200
        partnerConfigurationSha256:
          $ref: '#/components/schemas/PartnerConfigurationSha256'
        outcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TechnicalAcknowledgmentOutcome'
          description: Parsed TA1 result, or `null` when the retained technical-acknowledgment record has no TA1 X12 body.
    TransactionDocument:
      description: >
        One complete retained transaction artifact returned only by the
        individual document endpoint. Its `content` body is required.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentMetadata'
        - type: object
          required:
            - content
          properties:
            content:
              type: string
              description: Untrusted document body. Parse according to `contentType` and escape or sandbox it when rendering.
    TransactionDocumentMetadata:
      description: >
        Metadata for one retained transaction artifact. `type` selects the
        renderer and concrete `metadata` schema. The MDN shapes are further
        distinguished by stable `id`: `mdn-report` contains receipt-assurance
        metadata, while `functional-ack-mdn-report` and
        `implementation-ack-mdn-report` contain the Message-Id and disposition
        of the 997's or 999's own MDN. Document indexes never include
        `content`.
      oneOf:
        - $ref: '#/components/schemas/TransactionX12Document'
        - $ref: '#/components/schemas/TransactionMappedOutputDocument'
        - $ref: '#/components/schemas/TransactionMdnDocument'
        - $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentDocument'
        - $ref: '#/components/schemas/TransactionImplementationAcknowledgmentDocument'
        - $ref: '#/components/schemas/TransactionTechnicalAcknowledgmentDocument'
        - $ref: '#/components/schemas/TransactionHttpResponseDocument'
      discriminator:
        propertyName: type
        mapping:
          x12: '#/components/schemas/TransactionX12Document'
          mapped_output: '#/components/schemas/TransactionMappedOutputDocument'
          mdn: '#/components/schemas/TransactionMdnDocument'
          functional_ack: '#/components/schemas/TransactionFunctionalAcknowledgmentDocument'
          implementation_ack: '#/components/schemas/TransactionImplementationAcknowledgmentDocument'
          technical_ack: '#/components/schemas/TransactionTechnicalAcknowledgmentDocument'
          http_response: '#/components/schemas/TransactionHttpResponseDocument'
    TransactionDocumentBase:
      type: object
      required:
        - id
        - type
        - label
        - contentType
        - encoding
        - timestamp
        - contentLength
        - metadata
      properties:
        id:
          type: string
          description: Stable artifact identifier within this transaction response, not a queue acknowledgment id.
          example: raw-x12
        type:
          type: string
          description: Machine-readable artifact category used to choose rendering and operator controls.
        label:
          type: string
          description: Customer-readable artifact name suitable for a transaction document list.
          example: Inbound X12
        contentType:
          type: string
          description: Media type describing how to parse or display `content`.
          example: application/edi-x12
        encoding:
          type: string
          description: Representation of `content`; currently all public transaction documents are returned as text.
          enum:
            - text
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        contentLength:
          type: integer
          description: Length of the retained text artifact; use it as display context and to decide whether to fetch, not as a checksum.
          example: 256
        metadata:
          type: object
          description: Structured metadata whose concrete schema is selected by `type` and, for MDNs, `id`.
    TransactionX12Document:
      description: Raw inbound or outbound X12 transaction document.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [raw-x12]
              description: Stable id of the retained raw X12 artifact.
            type:
              type: string
              enum: [x12]
              description: Selects the raw-X12 document renderer and empty metadata shape.
            metadata:
              $ref: '#/components/schemas/EmptyTransactionDocumentMetadata'
    TransactionMappedOutputDocument:
      description: Application-facing output produced by an inbound mapping.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              pattern: '^mapped-output-[1-9]\d*$'
              example: mapped-output-1
              description: Stable transaction-local artifact id derived from the mapped-output sequence number.
            type:
              type: string
              enum: [mapped_output]
              description: Selects the mapped-output renderer and map-provenance metadata shape.
            metadata:
              $ref: '#/components/schemas/TransactionMappedOutputDocumentMetadata'
    TransactionMdnDocument:
      description: >
        AS2 MDN report. Inspect `id` to distinguish the original transaction's
        full MDN metadata from compact MDN metadata attached to a 997 or 999.
      oneOf:
        - $ref: '#/components/schemas/TransactionPrimaryMdnDocument'
        - $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnDocument'
        - $ref: '#/components/schemas/TransactionImplementationAcknowledgmentMdnDocument'
    TransactionPrimaryMdnDocument:
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [mdn-report]
              description: Stable id of the original transaction's full MDN report.
            type:
              type: string
              enum: [mdn]
              description: Selects an AS2 MDN report renderer; this id selects full receipt-assurance metadata.
            metadata:
              $ref: '#/components/schemas/TransactionMdnDocumentMetadata'
    TransactionFunctionalAcknowledgmentMdnDocument:
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [functional-ack-mdn-report]
              description: Stable id of the MDN report attached to the X12 997.
            type:
              type: string
              enum: [mdn]
              description: Selects an AS2 MDN report renderer; this id selects compact 997-MDN metadata.
            metadata:
              $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnMetadata'
    TransactionImplementationAcknowledgmentMdnDocument:
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [implementation-ack-mdn-report]
              description: Stable id of the MDN report attached to the X12 999.
            type:
              type: string
              enum: [mdn]
              description: Selects an AS2 MDN report renderer; this id selects compact 999-MDN metadata.
            metadata:
              $ref: '#/components/schemas/TransactionImplementationAcknowledgmentMdnMetadata'
    TransactionFunctionalAcknowledgmentDocument:
      description: Stored X12 997 and its normalized group and transaction-set evaluation.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [functional-ack-x12]
              description: Stable id of the stored X12 997 artifact.
            type:
              type: string
              enum: [functional_ack]
              description: Selects the X12 997 renderer and normalized acknowledgment metadata shape.
            metadata:
              $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentDocumentMetadata'
    TransactionImplementationAcknowledgmentDocument:
      description: Stored X12 999 and its normalized acknowledgment, group, and transaction-set evaluation.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [implementation-ack-x12]
              description: Stable id of the stored X12 999 artifact.
            type:
              type: string
              enum: [implementation_ack]
              description: Selects the X12 999 renderer and normalized acknowledgment metadata shape.
            metadata:
              $ref: '#/components/schemas/TransactionImplementationAcknowledgmentDocumentMetadata'
    TransactionTechnicalAcknowledgmentDocument:
      description: Stored X12 technical acknowledgment.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [technical-ack-x12]
              description: Stable id of the stored X12 technical-acknowledgment artifact.
            type:
              type: string
              enum: [technical_ack]
              description: Selects the X12 technical-acknowledgment renderer and transport metadata shape.
            metadata:
              $ref: '#/components/schemas/TransactionTechnicalAcknowledgmentDocumentMetadata'
    TransactionHttpResponseDocument:
      description: Raw HTTP response retained with a technical acknowledgment.
      allOf:
        - $ref: '#/components/schemas/TransactionDocumentBase'
        - type: object
          properties:
            id:
              type: string
              enum: [technical-ack-response]
              description: Stable id of the raw HTTP response retained with a technical acknowledgment.
            type:
              type: string
              enum: [http_response]
              description: Selects the plain-text HTTP-response renderer and transport metadata shape.
            metadata:
              $ref: '#/components/schemas/TransactionTechnicalAcknowledgmentDocumentMetadata'
    EmptyTransactionDocumentMetadata:
      type: object
      description: Raw X12 has no additional document metadata; transaction identity is available on the enclosing detail.
      maxProperties: 0
      additionalProperties: false
    TransactionMappedOutputDocumentMetadata:
      description: >
        The persisted mapped-output identity and map provenance. It omits both
        the body and managed-queue delivery state; fetch this document for its
        content and read `transaction.mappedOutputs[]` or mapped-output timeline
        events for current custody.
      allOf:
        - $ref: '#/components/schemas/TransactionMappedOutputMetadata'
        - type: object
          required:
            - id
            - sequenceNumber
            - purpose
            - contentType
            - createdAt
            - businessKey
            - mapping
            - extraFields
    TransactionMdnDocumentMetadata:
      type: object
      description: Full receipt-assurance metadata for the original transaction's MDN report.
      required:
        - messageId
        - disposition
        - status
        - asynchronous
        - micMatched
        - receivedContentMic
        - expectedContentMic
        - expectedMicAlgorithm
        - expectedBy
        - validationError
      properties:
        messageId:
          type: string
          nullable: true
          description: Message-ID of the MDN itself, or `null` while an asynchronous receipt is pending.
        disposition:
          type: string
          nullable: true
          description: Raw AS2 Disposition value returned by the partner.
        status:
          type: string
          enum: [pending, processed, warning, rejected, invalid, mic_mismatch, overdue]
          description: Normalized receipt-assurance outcome; only `processed` is a clean final success.
        asynchronous:
          type: boolean
          nullable: true
          description: Whether the receipt used the asynchronous Receipt-Delivery-Option callback.
        micMatched:
          type: boolean
          nullable: true
          description: Whether the returned MIC matched the canonical content ModernEDI sent.
        receivedContentMic:
          type: string
          nullable: true
          description: Partner-supplied Received-content-MIC value.
        expectedContentMic:
          type: string
          nullable: true
          description: Digest ModernEDI calculated over the sent canonical MIME content.
        expectedMicAlgorithm:
          type: string
          nullable: true
          description: MIC algorithm ModernEDI requested.
        expectedBy:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        validationError:
          type: string
          nullable: true
          description: Specific receipt validation or disposition problem, or `null`.
    TransactionFunctionalAcknowledgmentDocumentMetadata:
      type: object
      description: Normalized X12 997 outcome and the evaluation selected for the enclosing transaction.
      required:
        - messageId
        - sent
        - outcome
        - evaluationScope
        - groupOutcome
        - transactionOutcome
        - evaluatedStatus
      properties:
        messageId:
          type: string
          nullable: true
          description: AS2 Message-Id of the stored 997.
        sent:
          type: boolean
          nullable: true
          description: Delivery/persistence completion flag from the retained 997 record, or `null` when unavailable. It does not identify sender direction; use the transaction direction and timeline event type.
        outcome:
          $ref: '#/components/schemas/FunctionalAcknowledgmentOutcome'
        evaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, functional_group, functional_acknowledgment]
          description: Whether the enclosing transaction was evaluated from its exact AK2/AK5 result, uniquely matched AK1/AK9 group, or whole-997 ambiguity fallback.
        groupOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentGroupOutcome'
          description: Exact AK1/AK9 group selected for the enclosing transaction, or `null` when no group was uniquely attributable.
        transactionOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
          description: Exact AK2/AK5 result selected for the enclosing transaction, or `null`.
        evaluatedStatus:
          type: string
          nullable: true
          enum: [accepted, accepted_with_errors, partially_accepted, rejected, unknown]
          description: Status selected by `evaluationScope`, or `null` when no outcome was attributable.
    TransactionImplementationAcknowledgmentDocumentMetadata:
      type: object
      description: Normalized X12 999 outcome and the evaluation selected for the enclosing transaction.
      required:
        - messageId
        - sent
        - outcome
        - evaluationScope
        - transactionOutcome
        - evaluatedStatus
      properties:
        messageId:
          type: string
          nullable: true
          description: AS2 Message-Id of the stored 999.
        sent:
          type: boolean
          nullable: true
          description: Delivery/persistence completion flag from the retained 999 record, or `null` when unavailable. It does not identify sender direction; use the transaction direction and timeline event type.
        outcome:
          $ref: '#/components/schemas/ImplementationAcknowledgmentOutcome'
        evaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, implementation_group, implementation_acknowledgment]
          description: Whether the enclosing transaction was evaluated from its exact IK5 result, a unique AK9 group result, or the conservative whole-999 aggregate.
        transactionOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
          description: Exact AK2/IK5 result selected for the enclosing transaction, or `null`.
        evaluatedStatus:
          type: string
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentStatus'
          description: Status selected by `evaluationScope`, or `null` when no outcome was attributable.
    TransactionFunctionalAcknowledgmentMdnMetadata:
      type: object
      description: Message identity and raw disposition of the AS2 MDN attached to a 997.
      required:
        - messageId
        - disposition
      properties:
        messageId:
          type: string
          nullable: true
          description: Message-ID of the MDN attached to the 997.
        disposition:
          type: string
          nullable: true
          description: Raw disposition of the MDN attached to the 997.
    TransactionImplementationAcknowledgmentMdnMetadata:
      type: object
      description: Message identity and raw disposition of the AS2 MDN attached to a 999.
      required:
        - messageId
        - disposition
      properties:
        messageId:
          type: string
          nullable: true
          description: Message-ID of the MDN attached to the 999.
        disposition:
          type: string
          nullable: true
          description: Raw disposition of the MDN attached to the 999.
    TransactionTechnicalAcknowledgmentDocumentMetadata:
      type: object
      description: Send or receive direction and retained HTTP status for a technical acknowledgment.
      required:
        - sent
        - responseStatusCode
        - outcome
      properties:
        sent:
          type: boolean
          nullable: true
          description: True when ModernEDI sent the technical acknowledgment; false when it received one.
        responseStatusCode:
          type: integer
          nullable: true
          description: Retained downstream HTTP status, or `null`.
        outcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TechnicalAcknowledgmentOutcome'
          description: Parsed TA1 result, or `null` when this artifact is only a retained HTTP response without TA1 X12.
    TransactionTechnicalAcknowledgmentEventDetails:
      type: object
      description: Direction and normalized outcome fields for one sent or received TA1 timeline event.
      required:
        - sent
        - responseStatusCode
        - status
        - acknowledgmentCode
        - errorCode
      properties:
        sent:
          type: boolean
          nullable: true
          description: True when ModernEDI sent the TA1; false when it received one.
        responseStatusCode:
          type: integer
          nullable: true
          description: Retained downstream HTTP status, or `null`.
        status:
          type: string
          nullable: true
          enum: [received, received_with_errors, rejected, unknown]
          description: Normalized TA104 outcome, or `null` when no TA1 payload was available to parse.
        acknowledgmentCode:
          type: string
          nullable: true
          description: Raw TA104 code, or `null`.
        errorCode:
          type: string
          nullable: true
          description: Raw TA105 code, or `null`.
    TransactionEvent:
      description: >
        One derived operator-timeline entry. `type` is a discriminator for the
        stable `details` payload; clients do not need to infer fields from
        `label` or reverse-engineer examples.
      oneOf:
        - $ref: '#/components/schemas/TransactionLifecycleEvent'
        - $ref: '#/components/schemas/TransactionMappedOutputEvent'
        - $ref: '#/components/schemas/TransactionMappingEvent'
        - $ref: '#/components/schemas/TransactionMdnEvent'
        - $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentEvent'
        - $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnEvent'
        - $ref: '#/components/schemas/TransactionImplementationAcknowledgmentEvent'
        - $ref: '#/components/schemas/TransactionImplementationAcknowledgmentMdnEvent'
        - $ref: '#/components/schemas/TransactionTechnicalAcknowledgmentEvent'
      discriminator:
        propertyName: type
        mapping:
          transaction.received: '#/components/schemas/TransactionLifecycleEvent'
          transaction.sent: '#/components/schemas/TransactionLifecycleEvent'
          reply.sent: '#/components/schemas/TransactionLifecycleEvent'
          mapped_output.created: '#/components/schemas/TransactionMappedOutputEvent'
          mapped_output.available: '#/components/schemas/TransactionMappedOutputEvent'
          mapped_output.delivered: '#/components/schemas/TransactionMappedOutputEvent'
          mapped_output.redelivered: '#/components/schemas/TransactionMappedOutputEvent'
          mapped_output.attention_required: '#/components/schemas/TransactionMappedOutputEvent'
          mapped_output.acknowledged: '#/components/schemas/TransactionMappedOutputEvent'
          mapping.failed: '#/components/schemas/TransactionMappingEvent'
          mapping.succeeded: '#/components/schemas/TransactionMappingEvent'
          mapping.recovered: '#/components/schemas/TransactionMappingEvent'
          mdn.pending: '#/components/schemas/TransactionMdnEvent'
          mdn.overdue: '#/components/schemas/TransactionMdnEvent'
          mdn.sent: '#/components/schemas/TransactionMdnEvent'
          mdn.received: '#/components/schemas/TransactionMdnEvent'
          functional_ack.sent: '#/components/schemas/TransactionFunctionalAcknowledgmentEvent'
          functional_ack.received: '#/components/schemas/TransactionFunctionalAcknowledgmentEvent'
          functional_ack.mdn_sent: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnEvent'
          functional_ack.mdn_received: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnEvent'
          implementation_ack.sent: '#/components/schemas/TransactionImplementationAcknowledgmentEvent'
          implementation_ack.received: '#/components/schemas/TransactionImplementationAcknowledgmentEvent'
          implementation_ack.mdn_sent: '#/components/schemas/TransactionImplementationAcknowledgmentMdnEvent'
          implementation_ack.mdn_received: '#/components/schemas/TransactionImplementationAcknowledgmentMdnEvent'
          technical_ack.sent: '#/components/schemas/TransactionTechnicalAcknowledgmentEvent'
          technical_ack.received: '#/components/schemas/TransactionTechnicalAcknowledgmentEvent'
    TransactionEventBase:
      type: object
      required:
        - id
        - type
        - label
        - timestamp
        - details
      properties:
        id:
          type: string
          description: Stable event identifier within this transaction timeline.
          example: transaction
        type:
          type: string
          description: Machine-readable discriminator for the concrete `details` schema.
        label:
          type: string
          description: Customer-readable event title suitable for an operator timeline.
          example: Transaction received
        timestamp:
          $ref: '#/components/schemas/NullableUtcTimestamp'
          description: Stored timestamp for the underlying transaction, mapping, MDN, or acknowledgment.
        details:
          type: object
          description: Event-specific structured context selected by `type`.
    TransactionLifecycleEvent:
      description: Initial transaction activity or an outbound reply linked to the selected transaction.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [transaction.received, transaction.sent, reply.sent]
              description: Distinguishes the original inbound/outbound transaction from a linked outbound reply.
            details:
              $ref: '#/components/schemas/TransactionTimelineSummary'
    TransactionMappedOutputEvent:
      description: Creation or managed-delivery lifecycle of one mapped output.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum:
                - mapped_output.created
                - mapped_output.available
                - mapped_output.delivered
                - mapped_output.redelivered
                - mapped_output.attention_required
                - mapped_output.acknowledged
              description: Identifies the exact creation or managed-delivery transition represented by this event.
            details:
              $ref: '#/components/schemas/StoredTransactionMappedOutput'
    TransactionMappingEvent:
      description: Failed, successful, or recovered mapping execution.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [mapping.failed, mapping.succeeded, mapping.recovered]
              description: Identifies whether the attempt failed, succeeded, or resolved an earlier failure.
            details:
              $ref: '#/components/schemas/TransactionMappingAttempt'
    TransactionMdnEvent:
      description: AS2 receipt waiting, overdue, sent, or received state.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [mdn.pending, mdn.overdue, mdn.sent, mdn.received]
              description: Identifies the waiting, overdue, sent, or received AS2 receipt transition.
            details:
              $ref: '#/components/schemas/TransactionMdnEventDetails'
    TransactionFunctionalAcknowledgmentEvent:
      description: X12 997 sent or received with the exact outcome selected for this transaction.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [functional_ack.sent, functional_ack.received]
              description: Indicates whether ModernEDI sent or received the X12 997.
            details:
              $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentEventDetails'
    TransactionFunctionalAcknowledgmentMdnEvent:
      description: MDN sent or received for the X12 997 itself.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [functional_ack.mdn_sent, functional_ack.mdn_received]
              description: Indicates whether ModernEDI sent or received the MDN for the X12 997.
            details:
              $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentMdnMetadata'
    TransactionImplementationAcknowledgmentEvent:
      description: X12 999 sent or received with the exact outcome selected for this transaction.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [implementation_ack.sent, implementation_ack.received]
              description: Indicates whether ModernEDI sent or received the X12 999.
            details:
              $ref: '#/components/schemas/TransactionImplementationAcknowledgmentEventDetails'
    TransactionImplementationAcknowledgmentMdnEvent:
      description: MDN sent or received for the X12 999 itself.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [implementation_ack.mdn_sent, implementation_ack.mdn_received]
              description: Indicates whether ModernEDI sent or received the MDN for the X12 999.
            details:
              $ref: '#/components/schemas/TransactionImplementationAcknowledgmentMdnMetadata'
    TransactionTechnicalAcknowledgmentEvent:
      description: X12 technical acknowledgment sent or received.
      allOf:
        - $ref: '#/components/schemas/TransactionEventBase'
        - type: object
          properties:
            type:
              type: string
              enum: [technical_ack.sent, technical_ack.received]
              description: Indicates whether ModernEDI sent or received the X12 technical acknowledgment.
            details:
              $ref: '#/components/schemas/TransactionTechnicalAcknowledgmentEventDetails'
    TransactionTimelineSummary:
      description: >
        Stable transaction identity used inside transaction and reply timeline
        events. It intentionally omits the current attention and mapping
        projections; refetch transaction detail for authoritative current state.
      type: object
      required:
        - id
        - environment
        - messageId
        - transactionKey
        - replyToMessageId
        - replyToTransactionKey
        - direction
        - partnerName
        - partnerId
        - timestamp
        - transactionSet
        - controlNumbers
        - edi
        - businessKey
        - functionalAckOutcome
        - functionalAckTransactionOutcome
        - functionalAckGroupOutcome
        - functionalAckEvaluationScope
        - implementationAckOutcome
        - implementationAckTransactionOutcome
        - implementationAckEvaluationScope
        - x12AcknowledgmentExpectedBy
        - technicalAckRequested
        - technicalAckStatus
        - technicalAckExpectedBy
        - technicalAckOutcome
      properties:
        id:
          type: string
          description: Convenience id formatted as `<messageId>/<transactionKey>`.
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        messageId:
          type: string
          description: AS2 Message-Id that identifies the transaction for detail and correlation requests.
        transactionKey:
          type: string
          description: Transaction identifier within the AS2 message, usually `GS06#ST02`.
        replyToMessageId:
          type: string
          nullable: true
          description: Source inbound message for an outbound reply, or `null`.
        replyToTransactionKey:
          type: string
          nullable: true
          description: Exact source transaction for an outbound reply, or `null` for a non-reply.
        direction:
          type: string
          enum: [inbound, outbound]
          description: Direction across the ModernEDI boundary at the time this timeline snapshot was created.
        partnerName:
          type: string
          description: Partner name captured at processing time.
        partnerId:
          type: integer
          nullable: true
          description: Stable tenant-scoped partner id.
        timestamp:
          $ref: '#/components/schemas/UtcTimestamp'
        transactionSet:
          $ref: '#/components/schemas/TransactionSet'
        controlNumbers:
          $ref: '#/components/schemas/TransactionControlNumbers'
          description: ST02 and GS06 control numbers used for partner-side correlation.
        edi:
          $ref: '#/components/schemas/TransactionEdiMetadata'
        businessKey:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/TransactionBusinessKey'
        functionalAckOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentSummary'
        functionalAckTransactionOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentTransactionSetOutcome'
          description: Exact AK2/AK5 outcome uniquely attributable to this transaction, or `null`.
        functionalAckGroupOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/FunctionalAcknowledgmentGroupSummary'
          description: Compact AK1/AK9 group outcome uniquely attributable to this transaction, or `null`.
        functionalAckEvaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, functional_group, functional_acknowledgment]
          description: Whether operator status used the exact transaction-set result, the matching group, or the whole-997 ambiguity fallback.
        implementationAckOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentSummary'
          description: Compact aggregate and group-level 999 context, or `null` when no 999 was attributable.
        implementationAckTransactionOutcome:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ImplementationAcknowledgmentTransactionSetOutcome'
          description: Exact AK2/IK5 outcome uniquely attributable to this transaction, or `null`.
        implementationAckEvaluationScope:
          type: string
          nullable: true
          enum: [transaction_set, implementation_group, implementation_acknowledgment]
          description: Whether operator status used the exact IK5 result, a unique AK9 group result, or the conservative whole-999 aggregate.
        x12AcknowledgmentExpectedBy:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        technicalAckRequested:
          type: boolean
          description: Whether outbound ISA14 requested a TA1 for this timeline snapshot.
        technicalAckStatus:
          $ref: '#/components/schemas/TechnicalAcknowledgmentStatus'
        technicalAckExpectedBy:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        technicalAckOutcome:
          description: >
            Parsed TA1 outcome correlated to the interchange represented by
            this timeline snapshot, or `null` while no TA1 is available. Use
            `technicalAckStatus` and the `technical_ack_overdue` attention
            reason to distinguish not requested, pending, and overdue states;
            a null outcome alone is not evidence that the partner accepted the
            interchange.
          oneOf:
            - $ref: '#/components/schemas/TechnicalAcknowledgmentOutcome'
            - type: object
              nullable: true
              enum:
                - null
    TransactionMdnEventDetails:
      type: object
      description: Safe normalized AS2 receipt diagnostics used by MDN timeline events.
      required:
        - messageId
        - disposition
        - status
        - asynchronous
        - micMatched
        - expectedBy
        - validationError
      properties:
        messageId:
          type: string
          nullable: true
          description: Message-ID of the MDN itself.
        disposition:
          type: string
          nullable: true
          description: Raw AS2 Disposition value.
        status:
          type: string
          enum: [pending, processed, warning, rejected, invalid, mic_mismatch, overdue]
          description: Normalized receipt-assurance state that determines the event type.
        asynchronous:
          type: boolean
          nullable: true
          description: Whether the receipt used the asynchronous Receipt-Delivery-Option callback.
        micMatched:
          type: boolean
          nullable: true
          description: Whether the returned MIC matched the sent canonical content.
        expectedBy:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        validationError:
          type: string
          nullable: true
          description: Receipt validation or disposition problem, or `null`.
    TransactionFunctionalAcknowledgmentEventDetails:
      allOf:
        - $ref: '#/components/schemas/TransactionFunctionalAcknowledgmentDocumentMetadata'
    TransactionImplementationAcknowledgmentEventDetails:
      allOf:
        - $ref: '#/components/schemas/TransactionImplementationAcknowledgmentDocumentMetadata'
    TransactionEnvironmentValue:
      type: string
      description: Isolated transaction and queue environment used for this response object.
      enum:
        - production
        - test
      example: production
    UtcTimestamp:
      type: string
      format: date-time
      pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{9}Z$'
      description: UTC RFC 3339 instant with exactly nine fractional digits and a trailing `Z`.
      example: '2026-07-15T18:30:00.000000000Z'
    NullableUtcTimestamp:
      type: string
      format: date-time
      pattern: '^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{9}Z$'
      nullable: true
      description: UTC RFC 3339 instant with exactly nine fractional digits and a trailing `Z`, or `null`.
      example: '2026-07-15T18:30:00.000000000Z'
    TransactionReplayRequest:
      type: object
      additionalProperties: false
      properties:
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        mode:
          type: string
          enum:
            - current_maps
          default: current_maps
          description: Uses the mappings currently published for the partner. This is the only public replay mode.
        delivery:
          type: string
          enum:
            - response_only
          default: response_only
          description: Regenerated outputs are returned only; no queue item, webhook, or outbound acknowledgment is produced.
        reason:
          type: string
          maxLength: 500
          nullable: true
          description: Optional operator or automation context recorded on the replay attempt.
    TransactionReplayResponse:
      description: Atomic response-only replay result using the mappings currently published for the partner.
      type: object
      required:
        - success
        - replay
        - regeneratedOutputs
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; replay validation or execution failures use the replay error response.
        replay:
          description: Durable audit record for the replay request, execution status, and requester.
          $ref: '#/components/schemas/TransactionReplay'
        regeneratedOutputs:
          type: array
          description: Newly generated map results. They are not enqueued and do not trigger mapped-output webhooks.
          items:
            $ref: '#/components/schemas/TransactionMappedOutput'
    TransactionReplay:
      description: Persisted audit and lifecycle state for one transaction replay.
      type: object
      required:
        - id
        - status
        - environment
        - messageId
        - transactionKey
        - mode
        - delivery
        - reason
        - requestedByApiKeyId
        - attempts
        - requestedAt
        - startedAt
        - completedAt
        - error
      properties:
        id:
          type: string
          format: uuid
          description: Globally unique replay identifier used to correlate regenerated mapping attempts.
        status:
          type: string
          description: Current replay lifecycle; a synchronous success normally returns `succeeded`.
          enum:
            - succeeded
            - processing
            - failed
        environment:
          $ref: '#/components/schemas/TransactionEnvironmentValue'
        messageId:
          type: string
          description: Source inbound AS2 Message-Id replayed by this operation.
        transactionKey:
          type: string
          description: Source transaction key within the message replayed by this operation.
        mode:
          type: string
          description: Mapping revision policy; public replays always use the maps currently published.
          enum:
            - current_maps
        delivery:
          type: string
          description: Delivery boundary; public replay outputs are returned in the response and never queued or pushed.
          enum:
            - response_only
        reason:
          type: string
          nullable: true
          description: Caller-supplied operator context, or `null` when no reason was provided.
        requestedByApiKeyId:
          type: integer
          minimum: 1
          description: Internal id of the scoped Integration API key that requested the replay.
        attempts:
          type: integer
          minimum: 1
          description: Number of replay execution attempts recorded for this request.
        requestedAt:
          $ref: '#/components/schemas/UtcTimestamp'
        startedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        completedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        error:
          type: object
          nullable: true
          description: Safe terminal replay failure details, or `null` when no execution failure was recorded.
          properties:
            code:
              type: string
              nullable: true
              description: Stable replay failure code, or `null` when no specific code was captured.
            message:
              type: string
              nullable: true
              description: Safe operator-facing replay failure explanation, or `null` when unavailable.
    MappedOutputWebhookUpdateRequest:
      type: object
      additionalProperties: false
      required:
        - enabled
      properties:
        enabled:
          type: boolean
          description: Enables or disables push delivery for this partner. Disabling retains the stored endpoint and signing secret for later use; re-enabling still requires `endpointUrl` in this request.
        endpointUrl:
          type: string
          format: uri
          maxLength: 2000
          nullable: true
          description: Required when `enabled` is true. Must be an absolute HTTPS URL without user information or a fragment and use a publicly routable host. DNS is revalidated before every delivery.
          example: https://erp.example.com/webhooks/modernedi
        rotateSigningSecret:
          type: boolean
          default: false
          description: When true on an enabled webhook, replaces the signing secret and returns the new plaintext value once. Enabling a webhook without an existing secret creates one even when this is false.
    MappedOutputWebhookUpdateResponse:
      description: Successful mapped-output webhook configuration update.
      type: object
      required:
        - success
        - webhook
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; endpoint validation or configuration conflicts use an error response.
        webhook:
          description: Current webhook status, plus a one-time plaintext secret only when created or rotated.
          $ref: '#/components/schemas/MappedOutputWebhookStatus'
        plainTextSigningSecret:
          type: string
          description: Present only when a signing secret was created or rotated. It is never returned again.
          example: medo_whsec_qQ2h3zvT1vD1Vh0CG0q2gQ
        message:
          type: string
          description: Present with `plainTextSigningSecret` to remind the caller to save it.
    MappedOutputWebhookTestResponse:
      description: Result of one synthetic webhook connectivity attempt. This response never represents or changes a real mapped output.
      type: object
      required:
        - success
        - synthetic
        - event
        - deliveryId
        - requestId
        - attemptedAt
        - attempted
        - delivered
        - statusCode
        - error
      properties:
        success:
          type: boolean
          enum: [true]
          description: The ModernEDI test operation completed. This does not mean the destination accepted the event; inspect `delivered`.
        synthetic:
          type: boolean
          enum: [true]
          description: Always true so this result cannot be mistaken for production mapped-output delivery.
        event:
          type: string
          enum: [mapped_output.test]
          description: Synthetic event name sent in both the signed body and `X-ModernEDI-Event` header.
        deliveryId:
          type: string
          description: Synthetic `test_`-prefixed delivery correlation id. It is not a mapped-output queue id or receipt handle.
        requestId:
          type: string
          description: Request correlation id returned in `X-Request-Id` and included in the signed synthetic event.
        attemptedAt:
          $ref: '#/components/schemas/UtcTimestamp'
        attempted:
          type: boolean
          enum: [true]
          description: Always true because ModernEDI invoked the validated delivery path. A null `statusCode` means the path failed before an HTTP response was received.
        delivered:
          type: boolean
          description: >
            True only when the destination returned HTTP 2xx. A `200` from this
            ModernEDI API operation can still contain `delivered: false`.
        statusCode:
          type: integer
          nullable: true
          description: >
            Destination HTTP status, or null when public-address validation,
            DNS, connection, TLS, or timeout failure prevented an HTTP response.
        error:
          type: string
          nullable: true
          description: Safe delivery failure summary, or null when `delivered` is true.
    RuntimePublication:
      type: object
      required:
        - state
        - retrying
      description: Publication state for a committed partner, AS2 connection, or mapping mutation. This field is not returned by reads or webhook configuration changes.
      properties:
        state:
          type: string
          enum:
            - published
            - pending
            - not_provisioned
          description: |
            - `published`: the tenant runtime configuration was published successfully, either inline during rollout or by updating its external configuration pointer.
            - `pending`: the database mutation committed, but runtime publication failed. ModernEDI's reconciler retries automatically every 60 seconds.
            - `not_provisioned`: the tenant does not have runtime infrastructure yet, so there is no runtime context to publish.
        retrying:
          type: boolean
          description: True when the 60-second reconciler will continue retrying a pending publication.
        message:
          type: string
          description: Optional safe operational context when publication is pending or not provisioned.
      example:
        state: published
        retrying: false
    MappedOutputWebhookStatusResponse:
      description: Current per-partner mapped-output push-delivery configuration and recent delivery health.
      type: object
      required:
        - success
        - webhook
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; unknown partners or authorization failures use an error response.
        webhook:
          description: Current endpoint, secret-presence indicator, ETag, and most recent delivery outcome.
          $ref: '#/components/schemas/MappedOutputWebhookStatus'
    MappedOutputWebhookStatus:
      description: Per-partner HTTPS push configuration and last observed delivery attempt.
      type: object
      required:
        - partnerId
        - enabled
        - signingSecretConfigured
        - etag
      properties:
        partnerId:
          type: integer
          description: Stable workspace-scoped partner id whose mapped outputs use this webhook.
        enabled:
          type: boolean
          description: Whether ModernEDI currently attempts HTTPS push delivery for this partner.
        endpointUrl:
          type: string
          format: uri
          nullable: true
          description: Configured public HTTPS destination, or `null` when no endpoint has been stored.
        signingSecretConfigured:
          type: boolean
          description: Whether ModernEDI has a secret for signing webhook requests; the full secret is never returned here.
        signingSecretLastFour:
          type: string
          nullable: true
          description: Last four characters only; the signing secret is never returned.
        activatedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        lastDeliveryAttemptAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        lastDeliverySuccessAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        lastDeliveryStatusCode:
          type: integer
          nullable: true
          description: Most recent webhook HTTP response status, or `null` before a response has been recorded.
        lastDeliveryError:
          type: string
          nullable: true
          description: Safe most-recent delivery error, or `null` when the latest attempt succeeded or none has occurred.
        createdAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        lastUpdatedAt:
          $ref: '#/components/schemas/NullableUtcTimestamp'
        etag:
          type: string
          readOnly: true
          description: Quoted SHA-256 configuration ETag, also returned in the HTTP `ETag` header.
    UsageResponse:
      description: Current UTC-day message quota, enforcement state, history, and workload signals.
      type: object
      required:
        - success
        - usage
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; authorization or telemetry failures use an error response.
        usage:
          description: Usage counters and entitlement thresholds current at `asOf`.
          $ref: '#/components/schemas/UsageSnapshot'
    UsageSnapshot:
      description: Workspace AS2-message usage and self-service plan enforcement state, measured in UTC.
      type: object
      required:
        - asOf
        - timeZone
        - attemptedMessagesToday
        - acceptedMessagesToday
        - rejectedMessagesToday
        - rejectionActive
        - unlimited
        - status
        - enforcementMode
        - policy
        - today
        - dailyUsage
        - todayByPartner
        - todayByHour
        - signals
      properties:
        asOf:
          $ref: '#/components/schemas/UtcTimestamp'
        timeZone:
          type: string
          description: Time zone defining daily and hourly buckets; currently always `UTC`.
          example: UTC
        planCode:
          type: string
          nullable: true
          description: Current billing plan code, or `null` when billing metadata is unavailable.
        dailyLimit:
          type: integer
          nullable: true
          description: Included AS2 messages per UTC day, or `null` for an unlimited plan.
        warningThreshold:
          type: integer
          nullable: true
          description: Attempted-message count that changes `status` to `approaching_limit`, or `null` for unlimited plans.
        rejectionThreshold:
          type: integer
          nullable: true
          description: Attempted-message count after which new AS2 messages are rejected, or `null` for unlimited plans.
        attemptedMessagesToday:
          type: integer
          description: AS2 messages attempted since 00:00 UTC, including accepted and rejected messages.
        acceptedMessagesToday:
          type: integer
          description: AS2 messages accepted for processing since 00:00 UTC.
        rejectedMessagesToday:
          type: integer
          description: AS2 messages rejected by quota enforcement since 00:00 UTC.
        quarantineRetentionDays:
          type: integer
          nullable: true
          description: Days quota-rejected payloads are retained for support recovery, or `null` when enforcement is not configured.
        rejectionActive:
          type: boolean
          description: True when attempted usage has crossed the rejection threshold and new messages are being rejected.
        unlimited:
          type: boolean
          description: True when this workspace has no configured daily AS2 message limit.
        status:
          type: string
          description: 'Stable state: `ok`, `approaching_limit`, `over_limit`, `rejection_active`, or `unlimited`.'
        enforcementMode:
          type: string
          description: Machine-readable quota behavior, currently `reject_after_safety_threshold` or `not_configured`.
        policy:
          type: string
          description: Customer-readable explanation of the workspace's current quota and safety-threshold policy.
        today:
          description: Inbound, outbound, and total accepted messages for the current UTC date.
          $ref: '#/components/schemas/UsageDay'
        dailyUsage:
          type: array
          description: Daily accepted-message totals for the retained usage window, ordered by date.
          items:
            $ref: '#/components/schemas/UsageDay'
        todayByPartner:
          type: array
          description: Current UTC-day accepted messages and transaction rows grouped by partner.
          items:
            $ref: '#/components/schemas/UsagePartnerBreakdown'
        todayByHour:
          type: array
          description: Current UTC-day accepted messages and transaction rows grouped into UTC hour buckets.
          items:
            $ref: '#/components/schemas/UsageHour'
        signals:
          description: Workload-shape signals that help operators identify batching and concentration.
          $ref: '#/components/schemas/UsageSignals'
    UsageDay:
      description: Accepted AS2 message counts for one UTC calendar date.
      type: object
      required:
        - date
        - inboundMessages
        - outboundMessages
        - totalMessages
      properties:
        date:
          type: string
          format: date
          description: UTC calendar date for these counts.
        inboundMessages:
          type: integer
          description: Distinct inbound AS2 messages accepted on this date.
        outboundMessages:
          type: integer
          description: Distinct outbound AS2 messages accepted on this date.
        totalMessages:
          type: integer
          description: Combined inbound and outbound accepted AS2 messages for this date.
    UsagePartnerBreakdown:
      description: Current UTC-day message and transaction volume attributed to one partner.
      type: object
      required:
        - partnerName
        - inboundMessages
        - outboundMessages
        - totalMessages
        - transactionRows
      properties:
        partnerName:
          type: string
          description: Partner display name captured on the counted transaction rows.
        inboundMessages:
          type: integer
          description: Distinct inbound AS2 messages attributed to this partner today.
        outboundMessages:
          type: integer
          description: Distinct outbound AS2 messages attributed to this partner today.
        totalMessages:
          type: integer
          description: Combined distinct inbound and outbound messages attributed to this partner today.
        transactionRows:
          type: integer
          description: Transaction-set rows attributed to this partner today; one AS2 message may contain multiple rows.
    UsageHour:
      description: Current UTC-day message and transaction volume for one UTC hour.
      type: object
      required:
        - hour
        - inboundMessages
        - outboundMessages
        - totalMessages
        - transactionRows
      properties:
        hour:
          type: string
          pattern: '^(?:[01][0-9]|2[0-3]):00$'
          description: Hour bucket label in `HH:00` form.
          example: '14:00'
        inboundMessages:
          type: integer
          description: Distinct inbound AS2 messages accepted during this UTC hour.
        outboundMessages:
          type: integer
          description: Distinct outbound AS2 messages accepted during this UTC hour.
        totalMessages:
          type: integer
          description: Combined inbound and outbound accepted messages during this UTC hour.
        transactionRows:
          type: integer
          description: Transaction-set rows recorded during this UTC hour; one AS2 message may contain multiple rows.
    UsageSignals:
      description: Current-day workload-shape indicators derived from accepted transaction rows and message ids.
      type: object
      required:
        - transactionRowsToday
        - multiTransactionMessageIdsToday
        - busiestHourMessages
        - topPartnerMessages
      properties:
        transactionRowsToday:
          type: integer
          description: Total transaction-set rows recorded today; may exceed message count when interchanges are batched.
        multiTransactionMessageIdsToday:
          type: integer
          description: Distinct AS2 message ids that contained more than one transaction row today.
        busiestHour:
          type: string
          nullable: true
          description: UTC `HH:00` bucket with the most messages today, or `null` when no messages were recorded.
          pattern: '^(?:[01][0-9]|2[0-3]):00$'
          example: '18:00'
        busiestHourMessages:
          type: integer
          description: Distinct AS2 message count in `busiestHour`, or zero when there is no busiest hour.
        topPartnerName:
          type: string
          nullable: true
          description: Partner with the most messages today, or `null` when no partner-attributed messages were recorded.
        topPartnerMessages:
          type: integer
          description: Distinct AS2 message count for `topPartnerName`, or zero when no top partner exists.
    X12ValidationRequest:
      type: object
      required:
        - x12
      properties:
        x12:
          type: string
          description: Complete X12 interchange to parse and validate.
    X12ValidationResponse:
      description: Successful X12 parser and standards-validation result.
      type: object
      required:
        - success
        - validation
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; invalid X12 is reported in `validation`, while request-level failures use an error response.
        validation:
          description: Structured syntax diagnostics and, when parsing succeeds, a navigable interchange summary.
          $ref: '#/components/schemas/X12ValidationResult'
    X12ValidationResult:
      description: X12 well-formedness and validation diagnostics produced from the submitted interchange.
      type: object
      required:
        - valid
        - wellFormed
        - errors
        - warnings
        - failures
        - functionalGroupErrors
        - transactionErrors
        - segmentErrors
        - elementErrors
        - dispositionError
        - dispositionWarning
        - dispositionFailure
        - interchange
      properties:
        valid:
          type: boolean
          description: True only when parsing succeeded and no error- or failure-level X12 diagnostics were found.
        wellFormed:
          type: boolean
          description: True when ModernEDI could parse an interchange envelope; a well-formed document may still be invalid.
        errors:
          type: array
          description: Human-readable parser or validation errors that prevent the submitted interchange from being considered valid.
          items:
            type: string
        warnings:
          type: array
          description: Human-readable non-fatal findings that merit review but do not by themselves make `valid` false.
          items:
            type: string
        failures:
          type: array
          description: Human-readable severe validation failures reported separately by the X12 validator.
          items:
            type: string
        dispositionError:
          type: string
          nullable: true
          description: Interchange-level error disposition text, or `null` when the validator did not report one.
        dispositionWarning:
          type: string
          nullable: true
          description: Interchange-level warning disposition text, or `null` when the validator did not report one.
        dispositionFailure:
          type: string
          nullable: true
          description: Interchange-level failure disposition text, or `null` when the validator did not report one.
        functionalGroupErrors:
          type: array
          description: Structured findings attached to a GS/GE functional group, with zero-based group indexes for correlation.
          items:
            $ref: '#/components/schemas/X12FunctionalGroupValidationError'
        transactionErrors:
          type: array
          description: Structured findings attached to an ST/SE transaction set, with zero-based group and transaction indexes.
          items:
            $ref: '#/components/schemas/X12TransactionValidationError'
        segmentErrors:
          type: array
          description: Structured segment-level X12 syntax findings, including the one-based position within the transaction.
          items:
            $ref: '#/components/schemas/X12SegmentValidationError'
        elementErrors:
          type: array
          description: Structured data-element findings identifying the segment, element, optional composite component, and rejected value.
          items:
            $ref: '#/components/schemas/X12ElementValidationError'
        interchange:
          type: object
          nullable: true
          description: Parsed interchange summary with separators, groups, transactions, and segment previews; `null` when parsing did not produce an interchange.
          allOf:
            - $ref: '#/components/schemas/X12InterchangeSummary'
    X12FunctionalGroupValidationError:
      type: object
      description: Validation finding associated with one GS/GE functional group.
      required:
        - functionalGroupIndex
        - functionalIdentifierCode
        - functionalIdentifierDescription
        - controlNumber
        - code
        - description
      properties:
        functionalGroupIndex:
          type: integer
          minimum: 0
          description: Zero-based functional-group index within the parsed interchange.
        functionalIdentifierCode:
          type: string
          description: GS01 functional identifier code for the affected group.
        functionalIdentifierDescription:
          type: string
          nullable: true
          description: Human-readable GS01 code meaning, or `null` when the code is not in ModernEDI's reference catalog.
        controlNumber:
          type: string
          description: GS06 functional-group control number used to correlate the finding with source X12.
        code:
          type: string
          description: X12 validator code for the functional-group finding.
        description:
          type: string
          description: Human-readable explanation of the functional-group finding.
    X12TransactionValidationError:
      type: object
      description: Validation finding associated with one ST/SE transaction set.
      required:
        - functionalGroupIndex
        - transactionIndex
        - transactionSetIdentifierCode
        - transactionSetDescription
        - controlNumber
        - code
        - description
      properties:
        functionalGroupIndex:
          type: integer
          minimum: 0
          description: Zero-based functional-group index within the parsed interchange.
        transactionIndex:
          type: integer
          minimum: 0
          description: Zero-based transaction index within the containing functional group.
        transactionSetIdentifierCode:
          type: string
          description: ST01 transaction-set identifier, such as `850` or `810`.
        transactionSetDescription:
          type: string
          nullable: true
          description: Human-readable ST01 meaning, or `null` when the code is not in ModernEDI's reference catalog.
        controlNumber:
          type: string
          description: ST02 transaction control number used to correlate the finding with source X12.
        code:
          type: string
          description: X12 validator code for the transaction-level finding.
        description:
          type: string
          description: Human-readable explanation of the transaction-level finding.
    X12SegmentValidationError:
      allOf:
        - $ref: '#/components/schemas/X12TransactionValidationError'
        - type: object
          description: Validation finding associated with one segment in a transaction set.
          required:
            - segmentId
            - segmentPosition
          properties:
            segmentId:
              type: string
              description: Segment identifier, such as `BEG`, at the reported position.
            segmentPosition:
              type: integer
              minimum: 1
              description: One-based segment position within the transaction set.
    X12ElementValidationError:
      allOf:
        - $ref: '#/components/schemas/X12SegmentValidationError'
        - type: object
          description: Validation finding associated with one simple element or composite component.
          required:
            - elementPosition
            - compositePosition
            - elementDefinition
            - badValue
          properties:
            elementPosition:
              type: integer
              minimum: 1
              description: One-based element position within the affected segment.
            compositePosition:
              type: integer
              minimum: 1
              nullable: true
              description: One-based component position for a composite element, or `null` for a simple element.
            elementDefinition:
              type: string
              description: X12 data-element definition number used to validate the value.
            badValue:
              type: string
              description: Exact submitted element value that failed validation; treat it as potentially sensitive business data.
    X12InterchangeSummary:
      type: object
      description: Parsed ISA/IEA envelope and its functional groups, transactions, separators, and readable previews.
      required:
        - x12Version
        - controlNumber
        - technicalAcknowledgment
        - functionalAcknowledgment
        - implementationAcknowledgment
        - separators
        - functionalGroupCount
        - transactionCount
        - functionalGroups
      properties:
        x12Version:
          type: string
          description: X12 implementation version resolved from the interchange and functional-group headers.
        controlNumber:
          type: string
          description: ISA13 interchange control number from the submitted document.
        technicalAcknowledgment:
          type: boolean
          description: Whether the interchange is an X12 technical acknowledgment document.
        functionalAcknowledgment:
          type: boolean
          description: Whether the interchange is an X12 997 functional acknowledgment.
        implementationAcknowledgment:
          type: boolean
          description: Whether the interchange is an X12 999 implementation acknowledgment.
        separators:
          description: Delimiters detected from the ISA envelope and used to parse previews.
          $ref: '#/components/schemas/X12SeparatorSummary'
        functionalGroupCount:
          type: integer
          minimum: 0
          description: Number of parsed GS/GE functional groups in the interchange.
        transactionCount:
          type: integer
          minimum: 0
          description: Total number of parsed ST/SE transaction sets across all groups.
        functionalGroups:
          type: array
          description: Parsed functional groups in source order.
          items:
            $ref: '#/components/schemas/X12FunctionalGroupSummary'
    X12SeparatorSummary:
      type: object
      description: Single-character delimiters detected from the fixed-width ISA segment.
      required:
        - elementSeparator
        - subElementSeparator
        - segmentTerminator
        - repetitionSeparator
      properties:
        elementSeparator:
          type: string
          minLength: 1
          maxLength: 1
          description: Character separating simple elements within each segment.
        subElementSeparator:
          type: string
          minLength: 1
          maxLength: 1
          description: Character separating components inside composite data elements.
        segmentTerminator:
          type: string
          minLength: 1
          maxLength: 1
          description: Character terminating each X12 segment.
        repetitionSeparator:
          type: string
          minLength: 1
          maxLength: 1
          nullable: true
          description: Repetition separator for versions that support repetitions, or `null` when unavailable.
    X12FunctionalGroupSummary:
      type: object
      description: Parsed GS/GE group with its identity, control number, and transaction summaries.
      required:
        - functionalGroupIndex
        - functionalIdentifierCode
        - functionalIdentifierDescription
        - controlNumber
        - x12Version
        - transactionCount
        - transactions
      properties:
        functionalGroupIndex:
          type: integer
          minimum: 0
          description: Zero-based group index within the interchange.
        functionalIdentifierCode:
          type: string
          description: GS01 functional identifier code, such as `PO` or `IN`.
        functionalIdentifierDescription:
          type: string
          nullable: true
          description: Human-readable GS01 meaning, or `null` for an unknown code.
        controlNumber:
          type: string
          description: GS06 functional-group control number.
        x12Version:
          type: string
          description: X12 version declared by the functional-group header.
        transactionCount:
          type: integer
          minimum: 0
          description: Number of ST/SE transaction sets in this group.
        transactions:
          type: array
          description: Parsed transaction summaries in source order.
          items:
            $ref: '#/components/schemas/X12TransactionSummary'
    X12TransactionSummary:
      type: object
      description: Parsed ST/SE transaction identity and readable segment preview.
      required:
        - functionalGroupIndex
        - transactionIndex
        - transactionSetIdentifierCode
        - transactionSetDescription
        - controlNumber
        - preview
      properties:
        functionalGroupIndex:
          type: integer
          minimum: 0
          description: Zero-based index of the containing functional group.
        transactionIndex:
          type: integer
          minimum: 0
          description: Zero-based transaction index within the group.
        transactionSetIdentifierCode:
          type: string
          description: ST01 transaction-set identifier, such as `850` or `810`.
        transactionSetDescription:
          type: string
          nullable: true
          description: Human-readable ST01 meaning, or `null` for an unknown code.
        controlNumber:
          type: string
          description: ST02 transaction control number.
        preview:
          description: Source X12 and parsed segments for this transaction.
          $ref: '#/components/schemas/X12TransactionPreview'
    X12TransactionPreview:
      type: object
      description: Transaction-local X12 text and parsed segment/element values for inspection.
      required:
        - x12
        - segmentCount
        - segments
      properties:
        x12:
          type: string
          description: Complete ST-through-SE X12 text for this transaction using the detected delimiters.
        segmentCount:
          type: integer
          minimum: 0
          description: Number of parsed segments included in `segments`.
        segments:
          type: array
          description: Parsed segments in source order with loop-aware paths.
          items:
            $ref: '#/components/schemas/X12SegmentPreview'
    X12SegmentPreview:
      type: object
      description: One parsed segment and its populated element values.
      required:
        - segmentPosition
        - segmentId
        - segmentDescription
        - segmentPath
        - elements
      properties:
        segmentPosition:
          type: integer
          minimum: 1
          description: One-based segment position within the transaction.
        segmentId:
          type: string
          description: X12 segment identifier, such as `BEG` or `N1`.
        segmentDescription:
          type: string
          description: Human-readable segment name from the X12 reference catalog.
        segmentPath:
          type: array
          description: Loop-aware path of segment identifiers used to disambiguate repeated segments.
          items:
            type: string
        elements:
          type: array
          description: Populated elements only; omitted/empty source elements are not included.
          items:
            $ref: '#/components/schemas/X12ElementPreview'
    X12ElementPreview:
      type: object
      description: One populated X12 data element from a parsed segment.
      required:
        - elementPosition
        - definition
        - description
        - value
      properties:
        elementPosition:
          type: integer
          minimum: 1
          description: One-based element position within the segment.
        definition:
          type: string
          description: X12 data-element definition number from the reference catalog.
        description:
          type: string
          description: Human-readable data-element name from the reference catalog.
        dataType:
          type: string
          enum:
            - ALPHANUMERIC
            - BINARY
            - DATE
            - ID
            - NUMERIC
            - DECIMAL
            - TIME
            - COMPOSITE
            - NONE
          description: Normalized data type from the X12 reference catalog for this populated element.
        impliedDecimalDigits:
          type: integer
          minimum: 0
          description: Number of trailing digits interpreted as fractional for a NUMERIC (Nn) element; omitted for every other data type.
        value:
          type: string
          description: Exact parsed source value; treat it as potentially sensitive business data.
    X12VersionsResponse:
      description: X12 implementation versions available to validation and mapping tools.
      type: object
      required:
        - success
        - versions
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        versions:
          type: array
          description: Supported numeric X12 version identifiers accepted by reference endpoints.
          items:
            type: string
          example:
            - '4010'
            - '5010'
    X12TransactionSetsResponse:
      description: Transaction-set reference catalog for one supported X12 version.
      type: object
      required:
        - success
        - x12Version
        - transactionSets
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true`; failures use the documented error response instead.
        x12Version:
          type: string
          description: Requested numeric X12 version whose catalog is returned.
          example: '4010'
        transactionSets:
          type: array
          description: Supported transaction-set identifiers and their customer-readable names.
          items:
            $ref: '#/components/schemas/X12TransactionSetReference'
    X12TransactionSetReference:
      description: One transaction-set identifier in an X12 version's reference catalog.
      type: object
      required:
        - transactionSetIdentifierCode
        - transactionSetDescription
      properties:
        transactionSetIdentifierCode:
          type: string
          description: ST01 transaction-set identifier accepted for this X12 version.
          example: '850'
        transactionSetDescription:
          type: string
          description: Human-readable business-document name associated with the ST01 code.
          example: Purchase Order
    PlatformErrorResponse:
      $ref: '#/components/schemas/ErrorResponse'
    ErrorObject:
      description: Stable machine-readable error details returned for a failed Integration API request.
      type: object
      required:
        - code
        - message
        - retryable
        - requestId
        - details
      properties:
        code:
          type: string
          description: Stable machine-readable error code; branch on this value rather than parsing `message`.
          example: unauthorized
        message:
          type: string
          description: Customer-readable explanation suitable for logs or an operator-facing error message.
          example: Missing or invalid integration API key.
        retryable:
          type: boolean
          description: Whether retrying the same operation later may succeed without changing the request.
          example: false
        requestId:
          type: string
          description: Correlation identifier also returned in `X-Request-Id`; include it when contacting ModernEDI Support.
          example: req_01HZ9TRK7B0YQW2V4RMNC9B60A
        details:
          type: object
          additionalProperties: true
          description: Error-specific structured context such as field paths, limits, required scopes, or entitlement details.
    ErrorResponse:
      description: Standard JSON failure envelope used by Integration API operations.
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          enum:
            - false
          description: Always `false` for this error envelope.
        error:
          description: Machine-readable code, retry guidance, correlation id, and contextual details for the failure.
          $ref: '#/components/schemas/ErrorObject'
