{
  "openapi": "3.1.0",
  "info": {
    "title": "WealthGlider Agent API",
    "version": "1.0.0",
    "summary": "Versioned API for WealthGlider's daily recommendations and aggregate target-hit research.",
    "description": "Responses are impersonal educational research, not personalized financial advice or trade instructions. Historical recommendation retrieval remains limited to one exact date or immutable edition per request; aggregate performance responses contain summary statistics rather than raw recommendation archives.",
    "termsOfService": "https://www.wealthglider.com/terms",
    "contact": {
      "name": "WealthGlider Support",
      "email": "support@wealthglider.com"
    }
  },
  "x-wealthglider-release-status": "general-availability",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "servers": [
    {
      "url": "https://api.wealthglider.com",
      "description": "Production WealthGlider Agent API."
    }
  ],
  "tags": [
    { "name": "Samples", "description": "Fictional public records that demonstrate the contract without exposing live premium data." },
    { "name": "Editions", "description": "Published daily recommendation editions and individual signal records." },
    { "name": "Performance", "description": "Aggregate historical target-hit research statistics without raw recommendation archives." },
    { "name": "Account", "description": "Entitlement and usage information for an API consumer." },
    { "name": "Credentials", "description": "Firebase-authenticated browser control plane for named personal access tokens." }
  ],
  "paths": {
    "/v1/samples/latest": {
      "get": {
        "tags": ["Samples"],
        "operationId": "getLatestSample",
        "summary": "Get a fictional public recommendation sample",
        "description": "Returns an explicitly marked sample record so agents can demonstrate the response shape without authentication or access to a live recommendation edition.",
        "parameters": [
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Fictional sample data. This is never a live recommendation edition.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/recommendation-set-v1.json" },
                "examples": {
                  "fictionalSample": { "externalValue": "./examples/recommendation-set.sample.json" }
                }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "429": { "$ref": "#/components/responses/PublicRateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/v1/editions/latest": {
      "get": {
        "tags": ["Editions"],
        "operationId": "getLatestEdition",
        "summary": "Get the latest entitled recommendation edition",
        "description": "Returns exactly one latest published market-day edition. This operation accepts no date, range, pagination, or filtering parameters.",
        "x-required-scopes": ["daily_recommendations:read"],
        "parameters": [
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Latest edition and the recommendation rows available to the caller's entitlement.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/recommendation-set-v1.json" },
                "examples": {
                  "sampleShape": { "externalValue": "./examples/recommendation-set.sample.json" }
                }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/v1/editions/by-date/{edition_date}": {
      "get": {
        "tags": ["Editions"],
        "operationId": "getEditionByDate",
        "summary": "Get one exact historical market date",
        "description": "Returns only the newest immutable revision for the requested date. Ranges, multiple dates, cursors, limits, and filters are not accepted.",
        "x-required-scopes": ["historical_recommendations:read"],
        "parameters": [
          { "$ref": "#/components/parameters/EditionDate" },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "One recommendation edition for exactly the requested date.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/recommendation-set-v1.json" }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/editions/{edition_id}": {
      "get": {
        "tags": ["Editions"],
        "operationId": "getEdition",
        "summary": "Get one immutable edition revision",
        "x-required-scopes": ["historical_recommendations:read"],
        "parameters": [
          { "$ref": "#/components/parameters/EditionId" },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "The requested edition revision and entitled signal rows.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/recommendation-set-v1.json" }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/editions/{edition_id}/signals/{symbol}": {
      "get": {
        "tags": ["Editions"],
        "operationId": "getEditionSignal",
        "summary": "Get one signal from an immutable edition revision",
        "x-required-scopes": ["historical_recommendations:read"],
        "parameters": [
          { "$ref": "#/components/parameters/EditionId" },
          { "$ref": "#/components/parameters/Symbol" },
          {
            "name": "classification",
            "in": "query",
            "required": false,
            "description": "Select buy or sell when an edition contains both classifications for the symbol. Omit only when the symbol has one signal in the edition.",
            "schema": { "type": "string", "enum": ["buy", "sell"] }
          },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "One published signal available to the caller's entitlement.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/signal-response-v1.json" },
                "examples": { "sampleShape": { "externalValue": "./examples/signal-response.sample.json" } }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/performance/target-hit-rate": {
      "get": {
        "tags": ["Performance"],
        "operationId": "getTargetHitRate",
        "summary": "Get aggregate historical target-hit statistics",
        "description": "Returns aggregate threshold-touch counts, rates, and a daily aggregate series for published recommendations. Date and classification filters select the statistical window only; this operation never returns raw recommendations, archive pagination, or symbol history. One successful response consumes one account-wide monthly data allowance unit.",
        "x-required-scopes": ["historical_recommendations:read"],
        "parameters": [
          { "$ref": "#/components/parameters/FromDate" },
          { "$ref": "#/components/parameters/ToDate" },
          {
            "name": "classification",
            "in": "query",
            "required": false,
            "description": "Optional comma-separated subset of buy and sell classifications.",
            "schema": { "type": "array", "items": { "type": "string", "enum": ["buy", "sell"] }, "uniqueItems": true },
            "style": "form",
            "explode": false
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Optional comma-separated category names used only to filter aggregate statistics.",
            "schema": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 100 }, "uniqueItems": true },
            "style": "form",
            "explode": false
          },
          { "$ref": "#/components/parameters/IfNoneMatch" }
        ],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Aggregate target-hit statistics with explicit numerator, denominator, horizon, filters, and methodology version.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "ETag": { "$ref": "#/components/headers/ETag" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/target-hit-statistics-v1.json" },
                "examples": { "default": { "externalValue": "./examples/target-hit-statistics.json" } }
              }
            }
          },
          "304": { "$ref": "#/components/responses/NotModified" },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "503": { "$ref": "#/components/responses/Unavailable" }
        }
      }
    },
    "/v1/account/usage": {
      "get": {
        "tags": ["Account"],
        "operationId": "getAccountUsage",
        "summary": "Get current API entitlement and request usage",
        "description": "Returns account-wide calendar-month usage across every credential. This operation does not consume the monthly edition allowance.",
        "x-required-scopes": ["account:read"],
        "security": [
          { "PersonalAccessToken": [] },
          { "FirebaseBearer": [] }
        ],
        "responses": {
          "200": {
            "description": "Current access level and request quota period without consuming an edition response.",
            "headers": {
              "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
              "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
              "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
              "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
              "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/account-usage-v1.json" },
                "examples": { "default": { "externalValue": "./examples/account-usage.json" } }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/credentials": {
      "get": {
        "tags": ["Credentials"],
        "operationId": "listCredentials",
        "summary": "List named credentials without secrets",
        "security": [{ "FirebaseBearer": [] }],
        "responses": {
          "200": {
            "description": "Credential metadata. Previously returned secrets are never included.",
            "headers": { "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/credential-v1.json#/$defs/ListResponse" },
                "examples": { "default": { "externalValue": "./examples/credential-list.json" } }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      },
      "post": {
        "tags": ["Credentials"],
        "operationId": "createCredential",
        "summary": "Create a named scoped personal access token",
        "description": "Returns the raw secret once. The caller must store it securely; later list responses contain metadata only.",
        "security": [{ "FirebaseBearer": [] }],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "./schemas/credential-v1.json#/$defs/CreateRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Credential created and raw secret returned once.",
            "headers": { "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "./schemas/credential-v1.json#/$defs/CreatedResponse" },
                "examples": { "default": { "externalValue": "./examples/credential-created.json" } }
              }
            }
          },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "409": { "$ref": "#/components/responses/Conflict" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/credentials/{credential_id}": {
      "delete": {
        "tags": ["Credentials"],
        "operationId": "revokeCredential",
        "summary": "Revoke one credential",
        "parameters": [
          {
            "name": "credential_id",
            "in": "path",
            "required": true,
            "schema": { "type": "string", "pattern": "^cred_[A-Za-z0-9_-]{16,128}$" }
          }
        ],
        "security": [{ "FirebaseBearer": [] }],
        "responses": {
          "204": {
            "description": "Credential revoked. Repeating the request is harmless.",
            "headers": { "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } }
          },
          "400": { "$ref": "#/components/responses/InvalidRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PersonalAccessToken": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "WealthGlider personal access token",
        "description": "Named scoped credential for server-to-server and agent access."
      },
      "FirebaseBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Firebase ID token",
        "description": "Browser control-plane authentication and compatibility data access during migration."
      }
    },
    "parameters": {
      "EditionId": {
        "name": "edition_id",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}\\.r[1-9][0-9]*$" }
      },
      "EditionDate": {
        "name": "edition_date",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "format": "date" },
        "description": "Exactly one market date in YYYY-MM-DD format. Date ranges and multiple dates are not supported."
      },
      "Symbol": {
        "name": "symbol",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "pattern": "^[A-Z0-9.\\-]{1,20}$" }
      },
      "FromDate": {
        "name": "from",
        "in": "query",
        "required": false,
        "schema": { "type": "string", "format": "date" },
        "description": "Inclusive first recommendation date in the aggregate statistics window."
      },
      "ToDate": {
        "name": "to",
        "in": "query",
        "required": false,
        "schema": { "type": "string", "format": "date" },
        "description": "Inclusive last recommendation date in the aggregate statistics window."
      },
      "IfNoneMatch": {
        "name": "If-None-Match",
        "in": "header",
        "required": false,
        "schema": { "type": "string" },
        "description": "Return 304 when the selected representation still matches this entity tag."
      }
    },
    "headers": {
      "XRequestId": {
        "description": "Opaque support and audit identifier for this request.",
        "schema": { "type": "string", "minLength": 8, "maxLength": 128 }
      },
      "ETag": {
        "description": "Entity tag for conditional retrieval.",
        "schema": { "type": "string" }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying when a useful delay is known.",
        "schema": { "type": "integer", "minimum": 1 }
      },
      "XRateLimitLimit": {
        "description": "Successful authenticated recommendation-data responses allowed per account per calendar month.",
        "schema": { "type": "integer", "const": 50 }
      },
      "XRateLimitRemaining": {
        "description": "Successful authenticated recommendation-data responses remaining for the account in the current calendar month.",
        "schema": { "type": "integer", "minimum": 0, "maximum": 50 }
      },
      "XRateLimitReset": {
        "description": "UTC Unix timestamp for the next calendar-month reset.",
        "schema": { "type": "integer", "minimum": 1 }
      },
      "XRateLimitWarning": {
        "description": "Present with value approaching_limit after 40 successful authenticated recommendation-data responses.",
        "schema": { "type": "string", "const": "approaching_limit" }
      }
    },
    "responses": {
      "NotModified": {
        "description": "Representation has not changed. A 304 does not consume the monthly recommendation-data allowance.",
        "headers": {
          "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
          "ETag": { "$ref": "#/components/headers/ETag" },
          "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
          "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
          "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
          "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
        }
      },
      "InvalidRequest": {
        "$ref": "#/components/responses/ProblemResponse"
      },
      "Unauthorized": {
        "$ref": "#/components/responses/ProblemResponse"
      },
      "Forbidden": {
        "description": "The authenticated caller lacks the required entitlement or credential scope. Resolution metadata gives an agent approved language and human-controlled next steps.",
        "headers": { "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "./schemas/common-v1.json#/$defs/Problem" },
            "examples": {
              "premiumRequired": { "externalValue": "./examples/problem-premium-required.json" },
              "trialExpired": { "externalValue": "./examples/problem-trial-expired.json" },
              "scopeRequired": { "externalValue": "./examples/problem-scope-required.json" }
            }
          }
        }
      },
      "NotFound": {
        "$ref": "#/components/responses/ProblemResponse"
      },
      "Conflict": {
        "$ref": "#/components/responses/ProblemResponse"
      },
      "PublicRateLimited": {
        "description": "The unauthenticated public sample rate limit was exceeded.",
        "headers": {
          "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
          "Retry-After": { "$ref": "#/components/headers/RetryAfter" }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "./schemas/common-v1.json#/$defs/Problem" }
          }
        }
      },
      "RateLimited": {
        "description": "The account exceeded its 50 successful recommendation-data responses per month or five authenticated requests per minute.",
        "headers": {
          "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
          "Retry-After": { "$ref": "#/components/headers/RetryAfter" },
          "X-RateLimit-Limit": { "$ref": "#/components/headers/XRateLimitLimit" },
          "X-RateLimit-Remaining": { "$ref": "#/components/headers/XRateLimitRemaining" },
          "X-RateLimit-Reset": { "$ref": "#/components/headers/XRateLimitReset" },
          "X-RateLimit-Warning": { "$ref": "#/components/headers/XRateLimitWarning" }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "./schemas/common-v1.json#/$defs/Problem" },
            "examples": { "quotaExceeded": { "externalValue": "./examples/problem-quota-exceeded.json" } }
          }
        }
      },
      "Unavailable": {
        "description": "The requested resource is temporarily unavailable.",
        "headers": {
          "X-Request-Id": { "$ref": "#/components/headers/XRequestId" },
          "Retry-After": { "$ref": "#/components/headers/RetryAfter" }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "./schemas/common-v1.json#/$defs/Problem" }
          }
        }
      },
      "ProblemResponse": {
        "description": "Machine-readable HTTP problem.",
        "headers": { "X-Request-Id": { "$ref": "#/components/headers/XRequestId" } },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "./schemas/common-v1.json#/$defs/Problem" },
            "examples": { "default": { "externalValue": "./examples/problem.json" } }
          }
        }
      }
    }
  }
}
