Forzelite Developers

API reference

The Forzelite Partner API is documented as an OpenAPI 3.1 spec. Copy the YAML below into Postman, ReDoc, or your preferred generator. The live runtime spec is also available at /openapi.json on every API host.

Download openapi.yaml
# Forzelite Partner API
# OpenAPI 3.1 spec for /api/v2/external/*
# Export this file and import it into Postman or your generator of choice.

openapi: 3.1.0
info:
  title: Forzelite Partner API
  version: "2.0"
  description: |
    OAuth 2.0 client_credentials surface for third-party integrations
    against Forzelite tenant data.

servers:
  - url: https://api.forzelite.com
    description: Production
  - url: http://localhost:8000
    description: Local development

paths:
  /api/v2/external/oauth/token:
    post:
      summary: Issue an access token (client_credentials grant)
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              required: [grant_type, client_id, client_secret]
              properties:
                grant_type:
                  type: string
                  enum: [client_credentials]
                client_id: { type: string }
                client_secret: { type: string }
                scope: { type: string }
      responses:
        "200":
          description: Token issued
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        "401": { description: invalid_client }
        "400": { description: unsupported_grant_type }

  /api/v2/external/whoami:
    get:
      summary: Token introspection helper
      security: [{ bearerAuth: [] }]
      responses:
        "200":
          description: caller identity
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WhoAmIResponse"

  /api/v2/external/athletes/{athlete_id}:
    get:
      summary: Read a consented athlete profile
      security: [{ bearerAuth: ["athletes:read"] }]
      parameters:
        - in: path
          name: athlete_id
          required: true
          schema: { type: string, format: uuid }
      responses:
        "200":
          description: athlete profile
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AthleteProfile"
        "404": { description: not found or not consented }

  /api/v2/external/insights:
    post:
      summary: Submit a third-party insight card
      security: [{ bearerAuth: ["insights:write"] }]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/InsightSubmit"
      responses:
        "201":
          description: card created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InsightResult"

  /api/v2/external/usage:
    get:
      summary: Read this application's recent usage
      security: [{ bearerAuth: ["usage:read"] }]
      responses:
        "200":
          description: usage entries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UsageDashboard"

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: HMAC-SHA256
  schemas:
    TokenResponse:
      type: object
      properties:
        access_token: { type: string }
        token_type:   { type: string }
        expires_in:   { type: integer }
        scope:        { type: string }
    WhoAmIResponse:
      type: object
      properties:
        client_id:  { type: string }
        tenant_id:  { type: string, format: uuid }
        scopes:
          type: array
          items: { type: string }
        expires_at: { type: string, format: date-time }
    AthleteProfile:
      type: object
      properties:
        athlete_user_id: { type: string, format: uuid }
        tenant_id:       { type: string, format: uuid }
        primary_sport:   { type: string }
        graduation_year: { type: integer, nullable: true }
        height_cm:       { type: number,  nullable: true }
        weight_kg:       { type: number,  nullable: true }
        school_name:     { type: string,  nullable: true }
        is_consented:    { type: boolean }
    InsightSubmit:
      type: object
      required: [athlete_user_id, title, body]
      properties:
        athlete_user_id: { type: string, format: uuid }
        title:           { type: string }
        body:            { type: string }
        category:        { type: string }
        cta_label:       { type: string, nullable: true }
        cta_action:      { type: object, nullable: true }
    InsightResult:
      type: object
      properties:
        id:         { type: string, format: uuid }
        accepted:   { type: boolean }
        created_at: { type: string, format: date-time }
    UsageDashboard:
      type: object
      properties:
        client_id:   { type: string }
        total_calls: { type: integer }
        items:
          type: array
          items:
            $ref: "#/components/schemas/UsageEntry"
    UsageEntry:
      type: object
      properties:
        id:              { type: string, format: uuid }
        request_method:  { type: string }
        request_path:    { type: string }
        response_status: { type: integer }
        duration_ms:     { type: integer }
        created_at:      { type: string, format: date-time }