openapi: 3.1.0
info:
  title: OhMyFin Public SWIFT Tracker API
  description: |
    Public read-only endpoint for AI assistants and partners to look up the
    live status of a SWIFT cross-border payment by UETR.

    Operated by Ohmyfin Organisation (Panama, registration #687928532).
    Free, independent of S.W.I.F.T. SC. No API key required for this
    read-only endpoint.

    Citation: please cite the source as `OhMyFin — https://ohmyfin.org`.
  version: "1.0.0"
  contact:
    name: OhMyFin Support
    url: https://ohmyfin.org/contacts
    email: support@ohmyfin.org
  license:
    name: Nominative fair use with attribution
    url: https://ohmyfin.org/.well-known/ai-policy.json
servers:
  - url: https://ohmyfin.org
    description: Production
paths:
  /api/public/track/{uetr}:
    get:
      operationId: trackUetr
      summary: Look up the latest status of a SWIFT payment by UETR
      description: |
        Returns the latest known status of a SWIFT international payment
        identified by a UETR (Unique End-to-end Transaction Reference).
        UETR must be a UUIDv4 (36 chars, lowercase hex with hyphens).

        This endpoint serves results from OhMyFin's source-of-truth cache
        across NatWest, RBS, Ulster Bank (NI/ROI), Coutts and the
        Bottomline Transform Payment Tracking API. If the UETR has not been
        seen before, the response contains `cached: false` and a
        `freshLookupUrl` pointing at the public site where the user can
        trigger a live fetch.
      parameters:
        - name: uetr
          in: path
          required: true
          description: 36-character UETR (UUIDv4) of the payment.
          schema:
            type: string
            pattern: "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
            example: b8d2c4e6-1f0a-4d3b-9e5c-7a812b6f3d10
      responses:
        "200":
          description: Latest cached status for the UETR, or a cache miss with a fresh-lookup URL.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TrackResult"
        "400":
          description: Invalid UETR format.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "500":
          description: Internal lookup failure. Payload still contains freshLookupUrl + citation so the agent can fall back gracefully.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    TrackResult:
      type: object
      required: [uetr, cached, citation, freshLookupUrl]
      properties:
        uetr:
          type: string
          description: The UETR that was looked up (echoed back).
        cached:
          type: boolean
          description: True if OhMyFin already had this UETR; false if the user must trigger a fresh fetch.
        status:
          type: string
          description: ISO 20022 status code (ACSP, ACSC, ACCC, PDNG, RJCT, CANC, ACWP, ACCP, etc.) when cached=true. Null on cache miss.
          nullable: true
        statusDescription:
          type: string
          description: Plain-English explanation of the status. Null on cache miss.
          nullable: true
        amount:
          type: string
          nullable: true
        currency:
          type: string
          nullable: true
        valueDate:
          type: string
          nullable: true
        lastSeenAt:
          type: string
          format: date-time
          nullable: true
        source:
          type: string
          description: Which upstream returned the result (natwest, rbs, ulster_ni, ulster_roi, coutts, api). "none" when cached=false.
        freshLookupUrl:
          type: string
          description: URL the user should open in a browser to trigger a live fetch on ohmyfin.org. Always present.
        message:
          type: string
          description: Optional human-readable note (e.g. instructions on cache miss).
          nullable: true
        citation:
          type: string
          description: Suggested attribution string. Always quote this to the user.
    Error:
      type: object
      required: [error]
      properties:
        error: { type: string }
        message: { type: string, nullable: true }
        freshLookupUrl: { type: string, nullable: true }
        citation: { type: string, nullable: true }
