{
  "openapi": "3.0.3",
  "info": { "title": "Verify Digital Signature - asynchronous verification", "version": "1.0.0", "description": "Durable verification jobs. A completed job may have invalid, indeterminate or unsigned business results. Original input is deleted after terminal processing. Bearer tokens are opaque, not JWTs." },
  "servers": [{ "url": "/" }],
  "security": [{ "apiToken": [] }],
  "paths": {
    "/api/v1/verifications": {
      "post": {
        "operationId": "createVerification", "summary": "Accept one PDF/XML job durably",
        "parameters": [{ "name": "Idempotency-Key", "in": "header", "required": true, "schema": { "type": "string", "minLength": 8, "maxLength": 128 }, "description": "Case-sensitive opaque ASCII key scoped to owner and token; same payload replays without charging quota." }],
        "requestBody": { "required": true, "content": { "multipart/form-data": { "schema": { "type": "object", "required": ["file"], "properties": { "file": { "type": "string", "format": "binary", "description": "PDF/XML, at most 25 MiB (26214400 bytes). Multipart request limit is 27 MiB (28311552 bytes). Deployments may set lower limits. Base64 is not supported by this endpoint." }, "languageCode": { "type": "string", "enum": ["vi-VN", "en-US", "zh-CN", "ko-KR", "ja-JP"], "default": "vi-VN" } } } } } },
        "responses": {
          "202": { "description": "Input and job committed", "headers": { "Location": { "$ref": "#/components/headers/Location" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
          "200": { "description": "Idempotent replay", "headers": { "Idempotency-Replayed": { "schema": { "type": "string", "enum": ["true"] } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
          "400": { "$ref": "#/components/responses/Problem" }, "401": { "$ref": "#/components/responses/Problem" }, "403": { "$ref": "#/components/responses/Problem" }, "409": { "$ref": "#/components/responses/Problem" }, "413": { "$ref": "#/components/responses/Problem" }, "415": { "$ref": "#/components/responses/Problem" }, "429": { "$ref": "#/components/responses/RetryProblem" }, "503": { "$ref": "#/components/responses/RetryProblem" }
        }
      }
    },
    "/api/v1/verifications/{verificationId}": {
      "parameters": [{ "$ref": "#/components/parameters/VerificationId" }],
      "get": { "operationId": "getVerification", "summary": "Read owner-scoped status and progress", "parameters": [{ "name": "If-None-Match", "in": "header", "schema": { "type": "string" } }], "responses": {
        "200": { "description": "Current job status", "headers": { "ETag": { "schema": { "type": "string" } }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
        "304": { "description": "Unchanged; no response body" }, "401": { "$ref": "#/components/responses/Problem" }, "403": { "$ref": "#/components/responses/Problem" }, "404": { "$ref": "#/components/responses/Problem" }, "429": { "$ref": "#/components/responses/RetryProblem" }, "503": { "$ref": "#/components/responses/RetryProblem" }
      } }
    },
    "/api/v1/verifications/{verificationId}/result": {
      "parameters": [{ "$ref": "#/components/parameters/VerificationId" }],
      "get": { "operationId": "getVerificationResult", "summary": "Read completed result, not a validation of legal suitability", "responses": {
        "200": { "description": "Result available", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Result" } } } },
        "202": { "description": "Still processing; follow status Location", "headers": { "Location": { "$ref": "#/components/headers/Location" }, "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
        "401": { "$ref": "#/components/responses/Problem" }, "403": { "$ref": "#/components/responses/Problem" }, "404": { "$ref": "#/components/responses/Problem" }, "409": { "$ref": "#/components/responses/Problem" }, "410": { "$ref": "#/components/responses/Problem" }, "429": { "$ref": "#/components/responses/RetryProblem" }, "503": { "$ref": "#/components/responses/RetryProblem" }
      } }
    },
    "/api/v1/verifications/{verificationId}/cancel": {
      "parameters": [{ "$ref": "#/components/parameters/VerificationId" }],
      "post": { "operationId": "cancelVerification", "summary": "Request cooperative cancellation", "responses": {
        "200": { "description": "Cancelled", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
        "202": { "description": "Cancellation requested; poll until terminal", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Job" } } } },
        "401": { "$ref": "#/components/responses/Problem" }, "403": { "$ref": "#/components/responses/Problem" }, "404": { "$ref": "#/components/responses/Problem" }, "409": { "$ref": "#/components/responses/Problem" }, "429": { "$ref": "#/components/responses/RetryProblem" }, "503": { "$ref": "#/components/responses/RetryProblem" }
      } }
    }
  },
  "components": {
    "securitySchemes": { "apiToken": { "type": "http", "scheme": "bearer", "description": "Opaque API token issued by this application." } },
    "parameters": { "VerificationId": { "name": "verificationId", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } },
    "headers": { "Location": { "schema": { "type": "string", "format": "uri-reference" } }, "RetryAfter": { "description": "Suggested polling/backoff interval in seconds", "schema": { "type": "integer", "minimum": 1, "example": 3 } } },
    "responses": {
      "Problem": { "description": "RFC 9457 error; other owners' identifiers return 404", "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } },
      "RetryProblem": { "description": "Rate/quota/capacity limit or temporary dependency failure", "headers": { "Retry-After": { "$ref": "#/components/headers/RetryAfter" } }, "content": { "application/problem+json": { "schema": { "$ref": "#/components/schemas/Problem" } } } }
    },
    "schemas": {
      "Problem": { "type": "object", "required": ["type", "title", "status", "errorCode", "traceId"], "properties": { "type": { "type": "string", "format": "uri" }, "title": { "type": "string" }, "status": { "type": "integer" }, "detail": { "type": "string", "nullable": true }, "instance": { "type": "string" }, "errorCode": { "type": "string" }, "traceId": { "type": "string" } } },
      "Job": {
        "type": "object", "required": ["verificationId", "status", "acceptedAt", "progress", "resultAvailability", "version", "links"],
        "properties": {
          "verificationId": { "type": "string", "format": "uuid" }, "status": { "type": "string", "enum": ["queued", "running", "retry_scheduled", "completed", "failed", "cancelled"] },
          "acceptedAt": { "type": "string", "format": "date-time" }, "startedAt": { "type": "string", "format": "date-time", "nullable": true }, "completedAt": { "type": "string", "format": "date-time", "nullable": true },
          "progress": { "type": "object", "required": ["stage", "processedSignatures", "totalSignatures"], "properties": { "stage": { "type": "string" }, "processedSignatures": { "type": "integer", "minimum": 0 }, "totalSignatures": { "type": "integer", "minimum": 0, "nullable": true } } },
          "resultAvailability": { "type": "string", "enum": ["not_ready", "available", "expired", "not_applicable"] }, "resultExpiresAt": { "type": "string", "format": "date-time", "nullable": true },
          "retryAfterSeconds": { "type": "integer" }, "version": { "type": "string", "format": "uuid" }, "errorCode": { "type": "string", "nullable": true }, "errorCategory": { "type": "string", "nullable": true },
          "inputDeletedAt": { "type": "string", "format": "date-time", "nullable": true }, "inputRetentionStatus": { "type": "string", "enum": ["not_stored", "retained_for_processing", "deletion_pending", "deleted"] },
          "links": { "type": "object", "required": ["status", "result"], "properties": { "status": { "type": "string" }, "result": { "type": "string" } } }
        },
        "example": { "verificationId": "8d13f38e-b908-40d3-a08d-067249f73f13", "status": "queued", "acceptedAt": "2026-10-30T08:00:00Z", "progress": { "stage": "queued", "processedSignatures": 0, "totalSignatures": null }, "resultAvailability": "not_ready", "version": "76c69727-c4c7-4a39-bded-746380787783", "links": { "status": "/api/v1/verifications/8d13f38e-b908-40d3-a08d-067249f73f13", "result": "/api/v1/verifications/8d13f38e-b908-40d3-a08d-067249f73f13/result" } }
      },
      "Result": {
        "type": "object", "required": ["verificationId", "resultVersion", "status", "file", "documentOutcome", "signatureCount", "results", "timing"],
        "properties": {
          "verificationId": { "type": "string", "format": "uuid" }, "resultVersion": { "type": "string", "enum": ["1.0"] }, "status": { "type": "string", "enum": ["completed"] }, "documentOutcome": { "type": "string", "enum": ["valid", "invalid", "indeterminate", "unsigned"] }, "signatureCount": { "type": "integer", "minimum": 0 },
          "file": { "type": "object", "required": ["name", "fileType", "sizeBytes", "sha256"], "properties": { "name": { "type": "string" }, "fileType": { "type": "string", "enum": ["PDF", "XML"] }, "sizeBytes": { "type": "integer", "format": "int64" }, "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" } } },
          "summary": { "type": "object", "properties": { "valid": { "type": "integer" }, "invalid": { "type": "integer" }, "indeterminate": { "type": "integer" } } }, "documentSummary": { "type": "object", "description": "Compatibility summary and localized presentation; use canonical outcome for machine decisions.", "additionalProperties": true },
          "verifiedAt": { "type": "string", "format": "date-time" }, "policyVersion": { "type": "string", "format": "uuid" }, "trustSnapshotId": { "type": "string" }, "resultExpiresAt": { "type": "string", "format": "date-time" },
          "timing": { "type": "object", "properties": { "queueWaitMs": { "type": "integer", "format": "int64" }, "processingTimeMs": { "type": "integer", "format": "int64" }, "totalLatencyMs": { "type": "integer", "format": "int64" } } },
          "results": { "type": "array", "items": { "$ref": "#/components/schemas/Signature" } }
        }
      },
      "Signature": { "type": "object", "required": ["signatureIndex", "outcome", "certificate", "details"], "properties": {
        "signatureIndex": { "type": "integer", "minimum": 1 }, "outcome": { "type": "string", "enum": ["valid", "invalid", "indeterminate"] }, "durationMs": { "type": "integer", "format": "int64" }, "evidenceObservedAt": { "type": "string", "format": "date-time", "nullable": true },
        "certificate": { "type": "object", "properties": { "sha256": { "type": "string" }, "issuerSha256": { "type": "string" }, "providerId": { "type": "string" }, "providerName": { "type": "string" }, "trustType": { "type": "string" }, "subjectType": { "type": "string" }, "keyAlgorithm": { "type": "string" }, "keySize": { "type": "integer" } } },
        "details": { "type": "object", "description": "Existing signature evidence DTO: issuer, subject, integrity, outcome, revocation, timestamp, historicalValidation and warnings. Localized text is for presentation only.", "additionalProperties": true }
      } }
    }
  }
}
