{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/attestwire-com/json-schema/attestwire-com-send-accepted-schema.json",
  "title": "SendAccepted",
  "description": "The mail service accepted the message. `delivery` says what that does not mean.",
  "x-generated": "2026-11-02",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/attestwire-com-openapi.json#/components/schemas/SendAccepted",
  "type": "object",
  "required": [
    "status",
    "message_id",
    "to",
    "from",
    "reply_to",
    "subject",
    "language",
    "test_mode",
    "source",
    "format",
    "profile",
    "attachment",
    "warnings",
    "information",
    "delivery",
    "provenance"
  ],
  "properties": {
    "status": {
      "type": "string",
      "enum": [
        "accepted"
      ]
    },
    "message_id": {
      "type": "string",
      "description": "The mail service's id for the message."
    },
    "to": {
      "type": "string",
      "format": "email"
    },
    "from": {
      "type": "object",
      "required": [
        "email",
        "name"
      ],
      "properties": {
        "email": {
          "type": "string",
          "format": "email"
        },
        "name": {
          "type": "string",
          "description": "\"{seller} via Attestwire\"."
        }
      }
    },
    "reply_to": {
      "type": "string",
      "format": "email",
      "description": "The seller's contact e-mail (BT-43)."
    },
    "subject": {
      "type": "string"
    },
    "language": {
      "type": "string",
      "enum": [
        "en",
        "de",
        "fr"
      ]
    },
    "test_mode": {
      "type": "boolean",
      "description": "A free key's message: sent to its own address and marked as a test."
    },
    "source": {
      "type": "string",
      "enum": [
        "generated",
        "document"
      ],
      "description": "`generated` from `invoice`, or a `document` sent as it came."
    },
    "format": {
      "type": "string",
      "enum": [
        "xml",
        "pdf"
      ]
    },
    "profile": {
      "type": [
        "string",
        "null"
      ],
      "description": "The profile the invoice was judged under."
    },
    "attachment": {
      "type": "object",
      "required": [
        "filename",
        "content_type",
        "bytes",
        "sha256"
      ],
      "properties": {
        "filename": {
          "type": "string"
        },
        "content_type": {
          "type": "string",
          "enum": [
            "application/xml",
            "application/pdf"
          ]
        },
        "bytes": {
          "type": "integer"
        },
        "sha256": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$",
          "description": "The attachment's SHA-256: keep it as your record of what was sent."
        }
      }
    },
    "warnings": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/TeachingError"
      }
    },
    "information": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/TeachingError"
      }
    },
    "findings_truncated": {
      "$ref": "#/$defs/FindingsTruncated"
    },
    "delivery": {
      "type": "string",
      "description": "Accepted by the mail service, which delivers it and retries on its own. Attestwire is not told whether it was delivered, bounced or marked as spam, and does not store the message: keep `attachment.sha256` and `message_id` as your record of what was sent, and ask the recipient to confirm receipt if you need to know."
    },
    "provenance": {
      "$ref": "#/$defs/Provenance"
    }
  },
  "$defs": {
    "FindingsTruncated": {
      "type": "object",
      "description": "Present ONLY when a findings array was truncated, and absent — not null, not zeroed — otherwise. Each of `errors`, `warnings` and `information` is capped independently; past the cap the array is cut and this object states what was left out. `valid` still reflects the whole document: truncation changes what is printed, never the verdict. Reaching the cap takes a hundred-plus invoice lines on which every field is wrong, and at that scale the errors are systematic — every distinct problem in the document already appears in what you were given. Treat it as a hint to fix the pattern and re-validate, not as an error.",
      "required": [
        "total",
        "returned",
        "cap",
        "by_severity",
        "note"
      ],
      "properties": {
        "total": {
          "type": "integer",
          "description": "Findings the engine produced, across all three severities."
        },
        "returned": {
          "type": "integer",
          "description": "Findings actually listed in this response."
        },
        "cap": {
          "type": "integer",
          "description": "The per-severity cap this deployment applied."
        },
        "by_severity": {
          "type": "object",
          "description": "Per-array totals, so you can see which one overflowed.",
          "required": [
            "errors",
            "warnings",
            "information"
          ],
          "properties": {
            "errors": {
              "$ref": "#/$defs/TruncationCount"
            },
            "warnings": {
              "$ref": "#/$defs/TruncationCount"
            },
            "information": {
              "$ref": "#/$defs/TruncationCount"
            }
          }
        },
        "note": {
          "type": "string",
          "description": "Prose explanation, safe to show a user or an agent verbatim."
        }
      }
    },
    "KositConformance": {
      "type": "object",
      "description": "When the official KoSIT validator was last run against this engine's committed fixtures, and with what.\n\n**NOTHING IS SENT TO KoSIT WHEN YOU CALL US.** This is a dated record of a check we ran on release, not a per-call verification, and it says nothing about YOUR document.",
      "required": [
        "recorded",
        "validator",
        "configuration",
        "configuration_published"
      ],
      "properties": {
        "recorded": {
          "type": "string",
          "format": "date",
          "description": "The date of the last recorded full fixture run."
        },
        "validator": {
          "type": "string",
          "description": "Version of the KoSIT standalone validator used."
        },
        "configuration": {
          "type": "string",
          "description": "Version of the XRechnung validator configuration used."
        },
        "configuration_published": {
          "type": "string",
          "format": "date",
          "description": "The date that configuration was published by KoSIT."
        }
      }
    },
    "Provenance": {
      "type": "object",
      "description": "What ran. Present on every metered response — POST /v1/validate and POST /v1/parse, JSON body or XML document, and the JSON envelope of POST /v1/generate including the `422` it returns for an invoice it will not emit.\n\nWHY IT EXISTS. Pin `@attestwire/en16931` and your CI gets the same answer for the same invoice forever; the hosted API always runs the current rule set, because a compliance service that froze its rules would be answering last quarter's regulation. Both are correct and the difference used to be invisible — a `valid: false` looked identical whether your invoice had changed or our rules had. This says which.\n\nThe one metered response WITHOUT it is `/v1/generate?format=xml`, which returns the document alone: an XML file has nowhere to put this, and this API does not write its own metadata into a customer's tax document.",
      "required": [
        "engine",
        "engine_version",
        "ruleset",
        "profile",
        "kosit_conformance"
      ],
      "properties": {
        "engine": {
          "type": "string",
          "description": "The npm package every compliance decision on this API comes from. Install this package at `engine_version` and you have the build that judged your document."
        },
        "engine_version": {
          "type": "string"
        },
        "ruleset": {
          "type": "string",
          "description": "The standard and our build of it, as one identifier to quote."
        },
        "profile": {
          "type": [
            "string",
            "null"
          ],
          "description": "The CIUS that ACTUALLY ran, read from the result rather than from your request: a body naming no profile is judged as `en16931`, and this is where you see that. `null` when there was no verdict to read it from."
        },
        "kosit_conformance": {
          "$ref": "#/$defs/KositConformance"
        }
      }
    },
    "SourceLocation": {
      "type": "object",
      "description": "Only on findings for a document, and not on an `AW-` one, which is about the whole document. The line and column of the element in the document that was sent. When the element is missing, or several could be meant and nothing says which, `exact` is false and this is the nearest enclosing element that is there.",
      "required": [
        "line",
        "column",
        "path",
        "exact"
      ],
      "properties": {
        "line": {
          "type": "integer",
          "minimum": 1
        },
        "column": {
          "type": "integer",
          "minimum": 1,
          "description": "Of the start tag, in UTF-16 code units."
        },
        "path": {
          "type": "string",
          "description": "The element's path, with the document's own prefixes."
        },
        "exact": {
          "type": "boolean"
        },
        "attachment": {
          "type": "string",
          "description": "Only when a PDF was sent: the name of the attachment the XML was read from. `line` and `column` are then in that XML, not in the PDF."
        }
      }
    },
    "TeachingError": {
      "type": "object",
      "description": "One finding, with enough context to fix the invoice without opening the specification. Almost always a rule failure. The exception is a finding the engine raises about a document as a whole, whose `rule` starts `AW-` — such as `AW-PROFILE-SUBSET`, fatal, on a Factur-X or ZUGFeRD file whose BT-24 declares MINIMUM or BASIC WL, profiles that carry too little to be an EN 16931 invoice. It comes first, ahead of the rule failures it explains. The others are about a Factur-X or ZUGFeRD PDF's container and never fatal: `AW-PDF-ATTACHMENT`, `AW-PDF-AF`, `AW-PDF-RELATIONSHIP` and `AW-PDF-MIME` on the attached invoice XML, `AW-PDF-XMP` and `AW-PDF-XMP-PROFILE` on the XMP metadata, all on field `document` except an `AW-PDF-XMP-PROFILE` that contradicts the XML's own BT-24, which is on `BT-24`. An `AW-` finding has no rules page, so no `docsUrl`, and no `xpath` or `location`: its `message` and `fix` are the whole explanation.",
      "required": [
        "rule",
        "field",
        "severity",
        "message",
        "fix"
      ],
      "properties": {
        "rule": {
          "type": "string",
          "description": "The rule id, as the KoSIT validator prints it: BR-*, BR-DE-*, PEPPOL-EN16931-R*. `ATW-*` is a check of this validator's own rather than the regulation's. `AW-*` is not a rule at all: see above."
        },
        "field": {
          "description": "Business term(s) the rule constrains.",
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          ]
        },
        "severity": {
          "type": "string",
          "enum": [
            "fatal",
            "warning",
            "information"
          ],
          "description": "The reference validators' own three levels. `fatal` rejects the document; `warning` does not; `information` is advisory — KoSIT raises it and then accepts the invoice."
        },
        "message": {
          "type": "string"
        },
        "fix": {
          "type": "string"
        },
        "xpath": {
          "type": "string",
          "description": "Where the element is. For a JSON invoice, its place in the UBL this API would generate. For an XML document, its path in that document as written when it is there, otherwise where it belongs, in the document's own syntax."
        },
        "docsUrl": {
          "type": "string",
          "format": "uri",
          "description": "Where the rule is explained. On every finding except an `AW-` one, which is not a rule and has no page."
        },
        "location": {
          "$ref": "#/$defs/SourceLocation"
        }
      }
    },
    "TruncationCount": {
      "type": "object",
      "required": [
        "total",
        "returned"
      ],
      "properties": {
        "total": {
          "type": "integer"
        },
        "returned": {
          "type": "integer"
        }
      }
    }
  }
}