{
  "openapi": "3.0.3",
  "info": {
    "title": "Screenshare Scanner API",
    "version": "1.0.0",
    "description": "Server-side integrations using scoped account API keys. An active license is required. Keys expire after at most 365 days and are limited by a dated license's expiry. Lifetime licenses have lifetime:true and expiresAt:null; their API keys still expire. Removal, blacklist or license expiry revokes access.",
    "termsOfService": "https://screenshareac.org/tos/"
  },
  "servers": [
    {
      "url": "https://screenshareac.org/api"
    }
  ],
  "paths": {
    "/accounts": {
      "get": {
        "summary": "Read your account",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scope": "user:read",
        "responses": {
          "200": {
            "description": "Account and license",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope, license, account or IP access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Report unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "State conflict or earlier consent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/invites": {
      "post": {
        "summary": "Create an invitation or query its result",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scope": "scan:create or scan:read",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope, license, account or IP access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Report unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "State conflict or earlier consent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Invitation created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invitation"
                }
              }
            }
          },
          "410": {
            "description": "Invitation or result expired",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        },
        "description": "Create a single-use scan invitation using the saved customization, or query an existing invitation. The scanner opens Terms & Privacy first. After the player chooses Accept, the PIN fills in and the scan starts automatically. A PIN alone cannot authorize a scan.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "action"
                    ],
                    "properties": {
                      "action": {
                        "type": "string",
                        "enum": [
                          "create"
                        ]
                      },
                      "profileRevision": {
                        "type": "integer",
                        "minimum": 0
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "action",
                      "token"
                    ],
                    "properties": {
                      "action": {
                        "type": "string",
                        "enum": [
                          "status",
                          "result"
                        ]
                      },
                      "token": {
                        "type": "string",
                        "pattern": "^[a-f0-9]{64}$"
                      },
                      "includeLink": {
                        "type": "boolean"
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/scans": {
      "get": {
        "summary": "Read a report or list your scans",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scope": "scan:read",
        "responses": {
          "200": {
            "description": "Scan report or paginated list",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Report"
                    },
                    {
                      "$ref": "#/components/schemas/ScanList"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope, license, account or IP access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Report unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "State conflict or earlier consent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Use exactly one of id, list:mine or pin. A public consent2.9 report may be read anonymously using id. List and PIN lookup always require scan:read and only return owned reports.",
        "parameters": [
          {
            "in": "query",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Report ID"
          },
          {
            "in": "query",
            "name": "list",
            "schema": {
              "type": "string",
              "enum": [
                "mine"
              ]
            },
            "description": "List owned reports"
          },
          {
            "in": "query",
            "name": "pin",
            "schema": {
              "type": "string",
              "minLength": 5,
              "maxLength": 5
            },
            "description": "Five-character PIN, never an access credential"
          },
          {
            "in": "query",
            "name": "page",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 1
            },
            "description": "50 reports per page; follow hasMore"
          }
        ]
      },
      "post": {
        "summary": "Change report visibility",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-required-scope": "scan:publish",
        "responses": {
          "200": {
            "description": "Updated visibility",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Visibility"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired key",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Insufficient scope, license, account or IP access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Report unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "State conflict or earlier consent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "description": "Publishing requires consent2.9. Reports are private by default. Public grants anonymous access to the full report and its matched history.",
        "parameters": [
          {
            "in": "query",
            "name": "action",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "visibility"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id",
                  "visibility"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "visibility": {
                    "type": "string",
                    "enum": [
                      "private",
                      "public"
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "ssk_..."
      }
    },
    "schemas": {
      "Account": {
        "type": "object",
        "properties": {
          "user": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "email": {
                "type": "string",
                "format": "email"
              },
              "confirmedAt": {
                "type": "string",
                "nullable": true
              },
              "createdAt": {
                "type": "string"
              }
            }
          },
          "license": {
            "type": "object",
            "properties": {
              "status": {"type": "string", "enum": ["active", "expired", "disabled", "none"]},
              "lifetime": {"type": "boolean", "description": "True only for a lifetime license; omitted for dated licenses."},
              "expiresAt": {"type": "string", "format": "date-time", "nullable": true, "description": "Null for lifetime licenses."}
            },
            "additionalProperties": true
          },
          "message": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Invitation": {
        "type": "object",
        "required": [
          "url",
          "scanCode",
          "expiresAt",
          "profileRevision"
        ],
        "properties": {
          "url": {
            "type": "string",
            "example": "/start#invite=INVITATION_TOKEN"
          },
          "scanCode": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "profileRevision": {
            "type": "integer"
          }
        }
      },
      "Visibility": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "visibility": {
            "type": "string",
            "enum": [
              "private",
              "public"
            ]
          },
          "canManage": {
            "type": "boolean"
          },
          "canPublish": {
            "type": "boolean"
          },
          "publishBlockedReason": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "Report": {
        "type": "object",
        "description": "Full stored report. Collection-dependent fields can be absent. Reports expire after seven days.",
        "additionalProperties": true,
        "properties": {
          "schemaVersion": {
            "type": "integer"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "durationMs": {
            "type": "integer"
          },
          "scannerVersion": {
            "type": "string"
          },
          "findings": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "coverage": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "identity": {
            "type": "object",
            "additionalProperties": true
          },
          "system": {
            "type": "object",
            "additionalProperties": true
          },
          "access": {
            "$ref": "#/components/schemas/Visibility"
          }
        }
      },
      "ScanList": {
        "type": "object",
        "properties": {
          "scans": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "createdAt": {
                  "type": "string"
                },
                "steamName": {
                  "type": "string",
                  "nullable": true
                },
                "verdict": {
                  "type": "string"
                },
                "counts": {
                  "type": "object",
                  "additionalProperties": true
                },
                "fileCount": {
                  "type": "integer"
                },
                "visibility": {
                  "type": "string",
                  "enum": [
                    "private",
                    "public"
                  ]
                },
                "scanCode": {
                  "type": "string",
                  "nullable": true
                }
              }
            }
          },
          "page": {
            "type": "integer"
          },
          "hasMore": {
            "type": "boolean"
          },
          "truncated": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
