{
  "openapi": "3.1.0",
  "info": {
    "title": "Voice Benchmark Public API",
    "version": "1.0.0",
    "description": "Public endpoints for Voice Benchmark rankings and provider histories. Third-party requests are rate-limited to ~120 requests per minute; data updates hourly. Latency fields end with _ms (milliseconds); success is 0/1."
  },
  "servers": [
    {
      "url": "https://voicebenchmark.ai",
      "description": "Production"
    }
  ],
  "paths": {
    "/api/rankings": {
      "get": {
        "summary": "Get current rankings",
        "operationId": "getRankings",
        "description": "Returns visible providers ordered by current latency. Third-party origins are rate-limited to ~120 req/min; data refreshes hourly.",
        "responses": {
          "200": {
            "description": "Current rankings",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Ranking"
                  }
                },
                "examples": {
                  "example": {
                    "value": [
                      {
                        "id": 1,
                        "name": "Acme Voice",
                        "slug": "acme-voice",
                        "current_latency": 820,
                        "median_latency": 800,
                        "p95_latency": 900,
                        "p99_latency": 980,
                        "last_tested": "2025-02-18T13:25:16Z"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/providers/{id}/history": {
      "get": {
        "summary": "Get recent history for a provider",
        "operationId": "getProviderHistory",
        "description": "Returns recent (capped) test history for a provider by id. Third-party origins are rate-limited to ~120 req/min; data refreshes hourly.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "Provider ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Recent history (capped)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/HistoryEntry" }
                },
                "examples": {
                  "example": {
                    "value": [
                      {
                        "test_timestamp": "2025-02-18T12:35:16Z",
                        "average_latency_ms": 790,
                        "success": 1,
                        "job_id": "job-acme-2",
                        "status": "ok"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/providers/{id}/history-full": {
      "get": {
        "summary": "Get full history for a provider",
        "operationId": "getProviderHistoryFull",
        "description": "Returns full test history for a provider by id. Third-party origins are rate-limited to ~120 req/min; data refreshes hourly.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "Provider ID"
          }
        ],
        "responses": {
          "200": {
            "description": "Full history",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/HistoryEntry" }
                }
              }
            }
          }
        }
      }
    },
    "/leaderboard.json": {
      "get": {
        "summary": "Leaderboard snapshot (JSON)",
        "operationId": "getLeaderboardJson",
        "description": "Visible providers with current metrics and slugs. Rate-limited to ~120 req/min (third-party). Updated hourly.",
        "responses": {
          "200": {
            "description": "Leaderboard snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/RankingWithSlug" }
                },
                "examples": {
                  "example": {
                    "value": [
                      {
                        "id": 1,
                        "name": "Acme Voice",
                        "slug": "acme-voice",
                        "current_latency": 820,
                        "median_latency": 800,
                        "p95_latency": 900,
                        "p99_latency": 980,
                        "last_tested": "2025-02-18T13:25:16Z"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/providers.json": {
      "get": {
        "summary": "Provider list (JSON)",
        "operationId": "getProvidersJson",
        "description": "Visible providers (id, name, slug). Rate-limited to ~120 req/min (third-party). Updated hourly.",
        "responses": {
          "200": {
            "description": "Visible providers",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/ProviderSummary" }
                },
                "examples": {
                  "example": {
                    "value": [
                      {
                        "id": 1,
                        "name": "Acme Voice",
                        "slug": "acme-voice"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    },
    "/provider/{slug}.json": {
      "get": {
        "summary": "Provider snapshot with history",
        "operationId": "getProviderJson",
        "description": "Visible provider by slug, with capped history (last 100 points). Rate-limited to ~120 req/min (third-party). Updated hourly.",
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "Provider slug (canonical URL identifier)"
          }
        ],
        "responses": {
          "200": {
            "description": "Provider snapshot with capped history (last 100 points)",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProviderSnapshot" },
                "examples": {
                  "example": {
                    "value": {
                      "id": 3,
                      "name": "Echo AI",
                      "slug": "echo-ai",
                      "current_latency": 710,
                      "median_latency": 710,
                      "p95_latency": null,
                      "p99_latency": null,
                      "last_tested": "2025-02-18T13:33:16Z",
                      "history": [
                        {
                          "test_timestamp": "2025-02-18T09:35:16Z",
                          "average_latency_ms": 680,
                          "success": 1,
                          "job_id": "job-echo-1",
                          "status": "ok"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Provider not found"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Ranking": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "current_latency": { "type": ["number", "null"], "description": "Milliseconds" },
          "median_latency": { "type": ["number", "null"], "description": "Milliseconds" },
          "p95_latency": { "type": ["number", "null"], "description": "Milliseconds" },
          "p99_latency": { "type": ["number", "null"], "description": "Milliseconds" },
          "last_tested": { "type": ["string", "null"], "format": "date-time" }
        }
      },
      "RankingWithSlug": {
        "allOf": [
          { "$ref": "#/components/schemas/Ranking" },
          {
            "type": "object",
            "properties": {
              "slug": { "type": "string" }
            }
          }
        ]
      },
      "ProviderSummary": {
        "type": "object",
        "properties": {
          "id": { "type": "integer" },
          "name": { "type": "string" },
          "slug": { "type": "string" }
        }
      },
      "ProviderSnapshot": {
        "allOf": [
          { "$ref": "#/components/schemas/RankingWithSlug" },
          {
            "type": "object",
            "properties": {
              "history": {
                "type": "array",
                "items": { "$ref": "#/components/schemas/HistoryEntry" }
              }
            }
          }
        ]
      },
      "HistoryEntry": {
        "type": "object",
        "properties": {
          "test_timestamp": { "type": "string", "format": "date-time" },
          "average_latency_ms": { "type": ["number", "null"], "description": "Milliseconds" },
          "success": { "type": "integer", "enum": [0, 1] },
          "job_id": { "type": ["string", "null"] },
          "status": { "type": ["string", "null"] }
        }
      }
    }
  }
}
