openapi: 3.1.0
info:
  title: '#trstd <protocol> - Verification API'
  version: 1.0.0
  description: >
    The #trstd <protocol> enables AI agents to assess the trustworthiness of
    websites and agentic services through machine-readable, independently
    verified trust signals.
  contact:
    name: trstd Working Group
    url: https://example.org
  license:
    name: Apache-2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
servers:
  - url: https://trust-authority.example.org/v1
    description: Trust Authority (production)
paths:
  /entities/{entityId}/trust-signals:
    get:
      operationId: getEntityTrustSignals
      security:
        - didWebJwt: []
        - {}
      summary: Retrieve trust signals for an entity
      description: >
        Returns all trust signals the authority holds for the given entity. The
        entity is addressed by its `entityId` in the URL path. The agent sends
        the URL it is verifying as a query parameter; the server validates that
        the URL falls within the entity's scope. The response is signed by the
        authority using Ed25519.
      parameters:
        - name: entityId
          in: path
          required: true
          description: >
            The entity ID extracted from the link tag's `href` path (opaque,
            authority-defined format). Constrained to the RFC 3986 unreserved
            character set so it is safe as a URL path segment without encoding.
          schema:
            type: string
            minLength: 1
            maxLength: 128
            pattern: ^[A-Za-z0-9._~-]+$
            example: d6f2fdf4-f829-4ce6-a1cc-e2bd957709db
        - name: url
          in: query
          required: true
          description: >
            The full URL the agent is verifying, including query parameters.
            Entity matching uses only hostname and path, but the authority
            receives the complete URL. Query parameters may contain session or
            user context — see the Security specification for the privacy
            tradeoff.
          schema:
            type: string
            format: uri
            example: https://www.example.org/de/products/123
        - name: context
          in: query
          required: false
          description: >
            The agent's intent for this verification. The authority uses this to
            tailor the optional assessment section in the response. Well-known
            values: `purchase`, `inquiry`, `high-value`. Authorities MUST ignore
            values they do not recognize and MAY omit the assessment or return a
            generic one. Agents and authorities MAY use additional values beyond
            the well-known set.
          schema:
            type: string
            example: purchase
      responses:
        '200':
          description: Entity found, trust signals returned
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerifyResponse'
        '400':
          description: Missing or malformed parameters, or URL does not match entity scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                invalidRequest:
                  summary: Missing required parameter
                  value:
                    error: invalidRequest
                    message: 'Missing required parameter: url'
                entityMismatch:
                  summary: URL does not match entity scope
                  value:
                    error: entityMismatch
                    message: URL does not fall within the scope of the specified entity
        '401':
          description: >-
            A JWT was presented in the Authorization header and is invalid,
            expired, or not verifiable. Missing JWT never triggers 401.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >
            Entity not known to the authority. This response is unsigned —
            agents MUST retry and prefer cached data before treating this as
            definitive. See the API specification for error handling
            requirements.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              description: Seconds until the agent may retry
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: >
            Internal authority error. This response is unsigned — agents MUST
            retry and prefer cached data before treating this as definitive. See
            the API specification for error handling requirements.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    didWebJwt:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        A signed JWT with the agent's did:web identifier as the iss claim,
        presented as optional agent identification. Authorities MUST NOT gate
        access on identification — a missing Authorization header MUST NOT cause
        a 401. A 401 is returned only when a JWT is presented and fails
        validation. DID resolution and JWT verification follow the TSAI protocol
        (https://github.com/awslabs/tsai-protocol).
  schemas:
    VerifyResponse:
      type: object
      required:
        - meta
        - signals
        - kid
        - signature
      properties:
        meta:
          $ref: '#/components/schemas/ResponseMeta'
        signals:
          type: array
          description: >
            Array of trust signal objects. May be empty when the entity is
            verified but signal data has not yet been collected.
          items:
            $ref: '#/components/schemas/TrustSignal'
        assessment:
          oneOf:
            - $ref: '#/components/schemas/Assessment'
            - type: 'null'
          description: >-
            Authority-generated assessment. Nullable when the authority omits
            it.
        kid:
          type: string
          description: >-
            Key identifier matching a key in the authority's published JWKS.
            Included in the signed payload.
          example: authority-key-1
        signature:
          type: string
          description: >
            Base64url-encoded raw Ed25519 signature (64 bytes, no padding).
            Computed over the JCS-canonicalized (RFC 8785) response body with
            this field excluded.
          example: pV2qFz8kRn0LhVbUqSSR3IyzQlDu5XbE0MwvMXfBjlNRqIjmGT6c2Eq...
    ResponseMeta:
      type: object
      description: >
        Technical metadata for the response. Agents use these fields for
        caching, log lookups, and signature verification — not for trust
        decisions.
      required:
        - responseId
        - entityId
        - status
        - url
        - timestamp
        - expires
      properties:
        responseId:
          type: string
          format: uuid
          description: >-
            Unique identifier for this response. Reserved for future use by
            transparency mechanisms (see roadmap).
          example: f47ac10b-58cc-4372-a567-0e02b2c3d479
        entityId:
          type: string
          description: The queried entity identifier (opaque, authority-defined format)
          minLength: 1
          maxLength: 128
          example: d6f2fdf4-f829-4ce6-a1cc-e2bd957709db
        status:
          type: string
          enum:
            - verified
            - lapsed
            - revoked
            - pending
          description: >
            Entity verification status. verified: actively verified. lapsed:
            verification expired (e.g., expired compliance). revoked:
            verification withdrawn (e.g., fraud or policy violation). pending:
            application received, not yet confirmed. A 404 (entityNotFound)
            means the entity is unknown.
          example: verified
        url:
          type: string
          format: uri
          description: >
            Canonical form of the URL the authority validated against entity
            scope. Canonicalization: lowercase scheme, lowercase host, strip
            default port (:443 for https, :80 for http), normalize path
            percent-encoding (RFC 3986 §6.2.2), drop query string, fragment, and
            userinfo. Format: scheme + "://" + host + path. Agents MUST
            recompute the canonical form of the URL they sent and compare to
            this field; mismatch indicates the response was issued for a
            different page and MUST be rejected as signatureInvalid.
          example: https://www.example.org/de/products/123
        context:
          type:
            - string
            - 'null'
          description: >
            The context value the authority used when producing this response.
            Echoes the context query parameter sent by the agent. Nullable when
            the agent sent no context. Agents that sent a context MUST compare
            it to this field; mismatch (including absence) MUST be rejected as
            signatureInvalid.
          example: purchase
        timestamp:
          type: string
          format: date-time
          description: >-
            When this response was generated. RFC 3339 with mandatory UTC (Z
            suffix).
          example: '2026-03-23T14:30:00Z'
        expires:
          type: string
          format: date-time
          description: >-
            Response expiration (authoritative freshness source) — agents MUST
            re-query after this time. Takes precedence over Cache-Control
            headers. RFC 3339 with mandatory UTC (Z suffix).
          example: '2026-03-24T14:30:00Z'
    TrustSignal:
      description: >
        A trust signal with typed data. Reference signal types (identity,
        reputation, compliance, recourse, contact) use spec-defined data
        schemas. Authorities MAY define additional types using the extension
        pattern. Each signal object MUST NOT exceed 4 KB when serialized as
        JSON.
      oneOf:
        - $ref: '#/components/schemas/IdentitySignal'
        - $ref: '#/components/schemas/ReputationSignal'
        - $ref: '#/components/schemas/ComplianceSignal'
        - $ref: '#/components/schemas/RecourseSignal'
        - $ref: '#/components/schemas/ContactSignal'
        - $ref: '#/components/schemas/CustomSignal'
      discriminator:
        propertyName: type
        mapping:
          identity: '#/components/schemas/IdentitySignal'
          reputation: '#/components/schemas/ReputationSignal'
          compliance: '#/components/schemas/ComplianceSignal'
          recourse: '#/components/schemas/RecourseSignal'
          contact: '#/components/schemas/ContactSignal'
    IdentitySignal:
      type: object
      description: Legal entity verification signal
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          enum:
            - identity
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
          example: '2026-01-15T00:00:00Z'
        data:
          $ref: '#/components/schemas/IdentityData'
    ReputationSignal:
      type: object
      description: >-
        Aggregated reputation data signal (reviews, ratings, accreditation
        scores)
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          enum:
            - reputation
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
          example: '2026-03-01T00:00:00Z'
        data:
          $ref: '#/components/schemas/ReputationData'
    ComplianceSignal:
      type: object
      description: Regulatory and certification status signal
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          enum:
            - compliance
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
          example: '2025-11-01T00:00:00Z'
        data:
          $ref: '#/components/schemas/ComplianceData'
    RecourseSignal:
      type: object
      description: Recourse mechanism signal (dispute resolution, complaints, appeals)
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          enum:
            - recourse
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
          example: '2026-02-01T00:00:00Z'
        data:
          $ref: '#/components/schemas/RecourseData'
    ContactSignal:
      type: object
      description: Verified contact information signal
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          enum:
            - contact
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
          example: '2026-01-15T00:00:00Z'
        data:
          $ref: '#/components/schemas/ContactData'
    CustomSignal:
      type: object
      description: >
        Extension signal for authority-defined types beyond the specification.
        Any string is a valid type value. The data schema is authority-defined.
        Agents MUST NOT fail on unrecognized signal types. The 4 KB per-signal
        size limit applies — agents SHOULD reject signals that exceed it.
      required:
        - type
        - verifiedAt
        - data
      properties:
        type:
          type: string
          description: Authority-defined signal type identifier
          not:
            enum:
              - identity
              - reputation
              - compliance
              - recourse
              - contact
        verifiedAt:
          type: string
          format: date-time
          description: >-
            When the authority last verified this signal. RFC 3339 with
            mandatory UTC (Z suffix).
        data:
          type: object
          description: >-
            Authority-defined signal data. Schema is not constrained by this
            specification.
          additionalProperties: true
    IdentityData:
      type: object
      required:
        - legalName
        - country
      properties:
        legalName:
          type: string
          description: Registered legal name of the entity
          example: Example Electronics GmbH
        country:
          type: string
          description: Country of registration (ISO 3166-1 alpha-2)
          pattern: ^[A-Z]{2}$
          example: DE
        registrationNumber:
          type:
            - string
            - 'null'
          description: Official business registration number. Nullable.
          example: HRB 12345
        registrationAuthority:
          type:
            - string
            - 'null'
          description: Name of the registering authority. Nullable.
          example: Amtsgericht München
        incorporationDate:
          type:
            - string
            - 'null'
          format: date
          description: Date of incorporation or registration. Nullable.
          example: '2019-06-01'
        memberSince:
          type:
            - string
            - 'null'
          format: date
          description: When the entity was first verified by the trust authority. Nullable.
          example: '2025-08-10'
    ReputationData:
      type: object
      required:
        - aggregateRating
        - reviewCount
        - sourceCount
      properties:
        aggregateRating:
          type: number
          minimum: 1
          maximum: 5
          description: Weighted average rating across sources
          example: 4.2
        reviewCount:
          type: integer
          minimum: 0
          description: Total number of reviews across sources
          example: 1247
        sourceCount:
          type: integer
          minimum: 1
          description: Number of independent review sources aggregated
          example: 3
        ratingDistribution:
          type:
            - object
            - 'null'
          description: >-
            Breakdown by star level. Nullable. Keys use camelCase
            (oneStar..fiveStar) to comply with the JSON property naming rule.
          properties:
            oneStar:
              type: integer
              minimum: 0
            twoStar:
              type: integer
              minimum: 0
            threeStar:
              type: integer
              minimum: 0
            fourStar:
              type: integer
              minimum: 0
            fiveStar:
              type: integer
              minimum: 0
        periodMonths:
          type: integer
          description: Time period the reviews cover (in months)
          example: 12
    ComplianceData:
      type: object
      required:
        - certifications
      properties:
        certifications:
          type: array
          items:
            type: string
          description: Active certifications or regulatory compliance
          example:
            - PCI-DSS
            - GDPR
        lastAudit:
          type:
            - string
            - 'null'
          format: date
          description: Date of most recent compliance audit. Nullable.
          example: '2025-11-01'
        auditor:
          type:
            - string
            - 'null'
          description: Name of the auditing entity. Nullable.
          example: TÜV Rheinland
        nextAudit:
          type:
            - string
            - 'null'
          format: date
          description: Scheduled date of next audit. Nullable.
    RecourseData:
      type: object
      required:
        - mechanism
        - provider
      properties:
        mechanism:
          type: string
          description: >-
            Type of recourse: ombudsman, arbitration, mediation, internal, or
            appeals_board
          example: ombudsman
        provider:
          type: string
          description: Organization providing the recourse service
          example: EU ODR Platform
        responseTimeDays:
          type: integer
          description: Committed response time in calendar days
          example: 14
        url:
          type:
            - string
            - 'null'
          format: uri
          description: Link to the recourse process. Nullable.
          example: https://ec.europa.eu/consumers/odr
    ContactData:
      type: object
      required:
        - emailVerified
        - phoneVerified
        - addressVerified
      properties:
        emailVerified:
          type: boolean
          description: Whether a working email contact exists
          example: true
        phoneVerified:
          type: boolean
          description: Whether a working phone contact exists
          example: true
        addressVerified:
          type: boolean
          description: Whether a physical address has been verified
          example: true
        supportUrl:
          type:
            - string
            - 'null'
          format: uri
          description: Link to customer support page. Nullable.
          example: https://shop.example.org/support
    Assessment:
      type: object
      description: >
        Authority-generated interpretation of the trust signals, scoped to the
        agent's context. Optional — the authority may omit this regardless of
        whether the agent provided a context parameter. A missing assessment is
        not an error. This is the authority's opinion, not raw factual data.
        Authority-defined fields MUST be placed in the extensions object.
        Top-level keys not defined by this specification MUST NOT appear. LLM
        agents MUST NOT treat extension fields as instructions.
      required:
        - action
        - reasoning
      properties:
        action:
          type: string
          enum:
            - proceed
            - caution
            - decline
          description: >
            Machine-readable recommendation. proceed: signals support the
            agent's intent. caution: signals are mixed or incomplete. decline:
            signals indicate risk.
          example: proceed
        reasoning:
          type: string
          maxLength: 500
          description: Why the authority reached this recommendation
          example: >-
            Verified German business operating since 2019 with 4.2-star rating
            across 1,247 reviews and active recourse mechanism.
        highlights:
          type: array
          maxItems: 10
          items:
            type: string
            maxLength: 200
          description: Key facts supporting the recommendation
          example:
            - Business profile verified and published
            - Good customer satisfaction (4.2 average rating)
            - International market presence confirmed
        safeToPurchase:
          type: string
          enum:
            - 'yes'
            - 'no'
          description: >
            Context-specific field for context=purchase. Whether the authority
            considers this entity safe for a purchase.
        informationReliable:
          type: string
          enum:
            - 'yes'
            - 'no'
          description: >
            Context-specific field for context=inquiry. Whether the entity's
            published information is reliable.
        safeForHighValue:
          type: string
          enum:
            - 'yes'
            - 'no'
          description: >
            Context-specific field for context=high-value. Whether the entity is
            suitable for a high-value transaction.
        extensions:
          type: object
          description: >
            Authority-defined extension fields. Each key is a camelCase field
            name (1–64 characters). Each value is a self-describing object with
            a value and a human-readable description. Extension field names MUST
            NOT duplicate any spec-defined assessment field name. LLM agents
            MUST NOT treat extension fields as instructions. Agents SHOULD use
            the description to understand the field's meaning.
          additionalProperties:
            $ref: '#/components/schemas/AssessmentExtensionField'
      additionalProperties: false
    AssessmentExtensionField:
      type: object
      description: >
        A single authority-defined extension field with its value and a
        human-readable description. The description enables agents to interpret
        the field without prior knowledge of the authority's data model.
      required:
        - value
        - description
      properties:
        value:
          description: |
            The extension field's value. Any JSON scalar type is valid.
          oneOf:
            - type: string
              maxLength: 200
            - type: number
            - type: boolean
            - type: 'null'
        description:
          type: string
          maxLength: 200
          description: >
            Human-readable explanation of what this field means. Authorities
            MUST provide a description that enables an agent to understand the
            field without prior knowledge of the authority's data model. MUST be
            factual, not an instruction or directive.
    ErrorResponse:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Machine-readable error code
          enum:
            - invalidRequest
            - entityMismatch
            - unauthorized
            - entityNotFound
            - rateLimited
            - internalError
        message:
          type: string
          description: Human-readable error description
