{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/freightutils-com/json-schema/freightutils-com-resolve-response-schema.json",
  "title": "ResolveResponse",
  "description": "Envelope v1.1 (native); ?envelope=1.2 adds status, missing_inputs, edition and as_of (EnvelopeV12Fields). result holds the resolution; each candidate carries its own dataset citation. Zero candidates is ok:true with count 0 and a note, never an error.",
  "x-generated": "2026-11-09",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/freightutils-com-openapi.json#/components/schemas/ResolveResponse",
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean"
    },
    "envelope_version": {
      "type": "string",
      "enum": [
        "1",
        "1.1",
        "1.2"
      ]
    },
    "result": {
      "type": "object",
      "properties": {
        "query": {
          "type": "string"
        },
        "normalized": {
          "type": "string",
          "description": "After trim, uppercase, space/dash collapse and UN-prefix strip."
        },
        "candidates": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ResolveCandidate"
          }
        },
        "count": {
          "type": "integer"
        },
        "note": {
          "type": "string",
          "description": "Present only when count is 0: 'no known freight identifier grammar matched'."
        },
        "validation": {
          "type": "object",
          "description": "When the query is an identifier with a check digit (AWB, container, IMO): the check, run as it resolved.",
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "awb",
                "container",
                "imo"
              ]
            },
            "valid": {
              "type": "boolean"
            },
            "failure": {
              "$ref": "#/$defs/ValidationFailure"
            }
          }
        },
        "failure": {
          "type": "object",
          "description": "NO_MATCH (no grammar matched) or AMBIGUOUS (several candidates; candidate_types names them).",
          "properties": {
            "reason": {
              "type": "string",
              "enum": [
                "NO_MATCH",
                "AMBIGUOUS"
              ]
            },
            "message": {
              "type": "string"
            },
            "candidate_types": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        }
      },
      "required": [
        "query",
        "normalized",
        "candidates",
        "count"
      ]
    },
    "confidence": {
      "type": "object",
      "description": "high/deterministic when candidates exist; low/deterministic with a NO_MATCH warning when none do."
    },
    "warnings": {
      "type": "array",
      "description": "Advisory only. NO_MATCH is emitted on every count:0 response.",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    },
    "normalized_input": {
      "type": "object",
      "description": "Present when normalization changed the query (lowercase, spacing, dashes, UN prefix): q_input + normalized."
    },
    "blocking_errors": {
      "type": "array",
      "description": "Present on the 400 branches only: MISSING_INPUT (no q) or INVALID_INPUT (over the 32-char single-token limit).",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "recovery": {
            "type": "object"
          }
        }
      }
    },
    "citation": {
      "type": "object",
      "description": "Top-level one-line citation for the resolution itself; per-candidate dataset citations live on each candidate."
    },
    "_source": {
      "$ref": "#/$defs/EnvelopeSource"
    },
    "status": {
      "type": "string",
      "enum": [
        "ok",
        "partial",
        "not_found",
        "unsupported",
        "ambiguous"
      ]
    },
    "missing_inputs": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Input names a partial answer needs; empty otherwise."
    },
    "edition": {
      "type": [
        "object",
        "null"
      ],
      "description": "Served edition; null for computed or live answers.",
      "properties": {
        "name": {
          "type": "string"
        },
        "applies_from": {
          "type": [
            "string",
            "null"
          ]
        },
        "may_apply_until": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "as_of": {
      "type": "string",
      "description": "The served dataset's audited date (YYYY-MM-DD)."
    }
  },
  "required": [
    "ok",
    "envelope_version",
    "result",
    "confidence",
    "citation"
  ],
  "$defs": {
    "EnvelopeSource": {
      "type": "object",
      "description": "The envelope `_source` block (v1.1 / 1.2): the authority or method, when it was last audited (or request-time), and its provenance status. Distinct from the legacy flat-body SourceEnvelope.",
      "required": [
        "name",
        "checked",
        "provenance_status"
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "checked": {
          "type": "string",
          "description": "YYYY-MM-DD of the last content audit, or \"request-time\"."
        },
        "provenance_status": {
          "type": "string",
          "enum": [
            "verified",
            "pending-verification",
            "computed",
            "live"
          ]
        },
        "source_url": {
          "type": "string"
        },
        "dataset_edition": {
          "type": "string"
        },
        "authority_current_edition": {
          "type": "string"
        },
        "checked_at": {
          "type": "string"
        }
      }
    },
    "ResolveCandidate": {
      "type": "object",
      "description": "One resolution candidate. Ambiguity is the product: colliding grammars each contribute candidates, ranked deterministically with an inspectable rank_basis.",
      "properties": {
        "entity_type": {
          "type": "string",
          "description": "What the candidate is: dangerous_good, airline, airport, location, hs_classification, incoterm, container_type, container_equipment, uld_type, tunnel_restriction, adr_code, air_waybill, vessel."
        },
        "identifier_type": {
          "type": "string",
          "description": "Which grammar matched: un_number, awb_prefix, airline_iata, airline_icao, airport_iata, airport_icao, unlocode, container_number, hs_code, incoterm, tunnel_code, uld_type, iso_container_type, adr_code, awb_number, imo_number; airport_ident or airline_slug for a record with no usable code."
        },
        "value_normalized": {
          "type": "string"
        },
        "summary": {
          "type": "string",
          "description": "One-line human summary of the candidate."
        },
        "record": {
          "type": [
            "object",
            "null"
          ],
          "description": "Core fields from the matching dataset. Null for a pattern-only match (the value fits a grammar but is not in the served dataset)."
        },
        "verification_status": {
          "type": "string",
          "description": "Normalized across datasets: active_verified, verified, computed, partial, pending_verification, unchecked, unverified, historical, pattern_only."
        },
        "verification_basis": {
          "type": "string",
          "enum": [
            "record",
            "dataset"
          ],
          "description": "record = from this record's own provenance fields; dataset = the dataset-level claim (no record-level signal exists)."
        },
        "rank_basis": {
          "type": "string",
          "description": "Why the candidate sits where it does: record hit > verification status > static dataset prior > stable tiebreak."
        },
        "canonical_url": {
          "type": "string",
          "description": "The record's page on freightutils.com, where one exists. Omitted otherwise."
        },
        "api_url": {
          "type": "string",
          "description": "The dataset's REST query for this record, where one exists."
        },
        "citation": {
          "type": "object",
          "description": "The matching dataset's own citation for this record (text + optional qualifier).",
          "properties": {
            "text": {
              "type": "string"
            },
            "qualifier": {
              "type": "string"
            }
          },
          "required": [
            "text"
          ]
        }
      },
      "required": [
        "entity_type",
        "identifier_type",
        "value_normalized",
        "summary",
        "record",
        "verification_status",
        "verification_basis",
        "rank_basis",
        "citation"
      ]
    },
    "ValidationFailure": {
      "type": "object",
      "description": "Why an identifier failed: a stable reason code, a message, the expected format and an example.",
      "properties": {
        "reason": {
          "type": "string",
          "enum": [
            "INVALID_CHECK_DIGIT",
            "WRONG_LENGTH",
            "BAD_CHARSET",
            "UNKNOWN_PREFIX",
            "UNSUPPORTED_TYPE",
            "AMBIGUOUS"
          ]
        },
        "message": {
          "type": "string"
        },
        "expected_format": {
          "type": "string"
        }
      },
      "required": [
        "reason",
        "message",
        "expected_format",
        "example"
      ]
    }
  }
}