{
  "openapi": "3.0.1",
  "info": {
    "title": "Sahha Platform v1",
    "version": "v1"
  },
  "paths": {
    "/api/v1/oauth/account/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Get Account Token",
        "description": "Returns an Account access token when provided with a valid ClientId and ClientSecret. This token is used to perform administrative tasks like creating / modifying end user profiles and reporting.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveClientTokenRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveClientTokenRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveClientTokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returns a token response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RetrieveClientTokenCommandResult"
                }
              }
            }
          },
          "400": {
            "description": "Returned if the ClientId or ClientSecret is invalid, or if the X-Environment header is missing."
          }
        }
      }
    },
    "/api/v1/account/credentials/roll": {
      "post": {
        "tags": [
          "Credentials"
        ],
        "summary": "Roll a secret",
        "description": "Creates a new secret for the account's application or client credential in the given environment and returns it once. The secret it replaces keeps working until expireOldIn has passed: 7 days by default for a client secret, until it is revoked for an app secret, so shipped apps keep working until they are updated. A credential holds at most two active secrets, so a third roll is refused until one is revoked or has expired. The caller must be a member of the account, signed in with a user token.",
        "parameters": [
          {
            "name": "environment",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RollCredentialSecretRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RollCredentialSecretRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RollCredentialSecretRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The new secret and every secret of the credential.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RollCredentialSecretResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request isn't valid, or its environment isn't the one it was sent to.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in."
          },
          "403": {
            "description": "Not a member of the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The account has no such credential in the environment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Two secrets are already active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too many credential changes by this user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/credentials/secrets/{secretId}/restore": {
      "post": {
        "tags": [
          "Credentials"
        ],
        "summary": "Restore a revoked secret",
        "description": "Makes a revoked secret authenticate again. Any member of the account can restore within 24 hours of the revoke; after that, contact support. Refused while the credential already has two active secrets, and once the secret's own expiry has passed.",
        "parameters": [
          {
            "name": "secretId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreCredentialSecretRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreCredentialSecretRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreCredentialSecretRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Every secret of the credential after the restore.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialSecretsResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request isn't valid, or its environment isn't the one it was sent to.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in."
          },
          "403": {
            "description": "Not a member of the account, or more than 24 hours since the revoke.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The account has no such credential in the environment, or the credential has no secret with this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The secret isn't revoked, has expired, or two secrets are already active.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too many credential changes by this user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/credentials/secrets/{secretId}/revoke": {
      "post": {
        "tags": [
          "Credentials"
        ],
        "summary": "Revoke a secret",
        "description": "Stops the secret authenticating. A client secret stops minting account tokens immediately; an app secret stops registering profiles within five minutes. Tokens already issued are unaffected. The reason is required and recorded. Any member of the account can restore the secret within 24 hours.",
        "parameters": [
          {
            "name": "secretId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "environment",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeCredentialSecretRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeCredentialSecretRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeCredentialSecretRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Every secret of the credential after the revoke.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CredentialSecretsResponse"
                }
              }
            }
          },
          "400": {
            "description": "The request isn't valid, has no reason, or its environment isn't the one it was sent to.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Not signed in."
          },
          "403": {
            "description": "Not a member of the account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The account has no such credential in the environment, or the credential has no secret with this id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "The secret is already expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Too many credential changes by this user.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profile/archetypes": {
      "get": {
        "tags": [
          "Archetypes"
        ],
        "summary": "Get archetypes (Profile Authorization)",
        "description": "Gets archetypes for a given time window for a profile with profile authorization. Can be filtered by archetype name and periodicity.",
        "parameters": [
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ArchetypeDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/profile/archetypes/{externalId}": {
      "get": {
        "tags": [
          "Archetypes"
        ],
        "summary": "Get archetypes (Account Authorization)",
        "description": "Gets archetypes for a given time window for a profile with account authorization. Can be filtered by archetype name and periodicity.",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ArchetypeDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/oauth/profile/refreshToken": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Refresh Token",
        "description": "Returns a refreshed profile token to be used in the authorization header as 'profile {token}'.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshProfileTokenRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshProfileTokenRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RefreshProfileTokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returns a token response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      }
    },
    "/api/v1/oauth/profile/register": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Register a Profile using Account Token (For Server to Server Integration)",
        "description": "Creates a new profile a returns a Profile token. A profile represents your end user. Requires a valid <b>Account</b> token in the authorization header.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Initialises a new profile and returns a Profile Token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "400": {
            "description": "Returned if the provided external id is invalid or already in use."
          }
        }
      }
    },
    "/api/v1/oauth/profile/register/appId": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Register Profile using Application Credentials (For SDK Integration)",
        "description": "Creates a new profile and returns a profile token. A profile represents your end user. Required valid <b>AppId</b> and <b>AppSecret</b> in the headers.",
        "parameters": [
          {
            "name": "appId",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "appSecret",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterProfileRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Initialises a new Profile and returns a profile token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the headers are invalid."
          },
          "400": {
            "description": "Returned if the external id provided is invalid."
          }
        }
      }
    },
    "/api/v1/oauth/profile/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Get Profile Token using Account Token",
        "description": "Returns a profile token to be used in the authorization header as 'profile {token}'.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveProfileTokenRequest"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveProfileTokenRequest"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/RetrieveProfileTokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returns a token response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "400": {
            "description": "Returned if the external ID provided is invalid."
          }
        }
      }
    },
    "/api/v1/profile/biomarker": {
      "get": {
        "tags": [
          "Biomarkers"
        ],
        "summary": "Get biomarkers (Profile Authorization)",
        "description": "Gets biomarkers for a given time window for a profile with profile authorization.",
        "parameters": [
          {
            "name": "categories",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BiomarkerDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Returned if the profile id claim in the token is invalid."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      }
    },
    "/api/v1/profile/biomarker/{externalId}": {
      "get": {
        "tags": [
          "Biomarkers"
        ],
        "summary": "Get biomarkers (Account Authorization)",
        "description": "Gets biomarkers for a given time window for a profile with account authorization.",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "categories",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/BiomarkerDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Returned if the provided profile id is invalid."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      }
    },
    "/api/v1/profile/{accountId}/{profileId}/data/log/count": {
      "get": {
        "tags": [
          "Data Logs"
        ],
        "summary": "Get data log count (User Authorization)",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "profileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "startDateTimeUtc",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTimeUtc",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    },
    "/api/v1/profile/data/log": {
      "post": {
        "tags": [
          "Data Logs"
        ],
        "summary": "Upload data logs (Profile Authorization)",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DataLogDto"
                }
              }
            },
            "text/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DataLogDto"
                }
              }
            },
            "application/*+json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/DataLogDto"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    },
    "/api/v2/profile/data/log": {
      "post": {
        "tags": [
          "Data Logs"
        ],
        "summary": "Upload data logs (Profile Authorization)",
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    },
    "/api/v1/profile/insight/comparison": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Get comparisons (Profile Authorization)",
        "description": "Gets comparison data for a profile with profile authorization. Can be filtered by name, category, and date range.",
        "parameters": [
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "daily"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ComparisonDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/profile/insight/comparison/{externalId}": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Get comparisons (Account Authorization)",
        "description": "Gets comparison data for a profile with account authorization. Can be filtered by name, category, and date range.",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "daily"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ComparisonDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/profile/insight/trend": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Get trends (Profile Authorization)",
        "description": "Gets trend data for a profile with profile authorization. Can be filtered by name, category, and date range.",
        "parameters": [
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "weekly"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TrendDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/profile/insight/trend/{externalId}": {
      "get": {
        "tags": [
          "Insights"
        ],
        "summary": "Get trends (Account Authorization)",
        "description": "Gets trend data for a profile with account authorization. Can be filtered by name, category, and date range.",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "periodicity",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "weekly"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TrendDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          }
        }
      }
    },
    "/api/v1/account/profile/{externalId}": {
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get profile (Account Authorization)",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/account/profile/search": {
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Search profiles (Account Authorization)",
        "parameters": [
          {
            "name": "searchParameter",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currentPage",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 0
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32",
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Returns a paged list that match the search parameter.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileSearchResultItemPagedList"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/profile": {
      "delete": {
        "tags": [
          "Profile"
        ],
        "summary": "Delete profiles (Account Authorization)",
        "description": "Deletes profiles from the user account based on the provided list of external ids.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "text/json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "application/*+json": {
              "schema": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Returned if the delete operation is successful."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      },
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get profile (Profile Authorization)",
        "description": "Returns information for a profile. Requires a valid <b>Profile</b> token in the authorization header.",
        "responses": {
          "200": {
            "description": "Returns information for the profile specified by the token in the authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicDto"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "204": {
            "description": "Returned if there are no results for the query."
          }
        }
      }
    },
    "/api/v1/profile/demographic": {
      "put": {
        "tags": [
          "Profile"
        ],
        "summary": "Replace demographic (Profile Authorization)",
        "description": "Replaces the demographic information for a profile eg. Age, Gender. Requires a valid <b>Profile</b> token in the authorization header.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updates the demographic information for the profile."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "400": {
            "description": "Returned if the request data is invalid or empty."
          }
        }
      },
      "patch": {
        "tags": [
          "Profile"
        ],
        "summary": "Update demographic (Profile Authorization)",
        "description": "Patches the demographic information for a profile eg. Age, Gender. Requires a valid <b>Profile</b> token in the authorization header.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/DemographicDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updates the demographic information for the profile."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "400": {
            "description": "Returned if the request data is invalid or empty."
          }
        }
      },
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get demographic (Profile Authorization)",
        "description": "Returns the demographic information for a profile. Requires a valid <b>Profile</b> token in the authorization header.",
        "responses": {
          "200": {
            "description": "Returns demographic information for the profile specified by the token in the authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DemographicDto"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "204": {
            "description": "Returned if there are no results for the query."
          }
        }
      }
    },
    "/api/v1/profile/deviceInformation": {
      "put": {
        "tags": [
          "Profile"
        ],
        "summary": "Update device information (Profile Authorization)",
        "description": "Updates the device information for a profile, this is done automatically by the SDK if available. Requires a valid <b>Profile</b> token in the authorization header.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceInformationDto"
              }
            },
            "text/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceInformationDto"
              }
            },
            "application/*+json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceInformationDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updates device information."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "400": {
            "description": "Returned if the request data is invalid or empty."
          }
        }
      },
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "Get device information (Profile Authorization)",
        "description": "Returns the device information for a profile. Requires a valid <b>Profile</b> token in the authorization header.",
        "responses": {
          "200": {
            "description": "Returns device information for the profile specified by the token in the authorization header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceInformationDto"
                }
              }
            }
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          },
          "204": {
            "description": "Returned if there are no results for the query."
          }
        }
      }
    },
    "/api/v1/profile/score": {
      "get": {
        "tags": [
          "Scores"
        ],
        "summary": "Get scores (Profile Authorization)",
        "description": "Gets scores for a given time window for a profile.",
        "parameters": [
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ScoreDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Returned if the profile id claim in the token is invalid."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      }
    },
    "/api/v1/profile/score/{externalId}": {
      "get": {
        "tags": [
          "Scores"
        ],
        "summary": "Get scores (Account Authorization)",
        "description": "Gets scores for a given time window for a profile.",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "version",
            "in": "query",
            "schema": {
              "type": "number",
              "format": "float",
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ScoreDto"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Returned if the provided profile id is invalid."
          },
          "401": {
            "description": "Returned if the authorization token is invalid."
          }
        }
      }
    },
    "/api/v1/profile/tag": {
      "post": {
        "tags": [
          "Tags"
        ],
        "summary": "Upload tags (Profile Authorization)",
        "description": "Stores one or more tags for the authenticated profile and returns\r\nthe server-generated id for each. Stored tags are typically\r\nqueryable on `GET /api/v1/profile/tag` within a few seconds.\r\n            \r\nThe body is a JSON array of tags, optionally gzip-encoded\r\n(`Content-Encoding: gzip`). The uncompressed body must be\r\n256 KB or smaller.\r\n            \r\nEach tag's id is derived from `profile + Type + Name + Source + StartDateTime`;\r\nany `Id` sent in the request is ignored. The response's\r\n`Ids` is positional — `Ids[N]` matches the tag at index\r\n`N` in the request. Re-uploading the same identity tuple\r\nupdates the existing tag; to close out an ongoing `state`\r\ntag, re-upload it with `EndDateTime` set.\r\n            \r\nReserved tag names (e.g. `fever`, `pregnancy`) must use\r\nthe `Type`, `Category`, and `Value` combinations\r\ndefined in the [reserved tag schema](https://docs.sahha.ai/docs/products/tags#list-of-tags-reserved).\r\nA reserved tag whose values don't match is skipped, listed in\r\n`Warnings`, and appears as `null` in `Ids`; other\r\ntags in the same batch are unaffected.\r\n            \r\nThe whole batch is rejected with 400 when the body is empty or\r\nmalformed, a `StartDateTime` is not ISO 8601 with a timezone\r\noffset, or the uncompressed payload exceeds 256 KB.",
        "operationId": "Tags_UploadAsProfile",
        "requestBody": {
          "description": "JSON array of tags to store for the authenticated profile.",
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TagDto"
                }
              },
              "example": [
                {
                  "id": null,
                  "type": "state",
                  "startDateTime": "2024-02-09T19:00:00.0000000+00:00",
                  "endDateTime": "2024-02-10T07:00:00.0000000+00:00",
                  "name": "night_shift",
                  "category": "work",
                  "value": "12_hour",
                  "source": "acme.workforce",
                  "additionalProperties": {
                    "role": "icu_nurse",
                    "overtime": "false"
                  }
                },
                {
                  "id": null,
                  "type": "state",
                  "startDateTime": "2024-01-28",
                  "endDateTime": null,
                  "name": "premium_tier",
                  "category": "subscription",
                  "value": "annual",
                  "source": "acme.billing",
                  "additionalProperties": {
                    "autoRenew": "true",
                    "priceUsd": "99"
                  }
                },
                {
                  "id": null,
                  "type": "event",
                  "startDateTime": "2024-02-11T12:30:00.0000000+00:00",
                  "endDateTime": null,
                  "name": "insulin_bolus",
                  "category": "medication",
                  "value": "6_units",
                  "source": "acme.clinical",
                  "additionalProperties": {
                    "timing": "before_breakfast"
                  }
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag batch processed. Ids is positional with the request; rejected tags are null with the reason in Warnings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagUploadResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Body is empty or malformed, a StartDateTime is not ISO 8601 with a timezone offset, or the payload exceeds 256 KB."
          },
          "401": {
            "description": "Missing or invalid Profile token."
          }
        }
      },
      "get": {
        "tags": [
          "Tags"
        ],
        "summary": "Get tags (Profile Authorization)",
        "description": "Lists tags for the authenticated profile.",
        "operationId": "Tags_GetAsProfile",
        "parameters": [
          {
            "name": "types",
            "in": "query",
            "description": "Optional filter by tag shape — one or both of `event` and `state`. Repeat the parameter to supply multiple values.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "categories",
            "in": "query",
            "description": "Optional list of tag categories to filter by (e.g. `work`, `subscription`, `medication`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "names",
            "in": "query",
            "description": "Optional list of tag names to filter by (e.g. `night_shift`, `premium_tier`, `insulin_bolus`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "sources",
            "in": "query",
            "description": "Optional list of source identifiers to filter by (e.g. `acme.workforce`, `acme.billing`, `acme.clinical`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "description": "Inclusive lower bound on the tag's `StartDateTime`, in the profile's local time (no timezone offset). Defaults to endDateTime minus 7 days when unset.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "description": "Inclusive upper bound on the tag's `StartDateTime`, in the profile's local time (no timezone offset). Defaults to `now` when unset.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of tags ordered newest-first by StartDateTime.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagResponseDto"
                  }
                },
                "example": [
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a01",
                    "type": "state",
                    "name": "night_shift",
                    "category": "work",
                    "value": "12_hour",
                    "source": "acme.workforce",
                    "startDateTime": "2024-02-09T19:00:00.0000000+00:00",
                    "endDateTime": "2024-02-10T07:00:00.0000000+00:00",
                    "receivedAtUtc": "2024-02-10T07:05:02.0000000+00:00",
                    "additionalProperties": {
                      "role": "icu_nurse",
                      "overtime": "false"
                    }
                  },
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a02",
                    "type": "state",
                    "name": "premium_tier",
                    "category": "subscription",
                    "value": "annual",
                    "source": "acme.billing",
                    "startDateTime": "2024-01-28",
                    "endDateTime": null,
                    "receivedAtUtc": "2024-01-28T00:00:16.0000000+00:00",
                    "additionalProperties": {
                      "autoRenew": "true",
                      "priceUsd": "99"
                    }
                  },
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a03",
                    "type": "event",
                    "name": "insulin_bolus",
                    "category": "medication",
                    "value": "6_units",
                    "source": "acme.clinical",
                    "startDateTime": "2024-02-11T12:30:00.0000000+00:00",
                    "endDateTime": null,
                    "receivedAtUtc": "2024-02-11T12:30:10.0000000+00:00",
                    "additionalProperties": {
                      "timing": "before_breakfast"
                    }
                  }
                ]
              }
            }
          },
          "400": {
            "description": "endDateTime is earlier than startDateTime."
          },
          "401": {
            "description": "Missing or invalid Profile token."
          }
        }
      }
    },
    "/api/v1/profile/tag/{externalId}": {
      "post": {
        "tags": [
          "Tags"
        ],
        "summary": "Upload tags (Account Authorization)",
        "description": "Stores one or more tags for the profile identified by\r\nexternalId and returns the server-generated id\r\nfor each. Stored tags are typically queryable on\r\n`GET /api/v1/profile/tag/{externalId}` within a few seconds.\r\n            \r\nThe body, identity-tuple, positional-id, reserved-name, and 400\r\nrules are identical to `POST /api/v1/profile/tag`. The only\r\ndifferences are the authorization mode (Account token) and the\r\nfact that the target profile is resolved from the URL's\r\n`externalId` rather than the token. A 404 is returned only\r\nwhen no profile with the supplied externalId exists for the\r\ncalling account.",
        "operationId": "Tags_UploadAsAccount",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "description": "The integrator's stable identifier for the profile.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "JSON array of tags to store for the resolved profile.",
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/TagDto"
                }
              },
              "example": [
                {
                  "id": null,
                  "type": "state",
                  "startDateTime": "2024-02-09T19:00:00.0000000+00:00",
                  "endDateTime": "2024-02-10T07:00:00.0000000+00:00",
                  "name": "night_shift",
                  "category": "work",
                  "value": "12_hour",
                  "source": "acme.workforce",
                  "additionalProperties": {
                    "role": "icu_nurse",
                    "overtime": "false"
                  }
                },
                {
                  "id": null,
                  "type": "state",
                  "startDateTime": "2024-01-28",
                  "endDateTime": null,
                  "name": "premium_tier",
                  "category": "subscription",
                  "value": "annual",
                  "source": "acme.billing",
                  "additionalProperties": {
                    "autoRenew": "true",
                    "priceUsd": "99"
                  }
                },
                {
                  "id": null,
                  "type": "event",
                  "startDateTime": "2024-02-11T12:30:00.0000000+00:00",
                  "endDateTime": null,
                  "name": "insulin_bolus",
                  "category": "medication",
                  "value": "6_units",
                  "source": "acme.clinical",
                  "additionalProperties": {
                    "timing": "before_breakfast"
                  }
                }
              ]
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tag batch processed. Ids is positional with the request; rejected tags are null with the reason in Warnings.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TagUploadResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "External id is missing or malformed, body is empty or malformed, a StartDateTime is not ISO 8601 with a timezone offset, or the payload exceeds 256 KB."
          },
          "401": {
            "description": "Missing or invalid Account token, or no access to the resolved profile."
          },
          "404": {
            "description": "No profile with the supplied externalId exists for the account."
          }
        }
      },
      "get": {
        "tags": [
          "Tags"
        ],
        "summary": "Get tags (Account Authorization)",
        "description": "Lists tags for the profile identified by externalId.\r\nIf no profile with that externalId exists the response is 200 with\r\nan empty list rather than 404.",
        "operationId": "Tags_GetAsAccount",
        "parameters": [
          {
            "name": "externalId",
            "in": "path",
            "description": "The integrator's stable identifier for the profile.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "types",
            "in": "query",
            "description": "Optional filter by tag shape — one or both of `event` and `state`. Repeat the parameter to supply multiple values.",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "categories",
            "in": "query",
            "description": "Optional list of tag categories to filter by (e.g. `work`, `subscription`, `medication`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "names",
            "in": "query",
            "description": "Optional list of tag names to filter by (e.g. `night_shift`, `premium_tier`, `insulin_bolus`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "sources",
            "in": "query",
            "description": "Optional list of source identifiers to filter by (e.g. `acme.workforce`, `acme.billing`, `acme.clinical`).",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "startDateTime",
            "in": "query",
            "description": "Inclusive lower bound on the tag's `StartDateTime`, in the profile's local time (no timezone offset). Defaults to endDateTime minus 7 days when unset.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "endDateTime",
            "in": "query",
            "description": "Inclusive upper bound on the tag's `StartDateTime`, in the profile's local time (no timezone offset). Defaults to `now` when unset.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of tags ordered newest-first by StartDateTime. Empty when no profile or no matching tags exist.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/TagResponseDto"
                  }
                },
                "example": [
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a01",
                    "type": "state",
                    "name": "night_shift",
                    "category": "work",
                    "value": "12_hour",
                    "source": "acme.workforce",
                    "startDateTime": "2024-02-09T19:00:00.0000000+00:00",
                    "endDateTime": "2024-02-10T07:00:00.0000000+00:00",
                    "receivedAtUtc": "2024-02-10T07:05:02.0000000+00:00",
                    "additionalProperties": {
                      "role": "icu_nurse",
                      "overtime": "false"
                    }
                  },
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a02",
                    "type": "state",
                    "name": "premium_tier",
                    "category": "subscription",
                    "value": "annual",
                    "source": "acme.billing",
                    "startDateTime": "2024-01-28",
                    "endDateTime": null,
                    "receivedAtUtc": "2024-01-28T00:00:16.0000000+00:00",
                    "additionalProperties": {
                      "autoRenew": "true",
                      "priceUsd": "99"
                    }
                  },
                  {
                    "id": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a03",
                    "type": "event",
                    "name": "insulin_bolus",
                    "category": "medication",
                    "value": "6_units",
                    "source": "acme.clinical",
                    "startDateTime": "2024-02-11T12:30:00.0000000+00:00",
                    "endDateTime": null,
                    "receivedAtUtc": "2024-02-11T12:30:10.0000000+00:00",
                    "additionalProperties": {
                      "timing": "before_breakfast"
                    }
                  }
                ]
              }
            }
          },
          "400": {
            "description": "External id is missing or malformed, or endDateTime is earlier than startDateTime."
          },
          "401": {
            "description": "Missing or invalid Account token, or no access to the resolved profile."
          }
        }
      }
    },
    "/api/v1/integration/profile/integration": {
      "get": {
        "tags": [
          "Profile"
        ],
        "summary": "List the integrations available to this profile",
        "description": "Every integration configured on the account the profile belongs to, annotated with this profile's connection status and connection id. An empty array means the account has configured none, so an app can hide its connect screen entirely.\n\nIntegrations whose provider key this build does not recognise are omitted rather than failing the request.",
        "operationId": "listProfileIntegrations",
        "responses": {
          "200": {
            "description": "Integrations on the account, in creation order, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ProfileIntegration"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "ProfileToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/profile/connection": {
      "get": {
        "tags": [
          "Profile",
          "Connections"
        ],
        "summary": "List this profile's connections",
        "description": "Both identifiers come from the token, so a caller cannot read another profile's connections.",
        "operationId": "listProfileConnections",
        "responses": {
          "200": {
            "description": "This profile's live connections, whatever their status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Connection"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "ProfileToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/profile/connection/{connectionId}": {
      "delete": {
        "tags": [
          "Profile",
          "Connections"
        ],
        "summary": "Disconnect this profile from a provider",
        "description": "Soft-deletes the connection and, when nothing else uses it, destroys the stored provider credential. A connection owned by another profile in the same account reports 404 rather than 403, so a caller cannot learn it exists.\n\nAfter this, authorising again creates a new connection rather than reviving this one.",
        "operationId": "deleteOwnConnection",
        "parameters": [
          {
            "name": "connectionId",
            "in": "path",
            "description": "Connection to delete. Must belong to the calling profile.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Disconnected."
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "ProfileToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/profile/oauth/{providerKey}/authorize": {
      "get": {
        "tags": [
          "Profile",
          "OAuth"
        ],
        "summary": "Start the authorisation flow for this profile",
        "description": "Returns the provider consent URL to open in a system browser session (`ASWebAuthenticationSession`, Chrome Custom Tabs, or equivalent). One-time state and a PKCE verifier are stored server-side.\n\nAfter the user consents, the provider redirects to this service's callback, which exchanges the code, stores the credential, creates **or revives** the connection, and then redirects the browser to `redirectUrl` with `?status=success`, or `?status=error&error=<reason>`.\n\nCalling this for a provider the profile is already connected to, or whose connection is expired or revoked, reconnects it: the existing connection is revived and repointed at the newly authorised provider account. There is no need to disconnect first.",
        "operationId": "authorize",
        "parameters": [
          {
            "name": "providerKey",
            "in": "path",
            "description": "Provider key as returned by GET /api/v1/integration/user/provider.",
            "required": true,
            "schema": {
              "type": "string",
              "example": "whoop"
            }
          },
          {
            "name": "redirectUrl",
            "in": "query",
            "description": "Where to send the browser when the flow finishes. Must match an entry in the integration's redirectWhitelist exactly. Defaults to the first whitelisted URL when omitted.",
            "schema": {
              "type": "string",
              "example": "myapp://oauth/callback"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Consent URL to open.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthorizeResponse"
                }
              }
            }
          },
          "400": {
            "description": "providerKey missing, or redirectUrl is not whitelisted for this integration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "The account has no integration configured for this provider.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "ProfileToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/account/user/{accountId}/integration": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "summary": "List the account's integrations",
        "description": "Newest first. Carries no clientSecret and no webhookUrl — both are credentials, and a list returns one of each per row; fetch a single integration to reveal them.\n\nAn integration whose provider key this build does not recognise is still listed, named by its raw key with no available scopes, so it can be found and deleted.",
        "operationId": "listIntegrations",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "200": {
            "description": "Configured integrations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/IntegrationListItem"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      },
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Configure a provider for the account",
        "description": "Stores the OAuth credentials, encrypts the secret, and assigns the webhook token. One integration per provider per account.\n\nThe webhook URL is the one the setup endpoint answers with beforehand, so it can already be registered with the provider by the time the integration is created. Send that answer's `webhookToken` to have the create confirm the URL has not changed since.\n\nThe response carries the webhookUrl and the submitted clientSecret together. Where the provider is not auto-registered and the URL was not registered beforehand, register it now.",
        "operationId": "createIntegration",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateIntegrationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "description": "Validation failed: unsupported providerKey, empty clientId or clientSecret, empty or malformed redirectWhitelist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "409": {
            "description": "This account already has an integration for the provider, the clientId is in use, or the `webhookToken` sent is no longer current. The last names `webhookToken` as the error's origin and is resolved by fetching the setup again; the other two name `resource`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/account/user/{accountId}/integration/setup/{providerKey}": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "summary": "Fetch what a provider needs before its integration exists",
        "description": "Answers the webhook URL an integration for this provider will have, before the integration exists. The URL can then be registered with the provider first, so the integration is created once with everything in place instead of being created and then edited.\n\nThe URL is derived rather than reserved: asking again returns the same one until the integration is created, and nothing is stored if it never is. It changes when an integration for the same provider has been created and deleted in the meantime.\n\nSend `webhookToken` back in the create request. The create then refuses a URL that has changed since it was fetched, instead of storing a different one from the one registered with the provider.\n\nWhere `webhookAutoRegistered` is true the provider is subscribed programmatically, and the URL does not need registering by hand.",
        "operationId": "getIntegrationSetup",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "providerKey",
            "in": "path",
            "description": "Provider key as returned by GET /api/v1/integration/user/provider.",
            "required": true,
            "schema": {
              "type": "string",
              "example": "whoop"
            }
          }
        ],
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "200": {
            "description": "The webhook URL the integration will have, and the token behind it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationSetup"
                }
              }
            }
          },
          "404": {
            "description": "The provider key is not one this build supports.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "This account already has an integration for the provider. Its webhook URL is on the integration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/account/user/{accountId}/integration/{integrationId}": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "summary": "Fetch one integration, with credentials",
        "description": "Returns the decrypted clientSecret and the webhookUrl. One integration, fetched deliberately.\n\nAn integration whose provider key this build does not recognise answers 404 here. It is still listed, so it can be found and deleted.",
        "operationId": "getIntegration",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "integrationId",
            "in": "path",
            "description": "Integration to fetch.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "200": {
            "description": "The integration.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integration"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      },
      "put": {
        "tags": [
          "Integrations"
        ],
        "summary": "Update scopes, redirect whitelist, or client secret",
        "description": "Partial. Omit clientSecret (or send null) to leave it alone; an empty string is rejected rather than rotating the secret to nothing.\n\nThis is where an app's deep link is added to redirectWhitelist so authorize will accept it.",
        "operationId": "updateIntegration",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "integrationId",
            "in": "path",
            "description": "Integration to update.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateIntegrationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "204": {
            "description": "Updated."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      },
      "delete": {
        "tags": [
          "Integrations"
        ],
        "summary": "Delete an integration",
        "description": "Soft-deletes the integration and, asynchronously, every connection to it, destroying the stored provider credentials. Profiles connected through it stop delivering data.",
        "operationId": "deleteIntegration",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "integrationId",
            "in": "path",
            "description": "Integration to delete.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "204": {
            "description": "Deleted."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/account/user/{accountId}/connection": {
      "get": {
        "tags": [
          "Connections"
        ],
        "summary": "List and filter the account's connections",
        "operationId": "listAccountConnections",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "currentPage",
            "in": "query",
            "description": "Anything below 1 is treated as 1.",
            "schema": {
              "minimum": 1,
              "type": "integer",
              "default": 1
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "description": "Clamped to 100.",
            "schema": {
              "maximum": 100,
              "minimum": 1,
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "searchParameter",
            "in": "query",
            "description": "Free-text match on the connection's external and provider user ids.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "provider",
            "in": "query",
            "description": "Must be a registered provider key; an unknown key is a 400, not an empty page.",
            "schema": {
              "type": "string",
              "example": "oura"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ConnectionStatus"
            }
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid provider or status filter, or a malformed accountId.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "200": {
            "description": "Matching connections.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedConnectionList"
                }
              }
            }
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/account/user/{accountId}/connection/{connectionId}": {
      "delete": {
        "tags": [
          "Connections"
        ],
        "summary": "Disconnect a profile, as an admin",
        "description": "Account-scoped counterpart of the profile's own delete, for any connection on the account.",
        "operationId": "deleteConnection",
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "description": "Account the request acts on. The caller's user token must grant access to it.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "connectionId",
            "in": "path",
            "description": "Connection to delete.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "204": {
            "description": "Disconnected."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/user/provider": {
      "get": {
        "tags": [
          "Providers"
        ],
        "summary": "List supported providers",
        "description": "Every provider this build supports, ordered by key, with the scopes each accepts, the OAuth callback URL to register with it, and whether its webhooks are registered automatically. The catalogue is identical for every account, which is why this route is not account-scoped.",
        "operationId": "listProviders",
        "responses": {
          "200": {
            "description": "Supported providers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Provider"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "security": [
          {
            "UserToken": [ ]
          }
        ]
      }
    },
    "/api/v1/integration/oauth/{providerKey}/callback": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "OAuth redirect target (called by the provider)",
        "description": "Registered as the redirect URI in each provider's developer dashboard, per environment — which is why it keeps this unprefixed path and must not be moved. Not called by clients of ours, and carries no token of ours: the one-time `state` is what authenticates it.\n\nExchanges the code, stores the provider credential, creates or revives the connection, then redirects to the `redirectUrl` from the authorize call with `status=success`, or `status=error&error=<reason>` when any step fails. A failure after a consumed state still redirects, so the app always lands back.",
        "operationId": "oauthCallback",
        "parameters": [
          {
            "name": "providerKey",
            "in": "path",
            "description": "Provider key as returned by GET /api/v1/integration/user/provider.",
            "required": true,
            "schema": {
              "type": "string",
              "example": "whoop"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Opaque one-time value issued by the authorize call.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "in": "query",
            "description": "Authorisation code. Absent when the user denied consent.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "error",
            "in": "query",
            "description": "Set by the provider when the user denied consent.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to the whitelisted redirectUrl, carrying status and, on failure, error.",
            "headers": {
              "Location": {
                "description": "e.g. myapp://oauth/callback?status=success",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "state missing, unknown, or already consumed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/api/v1/integration/webhook/{token}/": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Provider data delivery",
        "description": "Called by the provider, not by clients of ours. The token in the URL is the endpoint's credential and identifies the integration; each provider adapter then validates its own signature. Bodies are provider-specific and capped at 10 MiB.\n\nAnswers 200 for anything a redelivery cannot fix — unknown token, bad signature, unparseable payload — because re-sending the same thing buys nothing and costs a retry storm. 503 is reserved for the one case worth redelivering: the payload was good and this service could not take it.",
        "operationId": "receiveWebhook",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "description": "Webhook token from the integration's webhookUrl.",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Provider-defined payload.",
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted, or rejected in a way a redelivery would not fix."
          },
          "400": {
            "description": "Empty token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Accepted-but-unstorable: the queue or database was unreachable. The provider should redeliver.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Webhook verification challenge",
        "description": "Providers that verify ownership of a webhook URL before delivering to it call this. The response body and headers are whatever that provider's scheme requires.",
        "operationId": "verifyWebhook",
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Provider-defined verification response.",
            "content": {
              "*/*": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Empty token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "No integration holds this token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "Liveness check",
        "description": "Served by every role, including worker and scheduler, which mount nothing else.",
        "operationId": "healthz",
        "responses": {
          "200": {
            "description": "OK.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string",
                  "example": "OK"
                }
              }
            }
          }
        }
      }
    },
    "/swagger/v1/swagger.json": {
      "get": {
        "tags": [
          "Operations"
        ],
        "summary": "This document",
        "operationId": "openApiDocument",
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "CredentialSecretDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The secret's id, used to revoke or restore it.",
            "format": "uuid"
          },
          "credentialType": {
            "type": "string",
            "description": "application or client."
          },
          "isLegacy": {
            "type": "boolean",
            "description": "True for a secret issued before rotation launched. Its value stays readable on the credential while it can authenticate."
          },
          "status": {
            "type": "string",
            "description": "active, expired or revoked."
          },
          "hint": {
            "type": "string",
            "description": "The secret's prefix and last four characters, such as sahha_app_prod_...Ab3x, enough to tell secrets apart and to confirm a revoke. A legacy secret's hint is its last four characters alone.",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "description": "When the secret stops authenticating. Null while it has no expiry.",
            "format": "date-time",
            "nullable": true
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "restoredAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "lastUsedAt": {
            "type": "string",
            "description": "The last time the secret authenticated, to within five minutes.",
            "format": "date-time",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "CredentialSecretsResponse": {
        "type": "object",
        "properties": {
          "secrets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CredentialSecretDto"
            },
            "description": "Every secret of the credential after the change."
          }
        },
        "additionalProperties": false
      },
      "ErrorModel": {
        "type": "object",
        "properties": {
          "origin": {
            "type": "string",
            "nullable": true
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "nullable": true
          },
          "statusCode": {
            "type": "integer",
            "format": "int32"
          },
          "location": {
            "type": "string",
            "nullable": true
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ErrorModel"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "RestoreCredentialSecretRequest": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "The account the credential belongs to.",
            "format": "uuid"
          },
          "environment": {
            "type": "string",
            "description": "sandbox or production. It must be the environment the request is sent to.",
            "example": "sandbox"
          },
          "credentialType": {
            "type": "string",
            "description": "application or client.",
            "example": "client"
          }
        },
        "additionalProperties": false
      },
      "RetrieveClientTokenCommandResult": {
        "type": "object",
        "properties": {
          "accountToken": {
            "type": "string",
            "nullable": true
          },
          "tokenType": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "RetrieveClientTokenRequest": {
        "type": "object",
        "properties": {
          "clientId": {
            "title": "ClientId",
            "type": "string",
            "description": "ClientId retrieved from logging in to https://app.sahha.ai.",
            "example": "12Ch2mfWwgZJdb1hFao7p1sx8xm2GPxA"
          },
          "clientSecret": {
            "title": "ClientSecret",
            "type": "string",
            "description": "Client Secret retrieved from logging in to https://app.sahha.ai.",
            "nullable": true,
            "example": "a1QB23452qr7z2SX9Cieod5plwSjxu2l4tUjhBpZfE4eDWIhciOqn2jY22UGvWQj"
          }
        },
        "additionalProperties": false
      },
      "RevokeCredentialSecretRequest": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "The account the credential belongs to.",
            "format": "uuid"
          },
          "environment": {
            "type": "string",
            "description": "sandbox or production. It must be the environment the request is sent to.",
            "example": "sandbox"
          },
          "credentialType": {
            "type": "string",
            "description": "application or client.",
            "example": "client"
          },
          "reason": {
            "type": "string",
            "description": "Why the secret is being revoked. Recorded against it.",
            "example": "Leaked in a CI log."
          }
        },
        "additionalProperties": false
      },
      "RollCredentialSecretRequest": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "description": "The account the credential belongs to.",
            "format": "uuid"
          },
          "environment": {
            "type": "string",
            "description": "sandbox or production. It must be the environment the request is sent to.",
            "example": "sandbox"
          },
          "credentialType": {
            "type": "string",
            "description": "application or client.",
            "example": "client"
          },
          "expireOldIn": {
            "type": "string",
            "description": "How long the secret being replaced keeps working: immediate, 24h, 7d, 30d or untilRevoked. Defaults to 7d for a client secret and untilRevoked for an app secret. Ignored when the credential has no secret yet.",
            "nullable": true,
            "example": "7d"
          }
        },
        "additionalProperties": false
      },
      "RollCredentialSecretResponse": {
        "type": "object",
        "properties": {
          "secret": {
            "type": "string",
            "description": "The new secret. It is shown once and cannot be retrieved again; store it now."
          },
          "secretId": {
            "type": "string",
            "description": "The new secret's id, as listed in secrets.",
            "format": "uuid"
          },
          "secrets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CredentialSecretDto"
            },
            "description": "Every secret of the credential after the roll, including the one being replaced and its expiry."
          }
        },
        "additionalProperties": false
      },
      "ArchetypeDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "value": {
            "type": "string",
            "nullable": true
          },
          "dataType": {
            "type": "string",
            "nullable": true
          },
          "periodicity": {
            "type": "string",
            "nullable": true
          },
          "startDateTime": {
            "type": "string",
            "format": "date-time"
          },
          "endDateTime": {
            "type": "string",
            "format": "date-time"
          },
          "ordinality": {
            "type": "integer",
            "format": "int32"
          },
          "version": {
            "type": "number",
            "format": "float"
          }
        },
        "additionalProperties": false
      },
      "BiomarkerDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "id",
            "format": "uuid"
          },
          "category": {
            "type": "string",
            "nullable": true,
            "example": "activity"
          },
          "type": {
            "type": "string",
            "nullable": true,
            "example": "step_count"
          },
          "periodicity": {
            "type": "string",
            "nullable": true,
            "example": "daily"
          },
          "aggregation": {
            "type": "string",
            "nullable": true,
            "example": "sum"
          },
          "value": {
            "type": "string",
            "nullable": true,
            "example": "10000"
          },
          "unit": {
            "type": "string",
            "nullable": true,
            "example": "count"
          },
          "valueType": {
            "type": "string",
            "nullable": true,
            "example": "long"
          },
          "startDateTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2024-02-11T00:00:00.0000000+00:00"
          },
          "endDateTime": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "example": "2024-02-12T00:00:00.0000000+00:00"
          }
        },
        "additionalProperties": false
      },
      "ComparisonDataPointDto": {
        "type": "object",
        "properties": {
          "type": {
            "title": "Type",
            "type": "string",
            "description": "The type of comparison (e.g., 'demographic', 'global', 'baseline').",
            "example": "demographic"
          },
          "value": {
            "title": "Value",
            "type": "number",
            "description": "The reference value for this comparison type.",
            "format": "double",
            "example": "0.71"
          },
          "percentile": {
            "title": "Percentile",
            "type": "integer",
            "description": "The percentile ranking within the reference group, if applicable.",
            "format": "int32",
            "nullable": true,
            "example": "58"
          },
          "difference": {
            "title": "Difference",
            "type": "number",
            "description": "The absolute difference between the current value and this reference value.",
            "format": "double",
            "example": "0.04"
          },
          "percentageDifference": {
            "title": "PercentageDifference",
            "type": "number",
            "description": "The percentage difference between the current value and this reference value.",
            "format": "double",
            "example": "0.05"
          },
          "state": {
            "title": "State",
            "type": "string",
            "description": "A qualitative assessment of the comparison result (e.g., 'low', 'medium', 'high').",
            "nullable": true,
            "example": "medium"
          },
          "properties": {
            "title": "Properties",
            "type": "object",
            "additionalProperties": { },
            "description": "Additional properties specific to this comparison type."
          }
        },
        "additionalProperties": false
      },
      "ComparisonDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Unique identifier for the comparison.",
            "format": "uuid",
            "example": "2F9EA4F8-8A96-4AC2-88B5-001EE6FC2CCD"
          },
          "type": {
            "title": "Type",
            "type": "string",
            "description": "The type of the data structure, always 'comparison'.",
            "example": "comparison"
          },
          "category": {
            "title": "Category",
            "type": "string",
            "description": "The category of the comparison, such as 'score', 'factor', or 'biomarker'.",
            "example": "score"
          },
          "name": {
            "title": "Name",
            "type": "string",
            "description": "The name of the metric being compared.",
            "example": "readiness"
          },
          "value": {
            "title": "Value",
            "type": "number",
            "description": "The current value of the metric being compared.",
            "format": "double",
            "example": "0.75"
          },
          "unit": {
            "title": "Unit",
            "type": "string",
            "description": "The unit of measurement for the values.",
            "example": "index"
          },
          "isHigherBetter": {
            "title": "IsHigherBetter",
            "type": "boolean",
            "description": "Indicates if higher values are better for this comparison.",
            "nullable": true,
            "example": "true"
          },
          "startDateTime": {
            "title": "StartDateTime",
            "type": "string",
            "description": "The start datetime for the comparison period.",
            "format": "date-time",
            "example": "2025-04-02T00:00:00.0000000+00:00"
          },
          "endDateTime": {
            "title": "EndDateTime",
            "type": "string",
            "description": "The end datetime for the comparison period.",
            "format": "date-time",
            "example": "2025-04-02T23:59:59.0000000+00:00"
          },
          "periodicity": {
            "title": "Periodicity",
            "type": "string",
            "description": "The time period the comparison represents, e.g., 'daily', 'weekly'.",
            "example": "daily"
          },
          "data": {
            "title": "Data",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ComparisonDataPointDto"
            },
            "description": "The collection of comparison data points."
          },
          "createdAtUtc": {
            "title": "CreatedAtUtc",
            "type": "string",
            "description": "The UTC timestamp when this comparison was created.",
            "format": "date-time",
            "example": "2023-05-16T09:30:00.0000000+00:00"
          },
          "version": {
            "title": "Version",
            "type": "number",
            "description": "The version of the comparison algorithm used.",
            "format": "float",
            "example": "1.0"
          }
        },
        "additionalProperties": false
      },
      "DataLogDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "",
            "format": "uuid",
            "nullable": true,
            "example": ""
          },
          "parentId": {
            "title": "ParentId",
            "type": "string",
            "description": "",
            "format": "uuid",
            "nullable": true,
            "example": ""
          },
          "logType": {
            "title": "LogType",
            "type": "string",
            "description": "",
            "example": ""
          },
          "dataType": {
            "title": "DataType",
            "type": "string",
            "description": "",
            "example": ""
          },
          "value": {
            "title": "Value",
            "type": "number",
            "description": "The amount of times the data type occurred within the time period.",
            "format": "double",
            "example": "55"
          },
          "unit": {
            "title": "Unit",
            "type": "string",
            "description": "The unit of measure for the value.",
            "example": "55"
          },
          "source": {
            "title": "Source",
            "type": "string",
            "description": "Source of this data log. e.g. 'Iphone X', 'Walking Buddy'",
            "example": "Iphone X"
          },
          "sourceId": {
            "title": "SourceId",
            "type": "integer",
            "description": "Unique Source Identifier of this data log for the profile.",
            "format": "int32",
            "example": "Iphone X"
          },
          "recordingMethod": {
            "title": "RecordingMethod",
            "type": "string",
            "description": "The method used to record the log: RECORDING_METHOD_ACTIVELY_RECORDED (For actively recorded data by the user), RECORDING_METHOD_AUTOMATICALLY_RECORDED (For passively recorded data by the app), RECORDING_METHOD_MANUAL_ENTRY (For manually entered data by the user), RECORDING_METHOD_UNKNOWN (Unknown recording method).",
            "example": "RECORDING_METHOD_UNKNOWN"
          },
          "deviceId": {
            "title": "DeviceId",
            "type": "string",
            "description": "The identifier for the device which recorded the log.",
            "format": "uuid",
            "nullable": true,
            "example": "C85330AD-C691-453C-8CB6-353AB75FD611"
          },
          "deviceType": {
            "title": "DeviceType",
            "type": "string",
            "description": "The device which recorded the log.",
            "example": "iPhone13,2"
          },
          "periodicity": {
            "title": "Periodicity",
            "type": "string",
            "description": "If the log is an aggregate this determins it's periodicity - daily, hourly",
            "example": "daily"
          },
          "aggregation": {
            "title": "Aggregation",
            "type": "string",
            "description": "If the log is an aggregate this determines it's aggregation type - sum, avg, max, min",
            "example": "sum"
          },
          "startDateTime": {
            "title": "StartDateTime",
            "type": "string",
            "description": "Denotes the start date and time for the log period. In ISO 8601 format with a timezone offset.",
            "format": "date-time",
            "example": "2022-01-01T00:00:00.0000000+12:00"
          },
          "endDateTime": {
            "title": "EndDateTime",
            "type": "string",
            "description": "Denotes the end date and time for the log period. In ISO 8601 format with a timezone offset.",
            "format": "date-time",
            "example": "2022-01-01T00:00:00.0000000+12:00"
          },
          "additionalProperties": {
            "title": "",
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "",
            "example": ""
          }
        },
        "additionalProperties": false
      },
      "DataSourceDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sourceId": {
            "type": "integer",
            "format": "int32"
          },
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "sourceName": {
            "type": "string",
            "nullable": true
          },
          "deviceType": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "DemographicDto": {
        "type": "object",
        "properties": {
          "age": {
            "title": "Age",
            "type": "integer",
            "description": "Age of the user, must be 18 or more and 100 or less.",
            "format": "int32",
            "nullable": true,
            "example": "35"
          },
          "gender": {
            "title": "Gender",
            "type": "string",
            "description": "Gender of the user. Can be Male, Female or Gender Diverse.",
            "nullable": true,
            "example": "Male"
          },
          "birthDate": {
            "title": "BirthDate",
            "type": "string",
            "description": "Birth Date of the user. In ISO 8601 format.",
            "format": "date-time",
            "nullable": true,
            "example": "1990-01-01T00:00:00.0000000+00:00"
          }
        },
        "additionalProperties": false
      },
      "DeviceInformationDto": {
        "type": "object",
        "properties": {
          "sdkId": {
            "title": "SDKId",
            "type": "string",
            "description": "Sahha SDK identifier (based on customer integration). E.G. 'android_kotlin', 'ios_swift', 'react_native', 'flutter', 'capacitor', 'cordova'.",
            "example": "ios_swift"
          },
          "sdkVersion": {
            "title": "SDKVersion",
            "type": "string",
            "description": "Sahha SDK version string such as 3.4.1.",
            "example": "3.4.1"
          },
          "appId": {
            "title": "AppId",
            "type": "string",
            "description": "Sahha customer's App Bundle Id, e.g. com.sahha.app.",
            "example": "com.sahha.app"
          },
          "appVersion": {
            "title": "AppVersion",
            "type": "string",
            "description": "Sahha customer's App Version, e.g. 0.1.4",
            "nullable": true,
            "example": "0.1.4"
          },
          "deviceId": {
            "title": "DeviceId",
            "type": "string",
            "description": "The identifier for the device.",
            "format": "uuid",
            "nullable": true,
            "example": "C85330AD-C691-453C-8CB6-353AB75FD611"
          },
          "deviceType": {
            "title": "DeviceType",
            "type": "string",
            "description": "User device identifier such as 'Apple iPhone' or 'Samsung Galaxy'.",
            "example": "iPhone"
          },
          "deviceModel": {
            "title": "DeviceModel",
            "type": "string",
            "description": "User device model identifier such as 'iPhone X' or 'Galaxy S10'.",
            "example": "iPhone X"
          },
          "system": {
            "title": "System",
            "type": "string",
            "description": "User device platform such as 'iOS', 'iPadOS', 'Android'.",
            "example": "iOS"
          },
          "systemVersion": {
            "title": "SystemVersion",
            "type": "string",
            "description": "User device platform version such as '15.1' on iOS or '21' on Android.",
            "example": "15.1"
          },
          "timeZone": {
            "title": "TimeZone",
            "type": "string",
            "description": "Time Zone of the profile holder. +12:00 ",
            "nullable": true,
            "example": "+12:00"
          }
        },
        "additionalProperties": false
      },
      "ProfileDto": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "dataLastReceivedAtUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "isSampleProfile": {
            "type": "boolean"
          },
          "dataSources": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DataSourceDto"
            },
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ProfileSearchResultItem": {
        "type": "object",
        "properties": {
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "externalId": {
            "type": "string",
            "nullable": true
          },
          "sdkId": {
            "type": "string",
            "nullable": true
          },
          "sdkVersion": {
            "type": "string",
            "nullable": true
          },
          "deviceType": {
            "type": "string",
            "nullable": true
          },
          "dataLastReceivedAtUtc": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "createdAtUtc": {
            "type": "string",
            "format": "date-time"
          },
          "isSampleProfile": {
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "ProfileSearchResultItemPagedList": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProfileSearchResultItem"
            },
            "nullable": true
          },
          "currentPage": {
            "type": "integer",
            "format": "int32"
          },
          "totalPages": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "pageSize": {
            "type": "integer",
            "format": "int32"
          },
          "totalCount": {
            "type": "integer",
            "format": "int32",
            "readOnly": true
          },
          "hasPrevious": {
            "type": "boolean",
            "readOnly": true
          },
          "hasNext": {
            "type": "boolean",
            "readOnly": true
          }
        },
        "additionalProperties": false
      },
      "ProfileTokenResponse": {
        "type": "object",
        "properties": {
          "profileToken": {
            "title": "ProfileToken",
            "type": "string",
            "description": "Profile token used in authorization header as 'profile {token}'",
            "example": "hIw0LuHXHZKMD7bWV0DlGWyTAyHqO8EceLmJ5ez96QrXv3Lhf0qoDqrNDp7jx..."
          },
          "expiresIn": {
            "title": "ExpiresIn",
            "type": "integer",
            "description": "When the token expires, as Unix time in seconds.",
            "format": "int32",
            "example": "1798761600"
          },
          "tokenType": {
            "title": "TokenType",
            "type": "string",
            "description": "The type of token being returned, will be 'account' or 'profile'",
            "example": "Profile"
          },
          "refreshToken": {
            "title": "RefreshToken",
            "type": "string",
            "description": "Populated with a token value in response to a refresh token request.",
            "nullable": true,
            "example": "hIw0LuHXHZKMD7bWV0DlGWyTAyHqO8EceLmJ5ez96QrXv3Lhf0qoDqrNDp7jx..."
          }
        },
        "additionalProperties": false
      },
      "RefreshProfileTokenRequest": {
        "type": "object",
        "properties": {
          "refreshToken": {
            "title": "RefreshToken",
            "type": "string",
            "description": "Profile refresh token",
            "example": "hIw0LuHXHZKMD7bWV0DlGWyTAyHqO8EceL"
          }
        },
        "additionalProperties": false
      },
      "RegisterProfileRequest": {
        "type": "object",
        "properties": {
          "externalId": {
            "title": "ExternalId",
            "type": "string",
            "description": "ExternalId used to reference the created Profile",
            "example": "6980b34e-14f9-47ef-b6f8-80a18b206a8e"
          }
        },
        "additionalProperties": false
      },
      "RetrieveProfileTokenRequest": {
        "type": "object",
        "properties": {
          "externalId": {
            "type": "string",
            "nullable": true,
            "example": "C85330AD-C691-453C-8CB6-353AB75FD611"
          },
          "readOnly": {
            "type": "boolean",
            "nullable": true,
            "example": "false"
          },
          "lifetime": {
            "type": "integer",
            "format": "int32",
            "nullable": true,
            "example": "86400"
          }
        },
        "additionalProperties": false
      },
      "ScoreDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Unique identifier for the inference.",
            "format": "uuid",
            "example": "2F9EA4F8-8A96-4AC2-88B5-001EE6FC2CCD"
          },
          "type": {
            "title": "Type",
            "type": "string",
            "description": "Specifies the type of score being reported, such as stress_resilience or depression_resilience. The type informs the client about which aspect of health the inference relates to.",
            "example": "activity"
          },
          "state": {
            "title": "State",
            "type": "string",
            "description": "Indicates the category of the score in a descriptive manner. Categories include none, low, medium, or high. This field provides a qualitative summary of the corresponding score.",
            "example": "medium"
          },
          "score": {
            "title": "Score",
            "type": "number",
            "description": "The numerical value of the health score, ranging between 0 and 1. Higher scores typically indicate better mental and physical well-being based on the features analyzed.",
            "format": "float",
            "example": "0.88"
          },
          "factors": {
            "title": "Factors",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScoreFactorDto"
            },
            "description": "A list of objects that break down the score contributions of different features such as sleep_routine, daily_activity, etc. Each object in the list specifies how much a particular feature has contributed to the final score.",
            "example": "[{ \"name\": \"active_hours\",\"value\": 8, \"goal\": 10, \"score\" : 0.65, \"state\" : \"low\" }]"
          },
          "dataSources": {
            "title": "InputData",
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Lists the features that were used to generate the inference. This can include features like age, gender, sleep, and activity.",
            "example": "[\"age\",\"exercise\",\"activity\"]"
          },
          "scoreDateTime": {
            "title": "ScoreDateTime",
            "type": "string",
            "description": "Date and Time the score is for.",
            "format": "date-time",
            "example": "2023-01-01T00:00:00.0000000+00:00"
          },
          "createdAtUtc": {
            "title": "CreatedAt",
            "type": "string",
            "description": "Date the inference was generated.",
            "format": "date-time",
            "example": "2023-01-01T00:00:00.0000000+00:00"
          },
          "version": {
            "title": "Version",
            "type": "number",
            "description": "Version number for the inference.",
            "format": "float",
            "example": "1.0"
          }
        },
        "additionalProperties": false
      },
      "ScoreFactorDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "value": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "goal": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "score": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "state": {
            "type": "string",
            "nullable": true
          },
          "unit": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "TagDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Server-generated. Any value supplied is ignored.",
            "nullable": true,
            "readOnly": true
          },
          "type": {
            "title": "Type",
            "type": "string",
            "description": "Tag shape — `event` (a moment) or `state` (a duration).",
            "example": "state"
          },
          "startDateTime": {
            "title": "StartDateTime",
            "type": "string",
            "description": "When the tag begins. ISO 8601 string with a timezone offset. For an `event`, when it occurred.",
            "example": "2024-02-09T19:00:00+00:00"
          },
          "endDateTime": {
            "title": "EndDateTime",
            "type": "string",
            "description": "When a `state` tag ended. ISO 8601 string with a timezone offset. Must be null for `event` tags; null on a `state` tag means it is still ongoing.",
            "nullable": true,
            "example": "2024-02-10T07:00:00+00:00"
          },
          "name": {
            "title": "Name",
            "type": "string",
            "description": "What the tag represents (e.g. `night_shift`, `insulin_bolus`).",
            "example": "night_shift"
          },
          "category": {
            "title": "Category",
            "type": "string",
            "description": "Optional broader grouping for the tag (e.g. `work`, `medication`).",
            "nullable": true,
            "example": "work"
          },
          "value": {
            "title": "Value",
            "type": "string",
            "description": "Optional value attached to the tag (e.g. `12_hour`, `annual`, `6_units`).",
            "nullable": true,
            "example": "12_hour"
          },
          "source": {
            "title": "Source",
            "type": "string",
            "description": "Which of your systems produced the tag, typically a reverse-DNS string.",
            "example": "acme.workforce"
          },
          "additionalProperties": {
            "title": "AdditionalProperties",
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Extra key/value context, stored as-is alongside the tag.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Single tag entry uploaded to Sahha. A tag attaches your own data to a\r\nprofile (e.g. a night shift, a medication, a subscription plan).\r\nHealth and wearable data does NOT belong here — upload that via\r\n`POST /api/v1/profile/data/log`.\r\n            \r\nProfiles.TypeContracts.DataTransferObjects.Tags.TagDto.Type is one of:\r\n<list type=\"bullet\"><item><description>`event` — a moment in time. Profiles.TypeContracts.DataTransferObjects.Tags.TagDto.EndDateTime must be null.</description></item><item><description>`state` — a period of time. Set Profiles.TypeContracts.DataTransferObjects.Tags.TagDto.EndDateTime when it ends; leave it null while ongoing.</description></item></list>\r\nTimestamps are ISO 8601 strings with a timezone offset (e.g.\r\n`2024-02-09T19:00:00+00:00`)."
      },
      "TagResponseDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Server-generated identifier for the tag.",
            "format": "uuid",
            "example": "f3b1a8e0-4c5d-4e6f-9a8b-1c2d3e4f5a01"
          },
          "type": {
            "title": "Type",
            "type": "string",
            "description": "Tag shape — `event` (a moment) or `state` (a duration).",
            "example": "state"
          },
          "name": {
            "title": "Name",
            "type": "string",
            "description": "What the tag represents (e.g. `night_shift`, `insulin_bolus`).",
            "example": "night_shift"
          },
          "category": {
            "title": "Category",
            "type": "string",
            "description": "Optional broader grouping (e.g. `work`, `medication`).",
            "nullable": true,
            "example": "work"
          },
          "value": {
            "title": "Value",
            "type": "string",
            "description": "Optional value attached to the tag (e.g. `12_hour`, `annual`, `6_units`).",
            "nullable": true,
            "example": "12_hour"
          },
          "source": {
            "title": "Source",
            "type": "string",
            "description": "Which of your systems produced the tag, typically a reverse-DNS string.",
            "example": "acme.workforce"
          },
          "startDateTime": {
            "title": "StartDateTime",
            "type": "string",
            "description": "When the tag begins, returned with the same timezone offset that was supplied at upload. For an `event`, when it occurred.",
            "format": "date-time",
            "example": "2024-02-09T19:00:00.0000000+00:00"
          },
          "endDateTime": {
            "title": "EndDateTime",
            "type": "string",
            "description": "When a `state` tag ended, returned with the same timezone offset that was supplied at upload. Null for `event` tags; null on a `state` tag means it is still ongoing.",
            "format": "date-time",
            "nullable": true,
            "example": "2024-02-10T07:00:00.0000000+00:00"
          },
          "receivedAtUtc": {
            "title": "ReceivedAtUtc",
            "type": "string",
            "description": "When the server received the tag, in UTC.",
            "format": "date-time",
            "example": "2024-02-10T07:05:02.0000000+00:00"
          },
          "additionalProperties": {
            "title": "AdditionalProperties",
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Extra key/value context, returned exactly as supplied at upload.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "Single tag as returned by the `GET /api/v1/profile/tag` endpoints.\r\nProfiles.TypeContracts.DataTransferObjects.Tags.TagResponseDto.StartDateTime and Profiles.TypeContracts.DataTransferObjects.Tags.TagResponseDto.EndDateTime preserve the\r\ntimezone offset that was supplied at upload; Profiles.TypeContracts.DataTransferObjects.Tags.TagResponseDto.ReceivedAtUtc\r\nis UTC."
      },
      "TagUploadResponseDto": {
        "type": "object",
        "properties": {
          "ids": {
            "title": "Ids",
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Server-derived ids, positional with the request. `null` at any rejected index."
          },
          "warnings": {
            "title": "Warnings",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TagUploadWarningDto"
            },
            "description": "Per-tag rejections. Omitted when empty.",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "description": "200 OK body for `POST /api/v1/profile/tag`. Profiles.TypeContracts.DataTransferObjects.Tags.TagUploadResponseDto.Ids is\r\npositional with the request — `null` at any index whose tag was\r\nrejected, with the reason in Profiles.TypeContracts.DataTransferObjects.Tags.TagUploadResponseDto.Warnings. A tag is only\r\nrejected when its name is in Sahha's\r\n[reserved tag schema](https://docs.sahha.ai/docs/products/tags#list-of-tags-reserved)\r\nand its `Type`, `Category`, or `Value` does not match\r\nthat schema."
      },
      "TagUploadWarningDto": {
        "type": "object",
        "properties": {
          "index": {
            "title": "Index",
            "type": "integer",
            "description": "Zero-based index of the rejected tag in the original request array.",
            "format": "int32",
            "example": "1"
          },
          "name": {
            "title": "Name",
            "type": "string",
            "description": "The reserved tag name that triggered the rejection.",
            "example": "fever"
          },
          "code": {
            "title": "Code",
            "type": "string",
            "description": "Machine-readable rejection code, stable across releases.",
            "example": "reserved_tag_invalid_value"
          },
          "message": {
            "title": "Message",
            "type": "string",
            "description": "Human-readable explanation of the rejection.",
            "example": "Reserved tag 'fever' must have value in [unknown, not_present, mild, moderate, severe]; received 'extreme'."
          }
        },
        "additionalProperties": false,
        "description": "One per-tag rejection on a `POST /api/v1/profile/tag` batch. A tag is\r\nonly ever rejected when its Profiles.TypeContracts.DataTransferObjects.Tags.TagDto.Name is in Sahha's reserved\r\nnamespace but its `Type`, `Category` or `Value` does not match\r\nthe reserved schema. Custom (non-reserved) tags are never rejected by this\r\nvalidator."
      },
      "TrendDataPointDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Unique identifier for the trend data point.",
            "format": "uuid",
            "example": "2F9EA4F8-8A96-4AC2-88B5-001EE6FC2CCD"
          },
          "startDateTime": {
            "title": "StartDateTime",
            "type": "string",
            "description": "The start date and time of the period this data point represents.",
            "format": "date-time",
            "example": "2023-05-01T00:00:00.0000000+05:00"
          },
          "endDateTime": {
            "title": "EndDateTime",
            "type": "string",
            "description": "The end date and time of the period this data point represents.",
            "format": "date-time",
            "example": "2023-05-08T00:00:00.0000000+05:00"
          },
          "value": {
            "title": "Value",
            "type": "number",
            "description": "The measured or calculated value for this time period.",
            "format": "double",
            "example": "0.65"
          },
          "percentChangeFromPrevious": {
            "title": "PercentChangeFromPrevious",
            "type": "number",
            "description": "The percentage change from the previous period's value, expressed as a decimal (e.g., 0.05 = 5% increase).",
            "format": "double",
            "nullable": true,
            "example": "-0.07"
          }
        },
        "additionalProperties": false
      },
      "TrendDto": {
        "type": "object",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string",
            "description": "Unique identifier for the trend.",
            "format": "uuid",
            "example": "2F9EA4F8-8A96-4AC2-88B5-001EE6FC2CCD"
          },
          "type": {
            "title": "Type",
            "type": "string",
            "description": "The type of the data structure, always 'trend'.",
            "example": "trend"
          },
          "category": {
            "title": "Category",
            "type": "string",
            "description": "The category of the trend, such as 'score', 'factor', or 'biomarker'.",
            "example": "score"
          },
          "name": {
            "title": "Name",
            "type": "string",
            "description": "The name of the metric being trended.",
            "example": "sleep"
          },
          "state": {
            "title": "State",
            "type": "string",
            "description": "The direction of the trend: 'increasing', 'decreasing', or 'stable'.",
            "example": "increasing"
          },
          "isHigherBetter": {
            "title": "IsHigherBetter",
            "type": "boolean",
            "description": "Indicates whether higher values are better for this metric.",
            "nullable": true,
            "example": "true"
          },
          "valueRange": {
            "title": "ValueRange",
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            },
            "description": "The minimum and maximum values in the data set, as [min, max].",
            "example": "[0.0,1.0]"
          },
          "unit": {
            "title": "Unit",
            "type": "string",
            "description": "The unit of measurement for the values.",
            "example": "index"
          },
          "periodicity": {
            "title": "Periodicity",
            "type": "string",
            "description": "The time period each data point represents, typically 'weekly'.",
            "example": "weekly"
          },
          "trendStartDateTime": {
            "title": "TrendStartDateTime",
            "type": "string",
            "description": "The start datetime for the entire trend period.",
            "format": "date-time",
            "example": "2023-05-01T00:00:00.0000000+05:00"
          },
          "trendEndDateTime": {
            "title": "TrendEndDateTime",
            "type": "string",
            "description": "The end datetime for the entire trend period.",
            "format": "date-time",
            "example": "2023-05-29T00:00:00.0000000+05:00"
          },
          "data": {
            "title": "Data",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TrendDataPointDto"
            },
            "description": "The collection of data points that make up the trend."
          },
          "createdAtUtc": {
            "title": "CreatedAtUtc",
            "type": "string",
            "description": "The UTC timestamp when this trend was created.",
            "format": "date-time",
            "example": "2023-05-16T09:30:00.0000000+00:00"
          },
          "version": {
            "title": "Version",
            "type": "number",
            "description": "The version of the trend algorithm used.",
            "format": "float",
            "example": "1.0"
          }
        },
        "additionalProperties": false
      },
      "ConnectionStatus": {
        "enum": [
          "connected",
          "expired",
          "revoked"
        ],
        "type": "string",
        "description": "`connected` — usable. `expired` — the stored refresh token stopped working. `revoked` — the provider reported the user withdrew access. Both of the latter are recoverable by authorising again, which revives the same connection."
      },
      "ProfileIntegration": {
        "required": [
          "providerKey",
          "providerName",
          "icon",
          "connectionStatus",
          "connectionId"
        ],
        "type": "object",
        "properties": {
          "providerKey": {
            "type": "string",
            "example": "whoop"
          },
          "providerName": {
            "type": "string",
            "example": "WHOOP"
          },
          "icon": {
            "type": "string",
            "description": "Brand mark as an `image/svg+xml` base64 data URI, ready for an `<img src>`. Empty when the provider has no icon.",
            "example": "data:image/svg+xml;base64,PHN2Zy4uLg=="
          },
          "connectionStatus": {
            "enum": [
              "none",
              "connected",
              "expired",
              "revoked"
            ],
            "type": "string",
            "description": "`none` means this profile has no connection to this integration; the rest mirror ConnectionStatus."
          },
          "connectionId": {
            "type": "string",
            "description": "The connection to pass to DELETE /api/v1/integration/profile/connection/{connectionId}. Null exactly when connectionStatus is `none`.",
            "format": "uuid",
            "nullable": true
          }
        },
        "description": "An integration on the caller's account, annotated with this profile's connection state. Carries no credentials."
      },
      "Connection": {
        "required": [
          "id",
          "integrationId",
          "accountId",
          "profileId",
          "providerKey",
          "providerUserId",
          "externalId",
          "status",
          "createdAtUtc",
          "updatedAtUtc"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "integrationId": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "profileId": {
            "type": "string",
            "format": "uuid"
          },
          "providerKey": {
            "type": "string",
            "example": "oura"
          },
          "providerUserId": {
            "type": "string",
            "description": "The user's id at the provider."
          },
          "externalId": {
            "type": "string",
            "description": "The profile's external id in Sahha."
          },
          "status": {
            "$ref": "#/components/schemas/ConnectionStatus"
          },
          "createdAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          },
          "updatedAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          }
        }
      },
      "PagedConnectionList": {
        "required": [
          "items",
          "currentPage",
          "totalPages",
          "pageSize",
          "totalCount",
          "hasPrevious",
          "hasNext"
        ],
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Connection"
            }
          },
          "currentPage": {
            "type": "integer",
            "example": 1
          },
          "totalPages": {
            "type": "integer",
            "example": 3
          },
          "pageSize": {
            "type": "integer",
            "example": 20
          },
          "totalCount": {
            "type": "integer",
            "example": 47
          },
          "hasPrevious": {
            "type": "boolean"
          },
          "hasNext": {
            "type": "boolean"
          }
        }
      },
      "Integration": {
        "required": [
          "id",
          "accountId",
          "providerKey",
          "providerName",
          "availableScopes",
          "clientId",
          "scopes",
          "redirectWhitelist",
          "webhookAutoRegistered",
          "connectionCount",
          "createdAtUtc",
          "updatedAtUtc",
          "clientSecret",
          "webhookUrl"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "providerKey": {
            "type": "string",
            "example": "whoop"
          },
          "providerName": {
            "type": "string",
            "description": "Display name from the provider catalogue. Falls back to the raw providerKey if this build does not know the provider.",
            "example": "WHOOP"
          },
          "availableScopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every scope the provider supports. Empty if the provider is unknown to this build."
          },
          "clientId": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Scopes this integration requests."
          },
          "redirectWhitelist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Redirect URLs the authorize endpoint will accept, matched exactly. Custom schemes are allowed; fragments are not."
          },
          "webhookAutoRegistered": {
            "type": "boolean",
            "description": "True when the provider is subscribed programmatically rather than by configuring the webhook URL in its dashboard."
          },
          "connectionCount": {
            "type": "integer"
          },
          "createdAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          },
          "updatedAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          },
          "clientSecret": {
            "type": "string",
            "description": "Decrypted OAuth client secret."
          },
          "webhookUrl": {
            "type": "string",
            "description": "Endpoint to register with the provider. Embeds this integration's webhook token, which is the only credential on that endpoint.",
            "example": "https://api.sahha.ai/api/v1/integration/webhook/<token>"
          }
        },
        "description": "Full integration, including credentials. Returned only by the single-integration create and fetch."
      },
      "IntegrationListItem": {
        "required": [
          "id",
          "accountId",
          "providerKey",
          "providerName",
          "availableScopes",
          "clientId",
          "scopes",
          "redirectWhitelist",
          "webhookAutoRegistered",
          "connectionCount",
          "createdAtUtc",
          "updatedAtUtc"
        ],
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "accountId": {
            "type": "string",
            "format": "uuid"
          },
          "providerKey": {
            "type": "string",
            "example": "whoop"
          },
          "providerName": {
            "type": "string",
            "description": "Display name from the provider catalogue. Falls back to the raw providerKey if this build does not know the provider.",
            "example": "WHOOP"
          },
          "availableScopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Every scope the provider supports. Empty if the provider is unknown to this build."
          },
          "clientId": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Scopes this integration requests."
          },
          "redirectWhitelist": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Redirect URLs the authorize endpoint will accept, matched exactly. Custom schemes are allowed; fragments are not."
          },
          "webhookAutoRegistered": {
            "type": "boolean",
            "description": "True when the provider is subscribed programmatically rather than by configuring the webhook URL in its dashboard."
          },
          "connectionCount": {
            "type": "integer"
          },
          "createdAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          },
          "updatedAtUtc": {
            "type": "string",
            "description": "RFC 3339, UTC.",
            "format": "date-time"
          }
        },
        "description": "List view. Deliberately omits clientSecret and webhookUrl: both are live credentials, and the list returns one of each per row."
      },
      "CreateIntegrationRequest": {
        "required": [
          "providerKey",
          "clientId",
          "clientSecret",
          "redirectWhitelist"
        ],
        "type": "object",
        "properties": {
          "providerKey": {
            "type": "string",
            "description": "Must be a key from the provider catalogue.",
            "example": "whoop"
          },
          "clientId": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string",
            "description": "Rejected if empty."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "redirectWhitelist": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "At least one URL. Each needs a scheme, a host for http(s), and no fragment."
          },
          "webhookToken": {
            "type": "string",
            "description": "Optional. The webhookToken the setup endpoint answered with. If it is no longer the token this integration would get, the create is refused with a 409 rather than storing a webhook URL other than the one registered with the provider. Omit it to take whichever token is current."
          }
        }
      },
      "UpdateIntegrationRequest": {
        "type": "object",
        "properties": {
          "clientSecret": {
            "type": "string",
            "description": "Omit or send null to leave the stored secret alone. An empty string is rejected rather than treated as unchanged.",
            "nullable": true
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "redirectWhitelist": {
            "minItems": 1,
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": "Partial update. providerKey and clientId cannot be changed."
      },
      "IntegrationSetup": {
        "required": [
          "providerKey",
          "providerName",
          "webhookAutoRegistered",
          "webhookUrl",
          "webhookToken"
        ],
        "type": "object",
        "properties": {
          "providerKey": {
            "type": "string",
            "example": "whoop"
          },
          "providerName": {
            "type": "string",
            "description": "Display name from the provider catalogue.",
            "example": "WHOOP"
          },
          "webhookAutoRegistered": {
            "type": "boolean",
            "description": "True when the provider is subscribed programmatically rather than by configuring the webhook URL in its dashboard."
          },
          "webhookUrl": {
            "type": "string",
            "description": "Endpoint the integration will receive webhooks on once it is created. Embeds webhookToken, which is the only credential on that endpoint.",
            "example": "https://api.sahha.ai/api/v1/integration/webhook/<token>"
          },
          "webhookToken": {
            "type": "string",
            "description": "The token in webhookUrl. Send it back as webhookToken when creating the integration."
          }
        },
        "description": "What a provider has to be given before an integration for it exists."
      },
      "Provider": {
        "required": [
          "key",
          "name",
          "availableScopes",
          "oauthCallbackUrl",
          "webhookAutoRegistered"
        ],
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "example": "whoop"
          },
          "name": {
            "type": "string",
            "example": "WHOOP"
          },
          "availableScopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "oauthCallbackUrl": {
            "type": "string",
            "description": "Redirect URL to register with the provider for the OAuth flow. The same for every account.",
            "example": "https://api.sahha.ai/api/v1/integration/oauth/whoop/callback"
          },
          "webhookAutoRegistered": {
            "type": "boolean",
            "description": "True when the provider is subscribed programmatically rather than by configuring the webhook URL in its dashboard."
          }
        }
      },
      "AuthorizeResponse": {
        "required": [
          "authorizationUrl"
        ],
        "type": "object",
        "properties": {
          "authorizationUrl": {
            "type": "string",
            "description": "Provider consent URL, carrying state and a PKCE challenge. Open it in a system browser session."
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Malformed path parameter, query filter, or request body.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed, or invalid token, or the wrong token scheme for this surface.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The user token does not grant access to the account in the path.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource, or none visible to this caller.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "Conflict": {
        "description": "The resource already exists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A dependency could not be reached, so the request could not be decided. Worth retrying.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected failure.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "Token": {
        "type": "apiKey",
        "description": "Sahha uses token-based authentication. Your account is provisioned with a Sandbox and Production <b>ClientId</b> and <b>ClientSecret</b> — exchange these for an access token via the <b>Get Account Token</b> endpoint below, then include the token in the <code>Authorization</code> header on subsequent requests.<br><br>Account tokens (used by integrators to create and manage profiles) are sent as <b>'account {token}'</b>. Profile tokens (used by SDKs on end-user devices) are sent as <b>'profile {token}'</b>.",
        "name": "Authorization",
        "in": "header"
      }
    }
  },
  "security": [
    {
      "Token": [ ]
    }
  ]
}