openapi: 3.0.3
info:
  title: GateKeeper SDK Integration API v1
  version: 1.0.0
  description: |
    Public integrator API.
    Integrators do not send client secrets on public SDK runtime requests.
    POST /authorize requires X-GK-Tenant-ID, Authorization Bearer, and JSON body (method, path).
    Rate limits apply per minute and per hour (429 with Retry-After when exceeded).
    Request signing and headers: see Java SDK documentation.
servers:
  - url: https://api.gatekeeperid.cloud/sdk/integration/v1
paths:
  /.well-known/gatekeeper-config:
    get:
      summary: Platform discovery
      operationId: getWellKnown
      responses:
        '200':
          description: Discovery document with integration.* endpoint URLs
  /login:
    post:
      summary: End-user login (tenant realm)
      operationId: login
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LoginRequest'
      responses:
        '200':
          description: Tokens
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
        '401':
          description: Invalid credentials or tenant
  /social/{provider}/start:
    get:
      summary: Start social OAuth (returns Google authorization URL via Albus)
      operationId: socialStart
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - name: provider
          in: path
          required: true
          schema:
            type: string
            enum: [google]
        - name: redirect_uri
          in: query
          required: true
          schema:
            type: string
        - name: state
          in: query
          schema:
            type: string
      responses:
        '200':
          description: Authorization URL (JSON when Accept application/json)
          content:
            application/json:
              schema:
                type: object
                properties:
                  authorization_url:
                    type: string
                  state:
                    type: string
  /social/{provider}/callback:
    get:
      summary: OAuth callback from Google (browser redirect)
      operationId: socialCallback
      parameters:
        - name: provider
          in: path
          required: true
          schema:
            type: string
        - name: code
          in: query
          schema:
            type: string
        - name: state
          in: query
          schema:
            type: string
      responses:
        '302':
          description: Redirect to app redirect_uri with gk_code
  /social/{provider}/exchange:
    post:
      summary: Exchange gk_code for GateKeeper tokens
      operationId: socialExchange
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - name: provider
          in: path
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [code]
              properties:
                code:
                  type: string
      responses:
        '200':
          description: Tokens
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LoginResponse'
  /register:
    post:
      summary: Register end-user
      operationId: register
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        '200':
          description: OK
  /refresh-token:
    post:
      summary: Refresh access token
      operationId: refreshToken
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                refresh_token:
                  type: string
      responses:
        '200':
          description: New tokens
  /logout:
    post:
      summary: Logout
      operationId: logout
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      responses:
        '200':
          description: OK
  /me:
    get:
      summary: Current end-user profile
      operationId: me
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - $ref: '#/components/parameters/AuthorizationBearer'
      responses:
        '200':
          description: Profile
  /change-password:
    post:
      summary: Change password (not implemented)
      operationId: changePassword
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      responses:
        '501':
          description: NOT_IMPLEMENTED
  /forgot-password:
    post:
      summary: Forgot password (not implemented)
      operationId: forgotPassword
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      responses:
        '501':
          description: NOT_IMPLEMENTED
  /reset-password:
    post:
      summary: Reset password (not implemented)
      operationId: resetPassword
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
      responses:
        '501':
          description: NOT_IMPLEMENTED
  /integration-plan:
    post:
      summary: Submit integration plan
      operationId: createIntegrationPlan
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - $ref: '#/components/parameters/XGkClientId'
        - $ref: '#/components/parameters/XGkClientSecret'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntegrationPlanRequest'
      responses:
        '201':
          description: Plan created (PENDING)
        '401':
          description: INVALID_SDK_CREDENTIALS
  /integration-plans/{plan_id}:
    get:
      summary: Get integration plan status
      operationId: getIntegrationPlan
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - $ref: '#/components/parameters/XGkClientId'
        - $ref: '#/components/parameters/XGkClientSecret'
        - name: plan_id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Plan
        '404':
          description: INTEGRATION_PLAN_NOT_FOUND
  /authorize:
    post:
      summary: Runtime authorization (RBAC by GK_ROLE)
      operationId: authorize
      description: |
        End-user Bearer token + tenant. No client secret. Body must include method+path or permission.
      parameters:
        - $ref: '#/components/parameters/XGkTenantId'
        - $ref: '#/components/parameters/AuthorizationBearer'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthorizeRequest'
      responses:
        '200':
          description: Access granted (allowed true)
        '403':
          description: Access denied (ACCESS_DENIED, ROUTE_NOT_FOUND, etc.)
        '401':
          description: Invalid or missing Bearer token
components:
  parameters:
    XGkTenantId:
      name: X-GK-Tenant-ID
      in: header
      required: true
      schema:
        type: string
      description: Tenant UUID or slug
    XGkClientId:
      name: X-GK-Client-ID
      in: header
      required: true
      schema:
        type: string
    XGkClientSecret:
      name: X-GK-Client-Secret
      in: header
      required: true
      schema:
        type: string
    AuthorizationBearer:
      name: Authorization
      in: header
      required: true
      schema:
        type: string
      description: Bearer end-user access token
  schemas:
    LoginRequest:
      type: object
      required: [email, password]
      properties:
        email:
          type: string
          format: email
        password:
          type: string
    LoginResponse:
      type: object
      properties:
        access_token:
          type: string
        refresh_token:
          type: string
        expires_in:
          type: integer
        external_id:
          type: string
    IntegrationPlanRequest:
      type: object
      required: [application, routes]
      properties:
        application:
          type: string
        environment:
          type: string
          default: default
        routes:
          type: array
          items:
            type: object
            required: [method, path, permission]
            properties:
              method:
                type: string
              path:
                type: string
              permission:
                type: string
              description:
                type: string
    AuthorizeRequest:
      type: object
      description: Provide permission and/or method+path to resolve required permission from route.
      properties:
        method:
          type: string
          example: GET
        path:
          type: string
          example: /api/reclamar
        permission:
          type: string
          example: orders.read
