mirror of
https://github.com/alexjustesen/speedtest-tracker.git
synced 2026-06-23 04:10:25 +00:00
6e90fb7607
Co-authored-by: Alex Justesen <1144087+alexjustesen@users.noreply.github.com>
1189 lines
47 KiB
JSON
1189 lines
47 KiB
JSON
{
|
|
"openapi": "3.0.0",
|
|
"info": {
|
|
"title": "Speedtest Tracker API",
|
|
"version": "1.0.0"
|
|
},
|
|
"paths": {
|
|
"/api/v1/ookla": {
|
|
"description": "Endpoints for retrieving Ookla speedtest servers and related resources."
|
|
},
|
|
"/api/v1/results": {
|
|
"description": "Endpoints for retrieving speedtest results.",
|
|
"get": {
|
|
"tags": [
|
|
"Results"
|
|
],
|
|
"summary": "List all results",
|
|
"operationId": "listResults",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
},
|
|
{
|
|
"name": "per.page",
|
|
"in": "query",
|
|
"description": "Number of results per page",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer",
|
|
"default": 25,
|
|
"maximum": 500,
|
|
"minimum": 1
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[ping]",
|
|
"in": "query",
|
|
"description": "Filter by ping value (supports operators like >=, <=, etc.)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[download]",
|
|
"in": "query",
|
|
"description": "Filter by download speed (supports operators like >=, <=, etc.)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[upload]",
|
|
"in": "query",
|
|
"description": "Filter by upload speed (supports operators like >=, <=, etc.)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[healthy]",
|
|
"in": "query",
|
|
"description": "Filter by healthy status",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[status]",
|
|
"in": "query",
|
|
"description": "Filter by status",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[scheduled]",
|
|
"in": "query",
|
|
"description": "Filter by scheduled status",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[start_at]",
|
|
"in": "query",
|
|
"description": "Filter results created on or after this date (alias for created_at>=)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date"
|
|
}
|
|
},
|
|
{
|
|
"name": "filter[end_at]",
|
|
"in": "query",
|
|
"description": "Filter results created on or before this date (alias for created_at<=)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date"
|
|
}
|
|
},
|
|
{
|
|
"name": "sort",
|
|
"in": "query",
|
|
"description": "Sort results by field (prefix with - for descending)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string",
|
|
"enum": [
|
|
"ping",
|
|
"-ping",
|
|
"download",
|
|
"-download",
|
|
"upload",
|
|
"-upload",
|
|
"created_at",
|
|
"-created_at",
|
|
"updated_at",
|
|
"-updated_at"
|
|
]
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ResultsCollection"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation failed",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/stats": {
|
|
"description": "Endpoints for viewing performance statistics.",
|
|
"get": {
|
|
"tags": [
|
|
"Stats"
|
|
],
|
|
"summary": "Fetch aggregated Speedtest statistics",
|
|
"operationId": "getStats",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
},
|
|
{
|
|
"name": "start_at",
|
|
"in": "query",
|
|
"description": "Filter stats from this date/time (ISO 8601)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
{
|
|
"name": "end_at",
|
|
"in": "query",
|
|
"description": "Filter stats up to this date/time (ISO 8601)",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Statistics fetched successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Stats"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/ookla/list-servers": {
|
|
"get": {
|
|
"tags": [
|
|
"Servers"
|
|
],
|
|
"summary": "List available Ookla speedtest servers",
|
|
"description": "Returns an array of available Ookla speedtest servers. Requires an API token with `ookla:list-servers` scope.",
|
|
"operationId": "listOoklaServers",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Servers retrieved successfully",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ServersCollection"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/results/{id}": {
|
|
"get": {
|
|
"tags": [
|
|
"Results"
|
|
],
|
|
"summary": "Get a single result",
|
|
"operationId": "getResult",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
},
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"description": "The ID of the result",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ResultResponse"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Result not found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotFoundError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/results/latest": {
|
|
"get": {
|
|
"tags": [
|
|
"Results"
|
|
],
|
|
"summary": "Get the most recent result",
|
|
"operationId": "getLatestResult",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Result"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "No result found",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotFoundError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/speedtests/run": {
|
|
"post": {
|
|
"tags": [
|
|
"Speedtests"
|
|
],
|
|
"summary": "Run a new Ookla speedtest",
|
|
"operationId": "runSpeedtest",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
},
|
|
{
|
|
"name": "server_id",
|
|
"in": "query",
|
|
"description": "Optional Ookla speedtest server ID",
|
|
"required": false,
|
|
"schema": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"201": {
|
|
"description": "Created",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SpeedtestRun"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"422": {
|
|
"description": "Validation error",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ValidationError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/speedtests/list-servers": {
|
|
"get": {
|
|
"tags": [
|
|
"Speedtests"
|
|
],
|
|
"summary": "List available Ookla speedtest servers",
|
|
"operationId": "listSpeedtestServers",
|
|
"parameters": [
|
|
{
|
|
"$ref": "#/components/parameters/AcceptHeader"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ServersCollection"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthenticated",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/UnauthenticatedError"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"403": {
|
|
"description": "Forbidden",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/ForbiddenError"
|
|
},
|
|
"example": {
|
|
"message": "You do not have permission to view speedtest servers."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"406": {
|
|
"description": "Not Acceptable - Missing or invalid Accept header",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/NotAcceptableError"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {
|
|
"ForbiddenError": {
|
|
"description": "Forbidden error response when user lacks permission",
|
|
"properties": {
|
|
"message": {
|
|
"description": "Error message indicating lack of permission",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"NotAcceptableError": {
|
|
"description": "Error response when the Accept header is missing or invalid",
|
|
"properties": {
|
|
"message": {
|
|
"type": "string",
|
|
"example": "This endpoint only accepts JSON. Please include \"Accept: application/json\" in your request headers."
|
|
},
|
|
"error": {
|
|
"type": "string",
|
|
"example": "Unsupported Media Type"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"NotFoundError": {
|
|
"description": "Error when a requested result is not found",
|
|
"properties": {
|
|
"message": {
|
|
"description": "Result not found error message",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"ResultResponse": {
|
|
"description": "Response for an Single Speedtest result entry",
|
|
"properties": {
|
|
"data": {
|
|
"$ref": "#/components/schemas/Result"
|
|
},
|
|
"message": {
|
|
"description": "Response status message",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"Result": {
|
|
"description": "Speedtest result entry",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"service": {
|
|
"type": "string"
|
|
},
|
|
"ping": {
|
|
"type": "number"
|
|
},
|
|
"download": {
|
|
"type": "integer"
|
|
},
|
|
"upload": {
|
|
"type": "integer"
|
|
},
|
|
"download_bits": {
|
|
"type": "integer"
|
|
},
|
|
"upload_bits": {
|
|
"type": "integer"
|
|
},
|
|
"download_bits_human": {
|
|
"type": "string"
|
|
},
|
|
"upload_bits_human": {
|
|
"type": "string"
|
|
},
|
|
"benchmarks": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "object"
|
|
},
|
|
"nullable": true
|
|
},
|
|
"healthy": {
|
|
"type": "boolean",
|
|
"nullable": true
|
|
},
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"scheduled": {
|
|
"type": "boolean"
|
|
},
|
|
"comments": {
|
|
"type": "string",
|
|
"nullable": true
|
|
},
|
|
"data": {
|
|
"description": "Nested speedtest data payload",
|
|
"properties": {
|
|
"isp": {
|
|
"type": "string"
|
|
},
|
|
"ping": {
|
|
"properties": {
|
|
"low": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"high": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"jitter": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"latency": {
|
|
"type": "number",
|
|
"format": "float"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"type": {
|
|
"type": "string"
|
|
},
|
|
"result": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"url": {
|
|
"type": "string",
|
|
"format": "uri"
|
|
},
|
|
"persisted": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"server": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"ip": {
|
|
"type": "string",
|
|
"format": "ipv4"
|
|
},
|
|
"host": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"port": {
|
|
"type": "integer"
|
|
},
|
|
"country": {
|
|
"type": "string"
|
|
},
|
|
"location": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"upload": {
|
|
"properties": {
|
|
"bytes": {
|
|
"type": "integer"
|
|
},
|
|
"elapsed": {
|
|
"type": "integer"
|
|
},
|
|
"latency": {
|
|
"properties": {
|
|
"iqm": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"low": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"high": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"jitter": {
|
|
"type": "number",
|
|
"format": "float"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"bandwidth": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"download": {
|
|
"properties": {
|
|
"bytes": {
|
|
"type": "integer"
|
|
},
|
|
"elapsed": {
|
|
"type": "integer"
|
|
},
|
|
"latency": {
|
|
"properties": {
|
|
"iqm": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"low": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"high": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"jitter": {
|
|
"type": "number",
|
|
"format": "float"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"bandwidth": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"interface": {
|
|
"properties": {
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"isVpn": {
|
|
"type": "boolean"
|
|
},
|
|
"macAddr": {
|
|
"type": "string",
|
|
"pattern": "^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$"
|
|
},
|
|
"externalIp": {
|
|
"type": "string",
|
|
"format": "ipv4"
|
|
},
|
|
"internalIp": {
|
|
"type": "string",
|
|
"format": "ipv4"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"timestamp": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"packetLoss": {
|
|
"type": "number"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"ResultsCollection": {
|
|
"description": "Paginated list of Speedtest results",
|
|
"properties": {
|
|
"data": {
|
|
"description": "Array of result objects",
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/components/schemas/Result"
|
|
}
|
|
},
|
|
"links": {
|
|
"properties": {
|
|
"first": {
|
|
"type": "string"
|
|
},
|
|
"last": {
|
|
"type": "string"
|
|
},
|
|
"prev": {
|
|
"type": "string",
|
|
"nullable": true
|
|
},
|
|
"next": {
|
|
"type": "string",
|
|
"nullable": true
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"meta": {
|
|
"properties": {
|
|
"current_page": {
|
|
"type": "integer"
|
|
},
|
|
"from": {
|
|
"type": "integer"
|
|
},
|
|
"last_page": {
|
|
"type": "integer"
|
|
},
|
|
"links": {
|
|
"type": "array",
|
|
"items": {
|
|
"properties": {
|
|
"url": {
|
|
"type": "string",
|
|
"nullable": true
|
|
},
|
|
"label": {
|
|
"type": "string"
|
|
},
|
|
"active": {
|
|
"type": "boolean"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
}
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"per.page": {
|
|
"type": "integer"
|
|
},
|
|
"to": {
|
|
"type": "integer"
|
|
},
|
|
"total": {
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"ServersCollection": {
|
|
"description": "Collection of Ookla speedtest servers",
|
|
"properties": {
|
|
"data": {
|
|
"description": "List of server objects",
|
|
"type": "array",
|
|
"items": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "string"
|
|
},
|
|
"host": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"location": {
|
|
"type": "string"
|
|
},
|
|
"country": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"message": {
|
|
"description": "Response status message",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"SpeedtestRun": {
|
|
"description": "A queued speedtest result",
|
|
"properties": {
|
|
"data": {
|
|
"description": "Queued speedtest result payload",
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer"
|
|
},
|
|
"service": {
|
|
"type": "string"
|
|
},
|
|
"ping": {
|
|
"type": "number",
|
|
"format": "float",
|
|
"nullable": true
|
|
},
|
|
"download": {
|
|
"type": "integer",
|
|
"nullable": true
|
|
},
|
|
"upload": {
|
|
"type": "integer",
|
|
"nullable": true
|
|
},
|
|
"benchmarks": {
|
|
"type": "object",
|
|
"nullable": true
|
|
},
|
|
"healthy": {
|
|
"type": "boolean",
|
|
"nullable": true
|
|
},
|
|
"status": {
|
|
"type": "string"
|
|
},
|
|
"scheduled": {
|
|
"type": "boolean"
|
|
},
|
|
"comments": {
|
|
"type": "string",
|
|
"nullable": true
|
|
},
|
|
"data": {
|
|
"description": "Additional data for queued result",
|
|
"properties": {
|
|
"server": {
|
|
"properties": {
|
|
"id": {
|
|
"type": "integer",
|
|
"nullable": true
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"created_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"updated_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"message": {
|
|
"description": "Response status message",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object",
|
|
"additionalProperties": false
|
|
},
|
|
"Stats": {
|
|
"description": "Aggregated speedtest statistics",
|
|
"properties": {
|
|
"total_results": {
|
|
"type": "integer"
|
|
},
|
|
"avg_ping": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"avg_download": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"avg_upload": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"min_ping": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"min_download": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"min_upload": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"max_ping": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"max_download": {
|
|
"type": "number",
|
|
"format": "float"
|
|
},
|
|
"max_upload": {
|
|
"type": "number",
|
|
"format": "float"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"UnauthenticatedError": {
|
|
"description": "Error when user is not authenticated",
|
|
"properties": {
|
|
"message": {
|
|
"description": "Unauthenticated error message",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"ValidationError": {
|
|
"description": "Validation failed due to invalid server_id input",
|
|
"properties": {
|
|
"message": {
|
|
"description": "Validation failed due to invalid server_id input",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
}
|
|
},
|
|
"parameters": {
|
|
"AcceptHeader": {
|
|
"name": "Accept",
|
|
"in": "header",
|
|
"description": "Must be \"application/json\" - this API only accepts and returns JSON",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string",
|
|
"default": "application/json"
|
|
}
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"bearerAuth": {
|
|
"type": "http",
|
|
"bearerFormat": "JWT",
|
|
"scheme": "bearer"
|
|
}
|
|
}
|
|
},
|
|
"tags": [
|
|
{
|
|
"name": "Results",
|
|
"description": "Endpoints for accessing and filtering speedtest results. Requires API token with `results:read` scope."
|
|
},
|
|
{
|
|
"name": "Speedtests",
|
|
"description": "Endpoints for running speedtests and listing servers."
|
|
},
|
|
{
|
|
"name": "Stats",
|
|
"description": "Endpoints for retrieving aggregated statistics and performance metrics. Requires `speedtests:read` token scope."
|
|
},
|
|
{
|
|
"name": "Servers",
|
|
"description": "Servers"
|
|
}
|
|
]
|
|
} |