openapi: 3.0.3
info:
  title: TrustSignal Public Verification API
  version: 1.1.0
  description: |
    TrustSignal is evidence integrity infrastructure for existing workflows.
    This contract documents the public verification lifecycle for creating signed verification receipts,
    retrieving receipt state, checking later verification status, and managing authorized lifecycle actions.
servers:
  - url: https://api.trustsignal.dev
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Verification
    description: Create signed verification receipts and return verification signals.
  - name: Receipts
    description: Retrieve stored receipts and receipt-ready artifacts.
  - name: Lifecycle
    description: Check later verification status and manage authorized receipt lifecycle actions.
  - name: Integrations
    description: Provider-specific verification adapters (GitHub, etc.).
paths:
  /api/v1/verify:
    post:
      tags: [Verification]
      summary: Create a verification and receive a signed verification receipt
      description: |
        Submit a verification request from an existing workflow. TrustSignal returns verification signals,
        a signed verification receipt, and verifiable provenance metadata that can be used for later verification.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VerificationRequest'
            examples:
              default:
                summary: Verification request
                value:
                  bundleId: verification-2026-03-12-001
                  transactionType: deed_transfer
                  ron:
                    provider: source-system
                    notaryId: NOTARY-EXAMPLE-01
                    commissionState: IL
                    sealPayload: simulated-seal-payload
                  doc:
                    docHash: "0x8b7b2f52f2a2e19f8f3fe0d815d1c1d8d1e0d120e8cc60d1baf5e7a6f9d211aa"
                  policy:
                    profile: CONTROL_CC_001
                  property:
                    parcelId: PARCEL-EXAMPLE-1001
                    county: Cook
                    state: IL
                  timestamp: "2026-03-12T15:24:00.000Z"
      responses:
        '200':
          description: Verification completed and a signed verification receipt was issued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationResponse'
              examples:
                default:
                  summary: Verification response
                  value:
                    receiptVersion: '2.0'
                    status: clean
                    decision: ALLOW
                    reasons:
                      - receipt issued
                    receiptId: 2c17d2f5-4de6-48c3-b22c-0b7ea9eb5c0a
                    receiptHash: "0x4e7f2ce9d3f7a8d3b0e4c9f2aa17fd59d6b4fda2d7b7b7d1cce8124d7ee39d04"
                    receiptSignature:
                      alg: EdDSA
                      kid: trustsignal-current
                      signature: eyJleGFtcGxlIjoic2lnbmVkLXJlY2VpcHQifQ
                    anchor:
                      status: PENDING
                      subjectDigest: "0x8c0f95cda31274e7b61adfd1dd1e0c03a4b96f78d90da52d42fd93d9a38fc112"
                      subjectVersion: trustsignal.anchor_subject.v1
                    revocation:
                      status: ACTIVE
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/receipt/{receiptId}:
    get:
      tags: [Receipts]
      summary: Retrieve a stored verification receipt
      description: |
        Return the stored receipt view for a previously created verification,
        including receipt metadata, the canonical receipt payload, and a PDF URL.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/ReceiptId'
      responses:
        '200':
          description: Stored receipt returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationReceipt'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/receipt/{receiptId}/pdf:
    get:
      tags: [Receipts]
      summary: Download a PDF rendering of a stored verification receipt
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/ReceiptId'
      responses:
        '200':
          description: PDF returned.
          content:
            application/pdf:
              schema:
                type: string
                format: binary
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/receipt/{receiptId}/verify:
    post:
      tags: [Lifecycle]
      summary: Check later verification status for a stored receipt
      description: |
        Recompute receipt integrity and return the current verification status for later verification.
        This endpoint does not accept a request body.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/ReceiptId'
      responses:
        '200':
          description: Receipt verification status returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStatus'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/receipt/{receiptId}/revoke:
    post:
      tags: [Lifecycle]
      summary: Revoke a receipt when the caller is authorized
      description: |
        Mark a stored receipt as revoked. This endpoint does not accept a request body.
        In addition to the API key, issuer authorization headers are required.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/ReceiptId'
        - $ref: '#/components/parameters/IssuerId'
        - $ref: '#/components/parameters/SignatureTimestamp'
        - $ref: '#/components/parameters/IssuerSignature'
      responses:
        '200':
          description: Receipt revocation state returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RevocationResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/anchor/{receiptId}:
    post:
      tags: [Lifecycle]
      summary: Record verifiable provenance metadata for a receipt when enabled
      description: |
        Return the current provenance state for a receipt. This endpoint does not accept a request body.
        It is intended for workflows that use later verification with anchor subject metadata.
      security:
        - ApiKeyAuth: []
      parameters:
        - $ref: '#/components/parameters/ReceiptId'
      responses:
        '200':
          description: Provenance state returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnchorState'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: The receipt is not yet in a state that can expose provenance metadata.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: proof_artifact_required_for_anchor
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/receipts:
    get:
      tags: [Receipts]
      summary: List recent verification receipts
      description: Return a compact list of recent receipts for read-scoped integrations.
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: Receipt list returned.
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ReceiptListItem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
  /api/v1/verifications/github:
    post:
      tags: [Integrations]
      summary: Create a verification receipt from a GitHub Actions workflow event
      description: |
        GitHub-specific adapter over the standard receipt issuance path.
        Intended for use inside GitHub Actions workflows via the TrustSignal Verify Artifact action.
        The response includes a `receiptStatus` (frozen enum) and a `conclusion` compatible with GitHub check runs.
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GitHubVerificationRequest'
      responses:
        '200':
          description: Verification completed and receipt issued.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GitHubVerificationResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: |
        API key authentication. TrustSignal uses scoped API keys for the public `/api/v1/*` surface.
        Typical scopes are `verify`, `read`, `anchor`, and `revoke`.
  parameters:
    ReceiptId:
      name: receiptId
      in: path
      required: true
      description: Receipt identifier returned by `POST /api/v1/verify`.
      schema:
        type: string
        format: uuid
    IssuerId:
      name: x-issuer-id
      in: header
      required: true
      schema:
        type: string
      description: Authorized issuer identifier for receipt revocation.
    SignatureTimestamp:
      name: x-signature-timestamp
      in: header
      required: true
      schema:
        type: string
        format: date-time
      description: Timestamp used for issuer revocation authorization.
    IssuerSignature:
      name: x-issuer-signature
      in: header
      required: true
      schema:
        type: string
      description: Issuer authorization signature for receipt revocation.
  responses:
    BadRequest:
      description: Request validation failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid authentication material.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Forbidden:
      description: The caller is authenticated but not authorized for this operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: Requested verification receipt was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    TooManyRequests:
      description: Rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ServiceUnavailable:
      description: A required service dependency is unavailable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    VerificationRequest:
      type: object
      additionalProperties: false
      required:
        - bundleId
        - transactionType
        - ron
        - doc
        - policy
        - property
      properties:
        bundleId:
          type: string
          minLength: 1
          description: Caller-controlled verification identifier.
        transactionType:
          type: string
          minLength: 1
          description: Existing workflow transaction category.
        ron:
          type: object
          additionalProperties: false
          required:
            - provider
            - notaryId
            - commissionState
            - sealPayload
          properties:
            provider:
              type: string
            notaryId:
              type: string
            commissionState:
              type: string
              minLength: 2
              maxLength: 2
            sealPayload:
              type: string
            sealScheme:
              type: string
              enum: [SIM-ECDSA-v1]
        doc:
          type: object
          additionalProperties: false
          required:
            - docHash
          properties:
            docHash:
              type: string
              description: Artifact hash supplied by the caller.
            pdfBase64:
              type: string
              description: Optional artifact payload when the integration sends the full document.
        policy:
          type: object
          additionalProperties: false
          required:
            - profile
          properties:
            profile:
              type: string
              description: Policy or control identifier for the verification.
        property:
          type: object
          additionalProperties: false
          required:
            - parcelId
            - county
            - state
          properties:
            parcelId:
              type: string
            county:
              type: string
            state:
              type: string
              minLength: 2
              maxLength: 2
        ocrData:
          type: object
          additionalProperties: false
          properties:
            notaryName:
              type: string
            notaryCommissionId:
              type: string
            propertyAddress:
              type: string
            grantorName:
              type: string
        registryScreening:
          type: object
          additionalProperties: false
          properties:
            subjectName:
              type: string
              minLength: 2
              maxLength: 256
            sourceIds:
              type: array
              items:
                type: string
              minItems: 1
              maxItems: 50
            forceRefresh:
              type: boolean
        timestamp:
          type: string
          format: date-time
          description: Caller-provided event timestamp.
    ExternalReceiptStatus:
      type: string
      enum: [clean, failure, revoked, compliance_gap]
      description: |
        Frozen external status enum for all pilot-facing routes.
        - `clean` — verification passed (decision: ALLOW, not revoked)
        - `failure` — verification failed (decision: BLOCK)
        - `revoked` — receipt was revoked after issuance
        - `compliance_gap` — verification requires review (decision: FLAG)
    VerificationResponse:
      type: object
      additionalProperties: true
      required:
        - receiptVersion
        - status
        - decision
        - reasons
        - receiptId
        - receiptHash
        - anchor
        - revocation
      properties:
        receiptVersion:
          type: string
          example: '2.0'
        status:
          $ref: '#/components/schemas/ExternalReceiptStatus'
        decision:
          type: string
          enum: [ALLOW, FLAG, BLOCK]
          description: Internal verification signal. Use `status` for integrations.
        reasons:
          type: array
          items:
            type: string
        receiptId:
          type: string
          format: uuid
        receiptHash:
          type: string
        receiptSignature:
          $ref: '#/components/schemas/ReceiptSignature'
        anchor:
          $ref: '#/components/schemas/AnchorState'
        revocation:
          $ref: '#/components/schemas/RevocationState'
      description: |
        Public response fields for receipt issuance. Additional implementation-specific fields may also be present.
        The `status` field is the canonical external status for pilot integrations.
    VerificationReceipt:
      allOf:
        - $ref: '#/components/schemas/VerificationResponse'
        - type: object
          additionalProperties: true
          required:
            - receipt
            - canonicalReceipt
            - pdfUrl
          properties:
            receipt:
              $ref: '#/components/schemas/StoredReceipt'
            canonicalReceipt:
              type: string
              description: Canonical receipt payload used for later verification.
            pdfUrl:
              type: string
              description: Relative URL for the PDF rendering of the receipt.
    StoredReceipt:
      type: object
      additionalProperties: true
      required:
        - receiptVersion
        - receiptId
        - createdAt
        - policyProfile
        - inputsCommitment
        - checks
        - decision
        - reasons
        - receiptHash
      properties:
        receiptVersion:
          type: string
        receiptId:
          type: string
          format: uuid
        createdAt:
          type: string
          format: date-time
        policyProfile:
          type: string
        inputsCommitment:
          type: string
        checks:
          type: array
          items:
            $ref: '#/components/schemas/CheckResult'
        decision:
          type: string
          enum: [ALLOW, FLAG, BLOCK]
        reasons:
          type: array
          items:
            type: string
        receiptHash:
          type: string
        receiptSignature:
          $ref: '#/components/schemas/ReceiptSignature'
      description: |
        Stored receipt representation returned by the gateway. Integrations should rely on the documented receipt fields
        and should not infer internal engine behavior from optional fields.
    VerificationStatus:
      type: object
      additionalProperties: false
      required:
        - verified
        - integrityVerified
        - signatureVerified
        - signatureStatus
        - proofVerified
        - recomputedHash
        - storedHash
        - inputsCommitment
        - receiptSignature
        - revoked
      properties:
        verified:
          type: boolean
          description: Overall later verification result.
        integrityVerified:
          type: boolean
          description: Whether the stored receipt still matches its canonical hash.
        signatureVerified:
          type: boolean
          description: Whether the stored receipt signature verified.
        signatureStatus:
          type: string
          enum: [verified, invalid, unknown-kid, legacy-unsigned]
        signatureReason:
          type: string
        proofVerified:
          type: boolean
          description: Public verification status flag returned by the API.
        recomputedHash:
          type: string
        storedHash:
          type: string
        inputsCommitment:
          type: string
        receiptSignature:
          oneOf:
            - $ref: '#/components/schemas/ReceiptSignatureSummary'
            - type: 'null'
        revoked:
          type: boolean
    AnchorState:
      type: object
      additionalProperties: true
      required:
        - status
      properties:
        status:
          type: string
          description: Current provenance state for the receipt.
        anchoredAt:
          type: string
          format: date-time
        subjectDigest:
          type: string
          description: Verifiable provenance digest for later verification.
        subjectVersion:
          type: string
          description: Version label for the provenance digest format.
      description: |
        Public-safe provenance metadata. Implementations may return additional fields, but integrations should treat
        this object as provenance state rather than infrastructure detail.
    ReceiptListItem:
      type: object
      additionalProperties: false
      required:
        - receiptId
        - status
        - decision
        - createdAt
        - anchorStatus
        - revoked
      properties:
        receiptId:
          type: string
          format: uuid
        status:
          $ref: '#/components/schemas/ExternalReceiptStatus'
        decision:
          type: string
          enum: [ALLOW, FLAG, BLOCK]
          description: Internal verification signal. Use `status` for integrations.
        createdAt:
          type: string
          format: date-time
        anchorStatus:
          type: string
        revoked:
          type: boolean
    RevocationState:
      type: object
      additionalProperties: false
      required:
        - status
      properties:
        status:
          type: string
          enum: [ACTIVE, REVOKED, ALREADY_REVOKED]
    RevocationResponse:
      type: object
      additionalProperties: false
      required:
        - receiptStatus
        - result
      properties:
        receiptStatus:
          $ref: '#/components/schemas/ExternalReceiptStatus'
          description: Always `revoked` for both new and already-revoked receipts.
        result:
          type: string
          enum: [REVOKED, ALREADY_REVOKED]
          description: Operation outcome — whether this call performed the revocation or it was already done.
        issuerId:
          type: string
          description: Authorized issuer identifier, returned only when result is REVOKED.
    GitHubVerificationRequest:
      type: object
      additionalProperties: false
      required:
        - externalId
        - headSha
        - subject
        - repository
        - provenance
      properties:
        externalId:
          type: string
          description: Unique identifier for this GitHub Actions run (e.g. workflow_run_id).
        headSha:
          type: string
          description: Git commit SHA being verified.
        subject:
          type: object
          additionalProperties: false
          required: [kind, summary]
          properties:
            kind:
              type: string
              description: Artifact or event kind (e.g. workflow_run, pull_request).
            summary:
              type: string
              description: Human-readable summary of the subject.
        repository:
          type: object
          additionalProperties: false
          required: [fullName]
          properties:
            fullName:
              type: string
              description: GitHub repository full name (owner/repo).
            htmlUrl:
              type: string
              format: uri
        provenance:
          type: object
          additionalProperties: false
          required: [eventName]
          properties:
            eventName:
              type: string
              description: GitHub Actions trigger event (e.g. push, pull_request).
        detailsUrl:
          type: string
          format: uri
          description: Optional URL for GitHub check run details.
    GitHubVerificationResponse:
      type: object
      additionalProperties: false
      required:
        - receiptId
        - checkRunStatus
        - receiptStatus
        - conclusion
        - title
        - summary
        - verificationTimestamp
      properties:
        receiptId:
          type: string
          format: uuid
        checkRunStatus:
          type: string
          enum: [completed]
          description: GitHub check run status. Always `completed`.
        receiptStatus:
          $ref: '#/components/schemas/ExternalReceiptStatus'
        conclusion:
          type: string
          enum: [success, failure, neutral]
          description: GitHub check run conclusion mapped from receiptStatus.
        title:
          type: string
        summary:
          type: string
        verificationTimestamp:
          type: string
          format: date-time
        provenanceNote:
          type: string
        detailsUrl:
          type: string
          format: uri
    ReceiptSignature:
      type: object
      additionalProperties: false
      required:
        - alg
        - kid
        - signature
      properties:
        alg:
          type: string
          enum: [EdDSA]
        kid:
          type: string
        signature:
          type: string
          description: Signed receipt artifact returned by the API.
    ReceiptSignatureSummary:
      type: object
      additionalProperties: false
      required:
        - alg
        - kid
      properties:
        alg:
          type: string
          enum: [EdDSA]
        kid:
          type: string
    CheckResult:
      type: object
      additionalProperties: false
      required:
        - checkId
        - status
      properties:
        checkId:
          type: string
        status:
          type: string
          enum: [PASS, FAIL, WARN]
        details:
          type: string
    ErrorResponse:
      type: object
      additionalProperties: true
      required:
        - error
      properties:
        error:
          type: string
        message:
          type: string
        details:
          description: Optional validation or request context.
