{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/aibuildermarketplace-com/json-schema/aibuildermarketplace-com-product-schema.json",
  "title": "Product",
  "x-generated": "2026-11-01",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/aibuildermarketplace-com-openapi.json#/components/schemas/Product",
  "type": "object",
  "required": [
    "id",
    "name",
    "pricing",
    "purchase",
    "unknowns"
  ],
  "properties": {
    "schema_version": {
      "type": "string"
    },
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "vendor_domain": {
      "type": [
        "string",
        "null"
      ]
    },
    "category": {
      "type": "string"
    },
    "task": {
      "type": [
        "string",
        "null"
      ]
    },
    "summary": {
      "type": [
        "string",
        "null"
      ]
    },
    "best_for": {
      "type": [
        "string",
        "null"
      ]
    },
    "skip_if": {
      "type": [
        "string",
        "null"
      ]
    },
    "honest_knock": {
      "type": [
        "string",
        "null"
      ]
    },
    "pricing": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string"
        },
        "entry_price": {
          "type": [
            "string",
            "null"
          ]
        },
        "entry_price_terms": {
          "type": [
            "string",
            "null"
          ]
        },
        "from_price_usd_month": {
          "type": [
            "number",
            "null"
          ],
          "description": "Only when the entry price is US dollars per month. The lowest entry price, often on annual billing: read entry_price_terms"
        },
        "schema_offer": {
          "type": [
            "object",
            "null"
          ],
          "description": "The Offer exactly as it appears in the JSON-LD of the canonical review (what search engines read): one plan's price without commitment where known, with plan and billing basis in description. It can differ from from_price_usd_month, which is the lowest entry price.",
          "properties": {
            "price": {
              "type": "number"
            },
            "currency": {
              "type": [
                "string",
                "null"
              ]
            },
            "description": {
              "type": [
                "string",
                "null"
              ]
            },
            "page": {
              "type": "string"
            }
          }
        },
        "plans": {
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/$defs/Plan"
          }
        },
        "plans_source": {
          "type": [
            "string",
            "null"
          ]
        },
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "verified_at": {
          "type": [
            "string",
            "null"
          ]
        },
        "source_url": {
          "type": [
            "string",
            "null"
          ]
        },
        "recent_change": {
          "type": [
            "object",
            "null"
          ],
          "description": "A buyer-relevant change from the vendor's own changelog or release notes in the last 6 months (plan renamed or dropped, new limit or meter, pricing model, feature moved to a pricier plan or removed), checked by us against the source. date = when the vendor made the change; read_at = when we read it.",
          "properties": {
            "date": {
              "type": [
                "string",
                "null"
              ]
            },
            "text": {
              "type": [
                "string",
                "null"
              ]
            },
            "source_url": {
              "type": [
                "string",
                "null"
              ]
            },
            "read_at": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        },
        "source_quotes": {
          "type": [
            "array",
            "null"
          ],
          "description": "Verbatim lines from the vendor's own pages (max 200 characters), each matched word for word against the live page on read_on. Only quotes that still agree with pricing.notes.",
          "items": {
            "type": "object",
            "properties": {
              "field": {
                "type": "string",
                "enum": [
                  "price",
                  "free_trial",
                  "refund"
                ]
              },
              "plan": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "quote": {
                "type": "string"
              },
              "source_url": {
                "type": "string"
              },
              "read_on": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "verification": {
      "type": "object",
      "description": "Per core field: 'quoted' (a verbatim vendor line is in pricing.source_quotes), 'read' (read on the vendor's page on pricing.verified_at, summarised in pricing.notes) or 'being_verified' (not yet matched; not the same as 'does not exist'). 'measured' means a confirmed hands-on trial-duration claim in measured.claims; it does not confirm all trial terms or create a vendor quote.",
      "properties": {
        "price": {
          "type": "string",
          "enum": [
            "quoted",
            "read",
            "being_verified",
            "measured"
          ]
        },
        "free_trial": {
          "type": "string",
          "enum": [
            "quoted",
            "read",
            "being_verified",
            "measured"
          ]
        },
        "refund": {
          "type": "string",
          "enum": [
            "quoted",
            "read",
            "being_verified",
            "measured"
          ]
        }
      }
    },
    "status_page": {
      "$ref": "#/$defs/StatusPage"
    },
    "measured": {
      "$ref": "#/$defs/Measured"
    },
    "third_party_video": {
      "type": "object",
      "description": "Optional. A YouTube video by another channel that shows the product in use (not ours, not a paid promotion when independent is true). Absent means none was checked or none qualified.",
      "properties": {
        "url": {
          "type": "string"
        },
        "channel": {
          "type": "string"
        },
        "published": {
          "type": [
            "string",
            "null"
          ]
        },
        "shows": {
          "type": [
            "string",
            "null"
          ]
        },
        "independent": {
          "type": "boolean"
        },
        "checked_at": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "free_plan": {
      "type": "boolean"
    },
    "cost_traps": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/CostTrap"
      }
    },
    "compare_with": {
      "type": [
        "object",
        "null"
      ]
    },
    "links": {
      "type": "object"
    },
    "purchase": {
      "type": "object",
      "properties": {
        "seller": {
          "type": "string"
        },
        "how": {
          "type": "string"
        },
        "handoff_url": {
          "type": [
            "string",
            "null"
          ]
        },
        "affiliate": {
          "type": "boolean"
        },
        "disclosure": {
          "type": "string"
        }
      }
    },
    "unknowns": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "provenance": {
      "type": "object"
    }
  },
  "$defs": {
    "CostTrap": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "enum": [
            "quote_only",
            "per_seat",
            "usage_metered",
            "renewal_jump",
            "addons_extra",
            "annual_lock"
          ]
        },
        "label": {
          "type": "string"
        },
        "evidence": {
          "type": "string",
          "description": "Full evidence sentence from the dossier, never truncated"
        },
        "verified_at": {
          "type": [
            "string",
            "null"
          ]
        },
        "source_url": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "Measured": {
      "type": "object",
      "additionalProperties": false,
      "description": "Own hands-on session from handson/<map>/meetlog.json; absent without a matching log. roles/api_access/downgrade are omitted when unknown; API availability is a UI observation, not a key or call test. tested_on is the original session date, not the rebuild date; claims and exit tests carry their own observation dates. Unknown facts are not_tested, never inferred from absence. tested_by identifies our team; the actor, account type and blocked/limited attempts are in the review.",
      "required": [
        "tested_on",
        "tested_by",
        "review_url",
        "method",
        "claims",
        "exit_test",
        "facts",
        "inbox",
        "invites",
        "entry_exit",
        "support",
        "onboarding"
      ],
      "properties": {
        "tested_on": {
          "type": "string",
          "format": "date"
        },
        "tested_by": {
          "type": "string"
        },
        "review_url": {
          "type": "string",
          "format": "uri"
        },
        "method": {
          "type": "array",
          "maxItems": 7,
          "items": {
            "type": "string"
          },
          "description": "Recorded actions from hands_on.methode; empty when no session steps were retained."
        },
        "claims": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/MeasuredClaim"
          }
        },
        "inbox": {
          "$ref": "#/$defs/MeasuredInbox"
        },
        "invites": {
          "$ref": "#/$defs/MeasuredInvites"
        },
        "entry_exit": {
          "$ref": "#/$defs/MeasuredEntryExit"
        },
        "support": {
          "$ref": "#/$defs/MeasuredSupport"
        },
        "onboarding": {
          "$ref": "#/$defs/MeasuredOnboarding"
        },
        "roles": {
          "$ref": "#/$defs/MeasuredRoles"
        },
        "api_access": {
          "$ref": "#/$defs/MeasuredApiAccess"
        },
        "downgrade": {
          "$ref": "#/$defs/MeasuredDowngrade"
        },
        "exit_test": {
          "$ref": "#/$defs/MeasuredExitTest"
        },
        "facts": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "trial_requires_card",
            "trial_duration_confirmed",
            "export_file_inspected",
            "export_reimport_tested",
            "export_direct_download",
            "marketing_emails_14d"
          ],
          "properties": {
            "trial_requires_card": {
              "$ref": "#/$defs/MeasuredFact"
            },
            "trial_duration_confirmed": {
              "$ref": "#/$defs/MeasuredFact"
            },
            "export_file_inspected": {
              "$ref": "#/$defs/MeasuredFact"
            },
            "export_reimport_tested": {
              "$ref": "#/$defs/MeasuredFact"
            },
            "export_direct_download": {
              "$ref": "#/$defs/MeasuredFact"
            },
            "marketing_emails_14d": {
              "$ref": "#/$defs/MeasuredCountFact"
            }
          }
        }
      }
    },
    "MeasuredApiAccess": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "plan",
        "route",
        "quote",
        "evidence",
        "status"
      ],
      "properties": {
        "plan": {
          "type": "string",
          "pattern": "\\S"
        },
        "route": {
          "type": "string",
          "pattern": "\\S"
        },
        "quote": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "text",
            "source_url",
            "observed_at"
          ],
          "properties": {
            "text": {
              "type": "string",
              "pattern": "\\S"
            },
            "source_url": {
              "type": "string",
              "format": "uri",
              "pattern": "^https?://[^/\\s?#]+(?:[^\\s]*)$"
            },
            "observed_at": {
              "type": "string",
              "format": "date-time"
            }
          }
        },
        "evidence": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^bewijs/[a-zA-Z0-9_.-]+\\.(jpg|png|webp)$"
          }
        },
        "status": {
          "enum": [
            "available_on_tested_plan",
            "gated",
            "not_found_in_ui"
          ]
        },
        "gated_plan": {
          "type": "string",
          "pattern": "\\S"
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "status": {
                "const": "gated"
              }
            }
          },
          "then": {
            "required": [
              "gated_plan"
            ]
          },
          "else": {
            "not": {
              "required": [
                "gated_plan"
              ]
            }
          }
        }
      ]
    },
    "MeasuredClaim": {
      "type": "object",
      "description": "Exactly koopbewijs.api(): vendor claim alongside our observation, not a vendor verification.",
      "required": [
        "claim",
        "claim_source",
        "claim_read_on",
        "observed",
        "observed_on",
        "evidence",
        "status"
      ],
      "properties": {
        "claim": {
          "type": "string"
        },
        "claim_source": {
          "type": "string"
        },
        "claim_changed_on": {
          "type": [
            "string",
            "null"
          ],
          "format": "date",
          "description": "First observed absence of the current vendor wording; does not change measurement status."
        },
        "claim_read_on": {
          "type": "string",
          "format": "date"
        },
        "observed": {
          "type": "string"
        },
        "observed_on": {
          "type": "string",
          "format": "date"
        },
        "evidence": {
          "type": "object",
          "required": [
            "label",
            "url"
          ],
          "properties": {
            "label": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "status": {
          "enum": [
            "confirmed",
            "contradicted",
            "not_comparable",
            "not_testable",
            "out_of_date"
          ]
        },
        "plan": {
          "type": [
            "string",
            "null"
          ]
        },
        "comparability": {
          "type": [
            "string",
            "null"
          ]
        },
        "buying_consequence": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "MeasuredCountFact": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "value",
        "basis",
        "observed_on",
        "evidence_url"
      ],
      "properties": {
        "value": {
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0
            },
            {
              "const": "not_tested"
            }
          ]
        },
        "basis": {
          "type": "string"
        },
        "observed_on": {
          "type": "string",
          "format": "date"
        },
        "evidence_url": {
          "type": "null",
          "description": "Aggregate not rendered in the review in this round."
        }
      }
    },
    "MeasuredDowngrade": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "plan",
        "route",
        "quote",
        "evidence",
        "status"
      ],
      "properties": {
        "plan": {
          "type": "string",
          "pattern": "\\S"
        },
        "route": {
          "type": "string",
          "pattern": "\\S"
        },
        "quote": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "text",
            "source_url",
            "observed_at"
          ],
          "properties": {
            "text": {
              "type": "string",
              "pattern": "\\S"
            },
            "source_url": {
              "type": "string",
              "format": "uri",
              "pattern": "^https?://[^/\\s?#]+(?:[^\\s]*)$"
            },
            "observed_at": {
              "type": "string",
              "format": "date-time"
            }
          }
        },
        "evidence": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^bewijs/[a-zA-Z0-9_.-]+\\.(jpg|png|webp)$"
          }
        },
        "status": {
          "enum": [
            "self_service",
            "contact_required",
            "not_offered"
          ]
        }
      }
    },
    "MeasuredEntryExit": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "signup",
        "cancel"
      ],
      "properties": {
        "signup": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "screens",
            "card_required",
            "call_required",
            "observed_on",
            "evidence_url"
          ],
          "properties": {
            "screens": {
              "oneOf": [
                {
                  "type": "integer",
                  "minimum": 0
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "card_required": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "call_required": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "observed_on": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "evidence_url": {
              "type": [
                "string",
                "null"
              ],
              "format": "uri"
            }
          }
        },
        "cancel": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "screens",
            "call_required",
            "observed_on",
            "evidence_url"
          ],
          "properties": {
            "screens": {
              "oneOf": [
                {
                  "type": "integer",
                  "minimum": 0
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "call_required": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "observed_on": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "evidence_url": {
              "type": [
                "string",
                "null"
              ],
              "format": "uri"
            }
          }
        }
      }
    },
    "MeasuredExitTest": {
      "type": [
        "object",
        "null"
      ],
      "description": "Exactly vertrektest.api() plus a public evidence_url. friction.format describes the route's formats, not a list of formats actually tested. available_fields/not_offered describe the dialog when file_inspected is false; they are never promoted to came_along/lost. Read not_tested and note.",
      "required": [
        "run_date",
        "evidence_url",
        "what",
        "file_inspected",
        "reimport_tested",
        "friction",
        "not_tested",
        "note"
      ],
      "properties": {
        "run_date": {
          "type": "string",
          "format": "date"
        },
        "evidence_url": {
          "type": "string",
          "format": "uri"
        },
        "what": {
          "type": "string"
        },
        "first_import": {
          "type": [
            "string",
            "null"
          ]
        },
        "awkward": {
          "type": [
            "string",
            "null"
          ]
        },
        "file_inspected": {
          "type": "boolean"
        },
        "reimport_tested": {
          "type": "boolean"
        },
        "friction": {
          "type": "object",
          "properties": {
            "export_route": {
              "type": [
                "string",
                "null"
              ]
            },
            "format": {
              "type": [
                "string",
                "null"
              ]
            },
            "reimport": {
              "type": [
                "string",
                "null"
              ]
            },
            "cancellation": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        },
        "came_along": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "lost": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "available_fields": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "not_offered": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "not_tested": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "note": {
          "type": "string"
        }
      }
    },
    "MeasuredFact": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "value",
        "basis",
        "observed_on",
        "evidence_url"
      ],
      "properties": {
        "value": {
          "enum": [
            true,
            false,
            "not_tested"
          ]
        },
        "basis": {
          "type": "string"
        },
        "observed_on": {
          "type": "string",
          "format": "date"
        },
        "evidence_url": {
          "type": "string",
          "format": "uri"
        }
      }
    },
    "MeasuredInbox": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "description": "Dated observation of retained INBOX/junk messages, with optional literal timeline. Counts exclude uncertain classifications; time_basis states whether the signup hour is known.",
      "required": [
        "window_start",
        "window_end",
        "window_days",
        "time_basis",
        "status",
        "observed_at",
        "counts",
        "first_sales_email_hours",
        "has_list_unsubscribe",
        "uncertain",
        "after_cancel",
        "after_deletion",
        "after_unsubscribe"
      ],
      "properties": {
        "window_start": {
          "type": "string",
          "format": "date-time"
        },
        "window_end": {
          "type": "string",
          "format": "date-time"
        },
        "window_days": {
          "const": 14,
          "type": "integer"
        },
        "time_basis": {
          "enum": [
            "signup_date_midnight_Europe_Amsterdam",
            "signup_timestamp"
          ],
          "type": "string"
        },
        "status": {
          "enum": [
            "complete",
            "partial"
          ]
        },
        "observed_at": {
          "type": "string",
          "format": "date-time"
        },
        "counts": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "transactional",
            "onboarding_tips",
            "sales_upsell",
            "personal_looking_sales"
          ],
          "properties": {
            "transactional": {
              "type": "integer",
              "minimum": 0
            },
            "onboarding_tips": {
              "type": "integer",
              "minimum": 0
            },
            "sales_upsell": {
              "type": "integer",
              "minimum": 0
            },
            "personal_looking_sales": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "first_sales_email_hours": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0
        },
        "has_list_unsubscribe": {
          "type": "boolean"
        },
        "uncertain": {
          "type": "integer",
          "minimum": 0
        },
        "after_cancel": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "status"
              ],
              "properties": {
                "status": {
                  "const": "not_tested"
                }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "window_start": {
                  "type": "string",
                  "format": "date-time"
                },
                "window_end": {
                  "type": "string",
                  "format": "date-time"
                },
                "observed_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "status": {
                  "enum": [
                    "complete",
                    "partial"
                  ]
                },
                "window_days": {
                  "const": 30,
                  "type": "integer"
                },
                "time_basis": {
                  "const": "event_date_midnight_Europe_Amsterdam"
                },
                "counts": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "transactional",
                    "marketing",
                    "sales"
                  ],
                  "properties": {
                    "transactional": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "marketing": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "sales": {
                      "type": "integer",
                      "minimum": 0
                    }
                  }
                },
                "last_marketing_day": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 29
                },
                "uncertain": {
                  "type": "integer",
                  "minimum": 0
                },
                "has_list_unsubscribe": {
                  "type": "boolean"
                }
              },
              "required": [
                "window_start",
                "window_end",
                "observed_at",
                "status",
                "window_days",
                "time_basis",
                "counts",
                "last_marketing_day",
                "uncertain",
                "has_list_unsubscribe"
              ]
            }
          ]
        },
        "after_deletion": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "status"
              ],
              "properties": {
                "status": {
                  "const": "not_tested"
                }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "window_start": {
                  "type": "string",
                  "format": "date-time"
                },
                "window_end": {
                  "type": "string",
                  "format": "date-time"
                },
                "observed_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "status": {
                  "enum": [
                    "complete",
                    "partial"
                  ]
                },
                "window_days": {
                  "const": 30,
                  "type": "integer"
                },
                "time_basis": {
                  "const": "event_date_midnight_Europe_Amsterdam"
                },
                "counts": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "transactional",
                    "marketing",
                    "sales"
                  ],
                  "properties": {
                    "transactional": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "marketing": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "sales": {
                      "type": "integer",
                      "minimum": 0
                    }
                  }
                },
                "last_marketing_day": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 29
                },
                "uncertain": {
                  "type": "integer",
                  "minimum": 0
                },
                "has_list_unsubscribe": {
                  "type": "boolean"
                }
              },
              "required": [
                "window_start",
                "window_end",
                "observed_at",
                "status",
                "window_days",
                "time_basis",
                "counts",
                "last_marketing_day",
                "uncertain",
                "has_list_unsubscribe"
              ]
            }
          ]
        },
        "after_unsubscribe": {
          "oneOf": [
            {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "status"
              ],
              "properties": {
                "status": {
                  "enum": [
                    "not_tested",
                    "indeterminate"
                  ]
                }
              }
            },
            {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "status": {
                  "enum": [
                    "waiting",
                    "partial",
                    "complete"
                  ]
                },
                "submitted_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "window_start": {
                  "type": "string",
                  "format": "date-time"
                },
                "window_end": {
                  "type": "string",
                  "format": "date-time"
                },
                "observed_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "marketing": {
                  "type": "integer",
                  "minimum": 0
                },
                "uncertain": {
                  "type": "integer",
                  "minimum": 0
                }
              },
              "required": [
                "status",
                "submitted_at",
                "window_start",
                "window_end",
                "observed_at",
                "marketing",
                "uncertain"
              ]
            }
          ]
        },
        "timeline": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "signup_at",
            "messages"
          ],
          "description": "Literal retained inbox/junk messages. Own correspondence (replies, tickets) excluded; one-time codes, our address, account name and our name replaced in brackets. Missing timeline means not measured, never zero. All display names replaced by vendor team. Exact signup time may be unknown.",
          "properties": {
            "signup_at": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "messages": {
              "type": "array",
              "items": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "received_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "sender_name": {
                    "type": "string",
                    "pattern": " team$"
                  },
                  "sender_domain": {
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9.-]*$"
                  },
                  "subject": {
                    "type": "string"
                  },
                  "folder": {
                    "enum": [
                      "inbox",
                      "junk"
                    ]
                  },
                  "offer": {
                    "oneOf": [
                      {
                        "type": "null"
                      },
                      {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "source",
                          "text"
                        ],
                        "properties": {
                          "source": {
                            "enum": [
                              "subject",
                              "body"
                            ]
                          },
                          "text": {
                            "type": "string",
                            "minLength": 1
                          }
                        }
                      }
                    ]
                  }
                },
                "required": [
                  "received_at",
                  "sender_name",
                  "sender_domain",
                  "subject",
                  "folder",
                  "offer"
                ]
              }
            }
          }
        }
      }
    },
    "MeasuredInvites": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "status",
            "default_on",
            "plus_accepted",
            "invitee_can_unsubscribe",
            "address_book_requested",
            "workspace_requested"
          ],
          "properties": {
            "status": {
              "const": "not_tested"
            },
            "default_on": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "plus_accepted": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "invitee_can_unsubscribe": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "address_book_requested": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "workspace_requested": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "window_start": {
              "type": "string",
              "format": "date-time"
            },
            "window_end": {
              "type": "string",
              "format": "date-time"
            },
            "observed_at": {
              "type": "string",
              "format": "date-time"
            },
            "status": {
              "enum": [
                "complete",
                "partial"
              ]
            },
            "default_on": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "plus_accepted": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "invitee_can_unsubscribe": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "address_book_requested": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "workspace_requested": {
              "oneOf": [
                {
                  "type": "boolean"
                },
                {
                  "const": "not_tested"
                }
              ]
            },
            "window_days": {
              "const": 14,
              "type": "integer"
            },
            "time_basis": {
              "const": "invite_date_midnight_Europe_Amsterdam"
            },
            "counts": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "invitations",
                "reminders"
              ],
              "properties": {
                "invitations": {
                  "type": "integer",
                  "minimum": 0
                },
                "reminders": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "uncertain": {
              "type": "integer",
              "minimum": 0
            },
            "has_list_unsubscribe": {
              "type": "boolean"
            },
            "has_one_click_header": {
              "type": "boolean"
            }
          },
          "required": [
            "window_start",
            "window_end",
            "observed_at",
            "status",
            "default_on",
            "plus_accepted",
            "invitee_can_unsubscribe",
            "address_book_requested",
            "workspace_requested",
            "window_days",
            "time_basis",
            "counts",
            "uncertain",
            "has_list_unsubscribe",
            "has_one_click_header"
          ]
        },
        {
          "type": "null"
        }
      ]
    },
    "MeasuredOnboarding": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "screens_to_first_result",
        "first_result",
        "card_required",
        "conversation_required",
        "connection_required",
        "observed_on"
      ],
      "properties": {
        "screens_to_first_result": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "first_result": {
          "type": [
            "string",
            "null"
          ]
        },
        "card_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "conversation_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "connection_required": {
          "type": [
            "boolean",
            "null"
          ]
        },
        "observed_on": {
          "type": "string",
          "format": "date"
        }
      }
    },
    "MeasuredRoles": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "plan",
        "route",
        "quote",
        "evidence",
        "status",
        "role_names",
        "viewer_roles"
      ],
      "properties": {
        "plan": {
          "type": "string",
          "pattern": "\\S"
        },
        "route": {
          "type": "string",
          "pattern": "\\S"
        },
        "quote": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "text",
            "source_url",
            "observed_at"
          ],
          "properties": {
            "text": {
              "type": "string",
              "pattern": "\\S"
            },
            "source_url": {
              "type": "string",
              "format": "uri",
              "pattern": "^https?://[^/\\s?#]+(?:[^\\s]*)$"
            },
            "observed_at": {
              "type": "string",
              "format": "date-time"
            }
          }
        },
        "evidence": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^bewijs/[a-zA-Z0-9_.-]+\\.(jpg|png|webp)$"
          }
        },
        "status": {
          "enum": [
            "free_viewer_documented",
            "viewer_costs_seat",
            "viewer_exists_cost_unknown",
            "no_viewer_role"
          ]
        },
        "role_names": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "\\S"
          }
        },
        "viewer_roles": {
          "type": "array",
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "\\S"
          }
        },
        "default_role": {
          "type": "string",
          "pattern": "\\S"
        }
      }
    },
    "MeasuredSupport": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "required": [
        "sent_at",
        "window_days",
        "observed_at",
        "status",
        "channel",
        "first_reply_hours",
        "first_human_reply_hours",
        "answered",
        "answered_by",
        "plan",
        "trial",
        "comparison",
        "method"
      ],
      "properties": {
        "sent_at": {
          "type": "string",
          "format": "date-time"
        },
        "window_days": {
          "const": 7
        },
        "observed_at": {
          "type": "string",
          "format": "date-time"
        },
        "status": {
          "enum": [
            "partial",
            "complete"
          ]
        },
        "channel": {
          "enum": [
            "email",
            "chat",
            "ticket"
          ]
        },
        "first_reply_hours": {
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 168
            },
            {
              "enum": [
                null,
                "no reply in 7 days"
              ]
            }
          ]
        },
        "first_human_reply_hours": {
          "oneOf": [
            {
              "type": "integer",
              "minimum": 0,
              "maximum": 168
            },
            {
              "enum": [
                null,
                "no reply in 7 days",
                "unclear"
              ]
            }
          ]
        },
        "answered": {
          "enum": [
            null,
            "yes",
            "no",
            "partly"
          ]
        },
        "answered_by": {
          "enum": [
            null,
            "Claude"
          ]
        },
        "plan": {
          "type": "string",
          "minLength": 1
        },
        "trial": {
          "type": "boolean"
        },
        "comparison": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "status",
            "reason"
          ],
          "properties": {
            "status": {
              "enum": [
                "comparable",
                "not_comparable"
              ]
            },
            "reason": {
              "type": "string"
            }
          }
        },
        "method": {
          "const": "One support message containing three fixed questions, by email, by the supplier's support ticket form, or, when the supplier publishes no email address, by in-app chat with manually recorded times; one measurement is one measurement, not an estimate of typical support speed. Seven elapsed days; whole hours, half up. Human means rule-based signals, not proof of authorship. Uncertain replies remain unclear. For email, only messages still present in INBOX/junk at collection time are covered."
        }
      }
    },
    "Plan": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "price": {
          "type": "string"
        },
        "includes": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "StatusPage": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "description": "Vendor self-reported history, separate from measured. Never an uptime percentage. Null means no fresh supported confirmed source. Feed-only data cannot establish 90-day incident totals or outage durations.",
      "required": [
        "source_url",
        "source_urls",
        "platform",
        "period",
        "read_at",
        "claim",
        "scope",
        "incident_count",
        "observed_count",
        "counts_by_vendor_label",
        "major_or_critical_count",
        "observed_major_or_critical_count",
        "duration_seconds",
        "known_duration_seconds",
        "duration_known_count",
        "ongoing_count",
        "incidents",
        "coverage",
        "note",
        "availability"
      ],
      "properties": {
        "source_url": {
          "type": "string",
          "format": "uri"
        },
        "source_urls": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "format": "uri"
          }
        },
        "platform": {
          "type": "string"
        },
        "read_at": {
          "type": "string",
          "format": "date-time"
        },
        "claim": {
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": false,
          "required": [
            "quote",
            "source_url",
            "read_on",
            "plan"
          ],
          "properties": {
            "quote": {
              "type": "string",
              "minLength": 1,
              "maxLength": 300
            },
            "source_url": {
              "type": "string",
              "format": "uri"
            },
            "read_on": {
              "type": "string",
              "format": "date"
            },
            "plan": {
              "type": "string",
              "minLength": 1
            }
          }
        },
        "scope": {
          "type": "string"
        },
        "period": {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "from",
            "to",
            "days"
          ],
          "properties": {
            "from": {
              "type": "string",
              "format": "date-time"
            },
            "to": {
              "type": "string",
              "format": "date-time"
            },
            "days": {
              "const": 90
            }
          }
        },
        "incident_count": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "observed_count": {
          "type": "integer",
          "minimum": 0
        },
        "counts_by_vendor_label": {
          "type": "object",
          "additionalProperties": {
            "type": "integer",
            "minimum": 0
          }
        },
        "major_or_critical_count": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "observed_major_or_critical_count": {
          "type": "integer",
          "minimum": 0
        },
        "duration_seconds": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0
        },
        "known_duration_seconds": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0
        },
        "duration_known_count": {
          "type": "integer",
          "minimum": 0
        },
        "ongoing_count": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0
        },
        "coverage": {
          "enum": [
            "complete_90_days",
            "feed_entries_only"
          ]
        },
        "availability": {
          "enum": [
            "ok",
            "tijdelijk_onbereikbaar",
            "pagina_onbereikbaar"
          ]
        },
        "note": {
          "type": "string"
        },
        "incidents": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "source_url",
              "label",
              "title",
              "started_at",
              "published_at",
              "resolved_at",
              "ongoing",
              "kind"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "source_url": {
                "type": "string",
                "format": "uri"
              },
              "label": {
                "type": "string"
              },
              "title": {
                "type": "string"
              },
              "started_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "published_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "resolved_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "ongoing": {
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "kind": {
                "enum": [
                  "incident",
                  "notice"
                ]
              }
            }
          }
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "coverage": {
                "const": "feed_entries_only"
              }
            }
          },
          "then": {
            "properties": {
              "incident_count": {
                "type": "null"
              },
              "major_or_critical_count": {
                "type": "null"
              },
              "duration_seconds": {
                "type": "null"
              },
              "ongoing_count": {
                "type": "null"
              }
            }
          }
        }
      ]
    }
  }
}