{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://api.youraitools.co/stats/v1/listings/schema.json",
  "title": "YourAITools third-party listing stats",
  "description": "GET https://api.youraitools.co/stats/v1/listings lists every listing in https://youraitools.co/listings.json; GET https://api.youraitools.co/stats/v1/listings/<slug> (also https://api.youraitools.co/stats/v1/tools/<slug> for listing slugs) returns the same envelope with \"listing\". Every listed slug answers 200, with nulls and status not_yet_measured before its first check. Collected with one unpaid request per listing per day; no payment is ever made and no IPs or bodies are stored.",
  "type": "object",
  "required": [
    "schema_version",
    "schema",
    "generated_at",
    "source",
    "index_fetched_at",
    "count",
    "notes"
  ],
  "properties": {
    "schema_version": {
      "const": "1.0"
    },
    "schema": {
      "type": "string",
      "format": "uri"
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    },
    "source": {
      "const": "https://youraitools.co/listings.json"
    },
    "index_fetched_at": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "count": {
      "type": "integer",
      "minimum": 0
    },
    "notes": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "listings": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/listing"
      }
    },
    "listing": {
      "$ref": "#/$defs/listing"
    }
  },
  "oneOf": [
    {
      "required": [
        "listings"
      ]
    },
    {
      "required": [
        "listing"
      ]
    }
  ],
  "$defs": {
    "listing": {
      "type": "object",
      "required": [
        "slug",
        "name",
        "kind",
        "listing_url",
        "stats_url",
        "protocol",
        "probe_target",
        "status",
        "measuring_since",
        "last_check",
        "price",
        "uptime",
        "trust",
        "probe_hold"
      ],
      "properties": {
        "slug": {
          "type": "string",
          "description": "Listing slug on youraitools.co (https://youraitools.co/tool/<slug>)."
        },
        "name": {
          "type": "string"
        },
        "kind": {
          "const": "listing"
        },
        "listing_url": {
          "type": "string",
          "format": "uri"
        },
        "stats_url": {
          "type": "string",
          "format": "uri"
        },
        "protocol": {
          "type": "string",
          "description": "Payment protocol as listed."
        },
        "probe_target": {
          "type": [
            "object",
            "null"
          ],
          "description": "What is probed: the listing's example endpoint, with the listing's endpointMethod (else the method its verification text documents, else GET). A POST sends the listing's exampleBody as application/json when it has one, else no body. null = no example endpoint, never probed.",
          "properties": {
            "url": {
              "type": "string",
              "format": "uri"
            },
            "method": {
              "enum": [
                "GET",
                "POST"
              ]
            },
            "body": {
              "type": [
                "string",
                "null"
              ],
              "description": "The JSON body a POST probe sends (the listing's exampleBody); null = no body."
            }
          }
        },
        "status": {
          "enum": [
            "up",
            "down",
            "stale",
            "not_yet_measured",
            "no_probe_target",
            "opted_out"
          ],
          "description": "opted_out = the operator asked us to stop probing (no measurements shown). Otherwise from the latest check. up = an HTTP answer below 500 that is not 404/410 within 8 s; down = timeout, network error, 5xx, 404 or 410; stale = no check in 3 days."
        },
        "measuring_since": {
          "type": [
            "string",
            "null"
          ],
          "format": "date",
          "description": "UTC date of the first check; null before it."
        },
        "last_check": {
          "type": [
            "object",
            "null"
          ],
          "description": "The latest daily check; null before the first.",
          "properties": {
            "at": {
              "type": "string",
              "format": "date-time",
              "description": "Last check time."
            },
            "http_status": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "HTTP status (redirects are not followed); null on timeout/network error."
            },
            "valid_x402": {
              "type": "boolean",
              "description": "HTTP 402 with x402 payment terms (v2 PAYMENT-REQUIRED header or v1 JSON body) naming scheme, network, payTo and an amount."
            },
            "x402_version": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "latency_ms": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "description": "Time to response headers, ms."
            },
            "error": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "timeout",
                "network",
                "no_probe_target",
                null
              ]
            }
          }
        },
        "price": {
          "type": "object",
          "required": [
            "listed",
            "listed_usd_range",
            "mode",
            "seen",
            "seen_usd",
            "price_seen_at_probe_time"
          ],
          "description": "The listed price, and the price read from the 402 only when one of its payment options (any network) falls inside the listed range.",
          "properties": {
            "listed": {
              "type": [
                "string",
                "null"
              ]
            },
            "listed_usd_range": {
              "type": [
                "object",
                "null"
              ],
              "description": "Every $ figure in the listed price, min to max. A single figure after \"from\" / \"starting at\" / \"minimum\" is a floor (max null); after \"up to\" a ceiling (min 0).",
              "properties": {
                "min": {
                  "type": "number"
                },
                "max": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            },
            "mode": {
              "enum": [
                "fixed",
                "dynamic",
                "prepaid"
              ],
              "description": "prepaid = a top-up / prepaid credit route whose amount the caller chooses (not a per-call price, never compared); dynamic = a range, from / varies / tier / usage wording, or an upto offer (compared against the listed range only); fixed = one listed price."
            },
            "seen": {
              "type": [
                "object",
                "null"
              ],
              "description": "The payment option from the latest 402 that falls inside listed_usd_range (the Base option when it does, else the first one that does; every option is compared). null when none does or the price is not comparable (prepaid, no listed figure, no USDC option). options = how many options the 402 offered.",
              "properties": {
                "amount_atomic": {
                  "type": "string"
                },
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "usd": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "options": {
                  "type": "integer",
                  "minimum": 0
                }
              }
            },
            "seen_usd": {
              "type": [
                "number",
                "null"
              ],
              "description": "USDC (6 decimals) amount of seen; null whenever seen is null."
            },
            "price_seen_at_probe_time": {
              "type": [
                "object",
                "null"
              ],
              "description": "Price seen at probe time when it is outside the listed range. Only after a manual recheck by YourAITools and only when every check for 3+ days saw it; null otherwise (the default).",
              "properties": {
                "usd": {
                  "type": "number"
                },
                "amount_atomic": {
                  "type": "string"
                },
                "asset": {
                  "type": "string"
                },
                "network": {
                  "type": "string"
                },
                "observed_since": {
                  "type": "string",
                  "format": "date"
                }
              }
            }
          }
        },
        "uptime": {
          "type": "object",
          "required": [
            "7d",
            "30d"
          ],
          "properties": {
            "7d": {
              "type": "object",
              "required": [
                "checks",
                "up",
                "uptime_pct",
                "valid_x402_pct"
              ],
              "properties": {
                "checks": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Daily checks in the window (one per listing per day)."
                },
                "up": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Checks where the listing was up."
                },
                "uptime_pct": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 100,
                  "description": "up / checks in percent, 2 decimals; null with 0 checks. Rolling: the last 7 or 30 days."
                },
                "valid_x402_pct": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 100,
                  "description": "Share of checks that returned a valid x402 402, percent; null with 0 checks."
                }
              }
            },
            "30d": {
              "type": "object",
              "required": [
                "checks",
                "up",
                "uptime_pct",
                "valid_x402_pct"
              ],
              "properties": {
                "checks": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Daily checks in the window (one per listing per day)."
                },
                "up": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Checks where the listing was up."
                },
                "uptime_pct": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 100,
                  "description": "up / checks in percent, 2 decimals; null with 0 checks. Rolling: the last 7 or 30 days."
                },
                "valid_x402_pct": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 100,
                  "description": "Share of checks that returned a valid x402 402, percent; null with 0 checks."
                }
              }
            }
          }
        },
        "trust": {
          "type": "object",
          "description": "Trust score, formula 1.0-median30. Trust score (0-100) uses only the public numbers on this page, from our daily unpaid check of the listing's example endpoint over the last 30 days: uptime (40 points), how often the endpoint returned a valid x402 payment request (40), whether the price in that request matches the listed price (10), and the median response time of the checks that were up (10). If a part can't apply, for example prepaid pricing, the score is rescaled over the parts that do. A score appears only after at least 7 days and 6 checks. Paying for Featured, Sponsored or any other placement never changes it, and it is not an endorsement. The formula and every input are in the JSON at api.youraitools.co/stats/v1/listings/{slug}. Listed a service and think the score is wrong? Email hello@youraitools.co and we'll re-check it. Score = points / applicable_weight x 100, rounded (uptime.30d.uptime_pct x 0.4; uptime.30d.valid_x402_pct x 0.4; price_match 10 when last_check.valid_x402 and price.seen_usd is set, not applicable for prepaid or no listed $ figure; latency 10/7/4/1 for a 30-day median of up checks under 500 / 500-999 / 1000-1999 / 2000+ ms, 0 when the last check was not up). Bands: strong 90-100, fair 70-89, weak under 70 (a label, not a ranking). Missing data is never filled in. When a listing's probe target (method + example endpoint) changes, the window restarts at the next check (window_start; reason \"probe target changed on <date>; re-measuring\"). Payment, Featured and Sponsored status are never inputs.",
          "required": [
            "formula_version",
            "status",
            "score",
            "band",
            "reason",
            "window_days",
            "checks",
            "measuring_since",
            "window_start",
            "components",
            "applicable_weight",
            "computed_at",
            "method"
          ],
          "properties": {
            "formula_version": {
              "const": "1.0-median30"
            },
            "status": {
              "enum": [
                "scored",
                "insufficient_data",
                "stale",
                "not_applicable"
              ],
              "description": "not_applicable: opted out, no example endpoint, our own tool, or not a plain x402 listing. insufficient_data: first check (or first check since the probe target changed) less than 7 days ago, or fewer than 6 checks in that window. stale: no check for 3 days."
            },
            "score": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "maximum": 100,
              "description": "null unless status = scored."
            },
            "band": {
              "enum": [
                "strong",
                "fair",
                "weak",
                null
              ]
            },
            "reason": {
              "type": [
                "string",
                "null"
              ]
            },
            "window_days": {
              "const": 30
            },
            "checks": {
              "type": "integer",
              "minimum": 0,
              "description": "Checks in the trust window (last 30 days, from window_start)."
            },
            "measuring_since": {
              "type": [
                "string",
                "null"
              ],
              "format": "date"
            },
            "window_start": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "Start of the trust window: the first check, or the first check after the listing's probe target (method + example endpoint) last changed. Only checks at or after it (and within 30 days) count toward the score and the 7-day / 6-check gates; the uptime block keeps every check."
            },
            "components": {
              "type": [
                "object",
                "null"
              ],
              "description": "null unless status = scored.",
              "properties": {
                "uptime": {
                  "type": "object",
                  "properties": {
                    "weight": {
                      "const": 40
                    },
                    "input_pct": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "points": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "minimum": 0
                    }
                  }
                },
                "valid_x402": {
                  "type": "object",
                  "properties": {
                    "weight": {
                      "const": 40
                    },
                    "input_pct": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "points": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "minimum": 0
                    }
                  }
                },
                "price_match": {
                  "type": "object",
                  "properties": {
                    "weight": {
                      "const": 10
                    },
                    "applicable": {
                      "type": "boolean"
                    },
                    "input": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "points": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "minimum": 0
                    }
                  }
                },
                "latency": {
                  "type": "object",
                  "properties": {
                    "weight": {
                      "const": 10
                    },
                    "input_ms": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Median latency_ms of the up checks in the last 30 days."
                    },
                    "input": {
                      "const": "median_30d_up_checks"
                    },
                    "up_checks": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "last_check_up": {
                      "type": "boolean"
                    },
                    "band": {
                      "enum": [
                        "<500",
                        "500-999",
                        "1000-1999",
                        "2000-8000",
                        null
                      ]
                    },
                    "points": {
                      "type": [
                        "number",
                        "null"
                      ],
                      "minimum": 0
                    }
                  }
                }
              }
            },
            "applicable_weight": {
              "enum": [
                90,
                100,
                null
              ]
            },
            "computed_at": {
              "type": "string",
              "format": "date-time"
            },
            "method": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "probe_hold": {
          "type": "boolean",
          "description": "true while our daily check of this listing is being fixed on our side (probe target, HTTP method or request body): its measured numbers may reflect our check, not the service, so show \"check being updated\" instead. Clears once a trust score is measured wholly on the fixed check."
        },
        "note": {
          "type": "string"
        }
      }
    },
    "window": {
      "type": "object",
      "required": [
        "checks",
        "up",
        "uptime_pct",
        "valid_x402_pct"
      ],
      "properties": {
        "checks": {
          "type": "integer",
          "minimum": 0,
          "description": "Daily checks in the window (one per listing per day)."
        },
        "up": {
          "type": "integer",
          "minimum": 0,
          "description": "Checks where the listing was up."
        },
        "uptime_pct": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 100,
          "description": "up / checks in percent, 2 decimals; null with 0 checks. Rolling: the last 7 or 30 days."
        },
        "valid_x402_pct": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 100,
          "description": "Share of checks that returned a valid x402 402, percent; null with 0 checks."
        }
      }
    }
  }
}