openapi: 3.1.0
info:
  title: GaaS API — Governance as a Service
  version: "0.2.17"
  description: |
    The GaaS API provides governance for autonomous AI agents. Every agent action
    passes through a five-stage pipeline: Intent Declaration, Context Enrichment,
    Policy Evaluation, Deliberation Engine, and Decision + Audit.

    ## Base URL
    `https://api.gaas.is/v1`

    ## Authentication
    All requests require an API key passed in the `X-API-Key` header:
    ```
    X-API-Key: gsk_...
    ```

    ## Shadow Mode
    Append `?mode=shadow` to any intent submission to run the full governance
    pipeline without enforcement. Actions are evaluated and audited but never blocked.

    ## What this file covers
    The routes most integrations start with, plus the public trust routes (check a proof
    token, fetch the signing key, list and download the daily public timestamps) and the
    routes to connect your own systems (context endpoint). `info.version` is the production
    API version this file was checked against. The complete spec, generated from the running
    service, is at https://api.gaas.is/openapi.json.
  contact:
    name: H2Om.AI LLC dba GaaS
    url: https://gaas.is/contact
  license:
    name: Proprietary
    url: https://gaas.is

externalDocs:
  description: Complete API spec, generated from the running service
  url: https://api.gaas.is/openapi.json

servers:
  - url: https://api.gaas.is/v1
    description: Production

paths:
  /onboarding/quickstart:
    post:
      operationId: quickstart
      summary: Create a shadow deployment
      description: |
        Register a new organization and receive API credentials for a 14-day
        free shadow deployment. No credit card required.
      tags:
        - Onboarding
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - org_name
                - description
              properties:
                email:
                  type: string
                  format: email
                  description: Contact email for the organization
                  example: engineer@acme.com
                org_name:
                  type: string
                  description: Organization name
                  example: Acme Corp
                description:
                  type: string
                  description: Description of what your AI agents do
                  example: "Process customer refunds, generate compliance reports, handle loan applications"
      responses:
        "201":
          description: Shadow deployment created successfully
          content:
            application/json:
              schema:
                type: object
                required: [membrane_id, membrane_status, org_id, api_key, key_id, quickstart_snippet, next_steps]
                properties:
                  membrane_id:
                    type: string
                    description: Organization identity on the GaaS network
                    example: mem_3f9a1c7e2b4d
                  membrane_status:
                    type: string
                    description: The new membrane's lifecycle state; shadow on success
                    example: shadow
                  org_id:
                    type: string
                    description: The new organization's id
                    example: org_acme_corp
                  api_key:
                    type: string
                    description: An admin API key for the new organization. Will not be shown again.
                    example: gsk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6
                  key_id:
                    type: string
                    description: The key's id (the key itself is stored hashed)
                    example: key_5e8d2c1a9b7f4e3d
                  quickstart_snippet:
                    type: string
                    description: A ready-to-run curl command that submits an intent in shadow mode
                  next_steps:
                    type: array
                    items:
                      type: string
                    description: Ordered list of recommended next steps
                    example:
                      - "Submit intents with ?mode=shadow using your API key"
                      - "Review shadow stats: GET /v1/membranes/mem_3f9a1c7e2b4d/shadow/stats"
                      - "Activate when ready: POST /v1/membranes/mem_3f9a1c7e2b4d/activate"
        "413":
          description: Request body larger than 1 MB (payload_too_large)
        "422":
          description: Missing or invalid fields, or an email on a reserved domain
        "429":
          description: Too many onboarding requests (10 a minute)

  /intents:
    post:
      operationId: declareIntent
      summary: Declare an agent intent for governance evaluation
      description: |
        Submit an agent's intended action through the full five-stage governance
        pipeline. The pipeline evaluates the intent, enriches context, applies
        policies, triggers deliberation if needed, and returns an audited decision.

        Use `?mode=shadow` to run without enforcement.

        **Note:** The schema below is illustrative. The full IntentDeclaration schema
        (with nested `agent`, `action`, `context_provided`, and `governance_request`
        objects) is available at https://api.gaas.is/openapi.json.
      tags:
        - Governance
      security:
        - apiKeyAuth: []
      parameters:
        - name: mode
          in: query
          required: false
          schema:
            type: string
            enum:
              - live
              - shadow
              - test
            default: live
          description: |
            `live` — full pipeline with active enforcement (default).
            `shadow` — evaluation and audit without enforcement; skips deliberation and does not count toward quota.
            `test` — full pipeline; the decision is recorded with pipeline_mode "test".
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - intent
              properties:
                intent:
                  type: object
                  required:
                    - agent
                    - action
                  properties:
                    agent:
                      type: object
                      required: [id]
                      properties:
                        id:
                          type: string
                          maxLength: 256
                          example: cx-agent-7
                        framework:
                          type: string
                          enum: [langchain, autogen, crewai, openai_assistants, anthropic_tools, semantic_kernel, haystack, custom]
                          default: custom
                    action:
                      type: object
                      required: [type, verb, target, payload]
                      properties:
                        type:
                          type: string
                          enum: [communicate, transact, access, control, publish, recommend, modify]
                          example: communicate
                        verb:
                          type: string
                          maxLength: 128
                          example: send
                        target:
                          type: object
                          required: [type, identifier]
                          properties:
                            type:
                              type: string
                              enum: [person, system, account, device, platform, record, dataset, endpoint, resource]
                              example: endpoint
                            identifier:
                              type: string
                              maxLength: 512
                              example: email-service
                            sensitivity:
                              type: string
                              enum: [public, internal, confidential, regulated]
                              default: public
                        payload:
                          type: object
                          required: [summary, content, estimated_impact]
                          properties:
                            summary:
                              type: string
                              minLength: 10
                              maxLength: 1000
                              example: Send welcome email to new user
                            content:
                              type: object
                              additionalProperties: true
                              example:
                                template: welcome_series
                            estimated_impact:
                              type: object
                              required: [reversible]
                              properties:
                                reversible:
                                  type: boolean
                                  example: true
                                financial_exposure_usd:
                                  type: number
                                  minimum: 0
                                  default: 0
                                audience_size:
                                  type: integer
                                  minimum: 0
                                  default: 1
                                regulatory_domains:
                                  type: array
                                  items:
                                    type: string
                                data_categories:
                                  type: array
                                  items:
                                    type: string
                    context_provided:
                      type: object
                      additionalProperties: true
                      description: Context the agent chooses to share (session_id, conversation_id, user_state, environment, custom)
                    governance_request:
                      type: object
                      description: Governance preferences (urgency, max_latency_ms, fallback_on_timeout, require_deliberation, require_human_review)
                      additionalProperties: true
                    idempotency_key:
                      type: string
                      maxLength: 128
      responses:
        "200":
          description: Governance decision returned (abridged; see the live spec for every field)
          content:
            application/json:
              schema:
                type: object
                properties:
                  decision:
                    type: object
                    properties:
                      id:
                        type: string
                        example: dec_3eb8c129b3404a8c8843ecec0372a70b
                      intent_id:
                        type: string
                      verdict:
                        type: string
                        enum: [approve, approve_modified, escalate, block]
                      verdict_reason:
                        type: string
                      modifications:
                        type: array
                        items:
                          type: object
                          additionalProperties: true
                      conditions:
                        type: array
                        items:
                          type: string
                      risk_assessment:
                        type: object
                        properties:
                          score:
                            type: number
                          classification:
                            type: string
                      governance_metadata:
                        type: object
                        additionalProperties: true
                        description: Stages executed, deliberation_triggered, policy counts, pipeline_latency_ms
                      reasoning:
                        type: object
                        additionalProperties: true
                        description: Reasoning chain, including blocking_policies on a block
                      audit_ref:
                        type: string
                        description: Reference to the decision's audit record
                        example: aud_6c8621b644694f30bf5b5656bc6747dd
                      pipeline_mode:
                        type: string
                        enum: [live, shadow, test]
        "401":
          description: Missing or invalid API key
        "402":
          description: Plan quota exceeded (live and test modes; shadow does not count toward quota)
        "422":
          description: Request failed schema or semantic validation
        "429":
          description: Rate limit exceeded (Retry-After header set)

  /verify/proof/{token_id}:
    get:
      operationId: verifyProofToken
      summary: Check a Governance Proof Token (public, no API key)
      description: |
        Checks that GaaS signed the token (ECDSA P-256 / SHA-256), that its contents are
        unchanged, and that the audit record it points to still matches its hash. Returns the
        signed token, so it can also be checked offline with the key at
        `/.well-known/gaas-audit-keys.json`. Every live decision carries a proof token.
      tags:
        - Trust
      security: []
      parameters:
        - name: token_id
          in: path
          required: true
          schema:
            type: string
      responses:
        "200":
          description: The check result and the signed token
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VerifyProofEnvelope"
        "404":
          description: No token has this id

  /.well-known/gaas-audit-keys.json:
    servers:
      - url: https://api.gaas.is
        description: Production (served at the root, not under /v1)
    get:
      operationId: getAuditKeys
      summary: Public key that signs proof tokens and audit records (JWK Set)
      description: |
        Public: anyone checking a proof token offline needs it. `keys` is empty when
        signing is off.
      tags:
        - Trust
      security: []
      responses:
        "200":
          description: JWK Set
          content:
            application/json:
              schema:
                type: object

  /audit/timestamps:
    get:
      operationId: listPublicTimestamps
      summary: Your organization's daily public timestamps
      description: |
        Once a day, each organization's audit records for the previous UTC day are combined
        into one digest and stamped into Bitcoin through the free, public OpenTimestamps
        service. Lists your organization's days, newest first, with the digest recipe.
        Any API key of the organization can read them. Guide: https://gaas.to/audit-timestamps
      tags:
        - Trust
      security:
        - apiKeyAuth: []
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 366
            default: 90
      responses:
        "200":
          description: Your organization's stamped days and the digest recipe
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Missing or invalid API key

  /audit/timestamps/{day}/ots:
    get:
      operationId: downloadPublicTimestamp
      summary: Download the OpenTimestamps proof for one UTC day
      description: |
        The detached `.ots` proof for one day, for the standard `ots` client. Save it as
        `<day>.hashes.ots` next to the `<day>.hashes` file the recipe builds, then
        `ots upgrade` and `ots verify`. Another organization's day is a 404, the same as a
        day with no proof.
      tags:
        - Trust
      security:
        - apiKeyAuth: []
      parameters:
        - name: day
          in: path
          required: true
          schema:
            type: string
            format: date
      responses:
        "200":
          description: The .ots proof file
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "404":
          description: No proof for this day in your organization

  /context-endpoint:
    get:
      operationId: getContextEndpoint
      summary: Your organization's context endpoint (connect your own systems)
      description: |
        Your settings. Secrets appear only as their last four characters. Operator or admin
        key. Guide: https://gaas.to/context-endpoint.html
      tags:
        - Context endpoint
      security:
        - apiKeyAuth: []
      responses:
        "200":
          description: The endpoint settings
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Missing or invalid API key
    put:
      operationId: putContextEndpoint
      summary: Create or replace your organization's context endpoint
      description: |
        During every decision GaaS sends this HTTPS endpoint a signed request describing the
        action (never its free-text content) and reads back the facts the policies check, in
        up to six categories. If it fails or is slow, the decision still happens and the missing
        facts count as risk. Changing the address, categories, secret or time limit switches it
        off until a test passes. Admin key.
      tags:
        - Context endpoint
      security:
        - apiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/EndpointSettings"
      responses:
        "200":
          description: The saved settings
          content:
            application/json:
              schema:
                type: object
        "422":
          description: Request failed validation
    delete:
      operationId: deleteContextEndpoint
      summary: Remove your organization's context endpoint
      description: Admin key.
      tags:
        - Context endpoint
      security:
        - apiKeyAuth: []
      responses:
        "200":
          description: Removed
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Missing or invalid API key

  /context-endpoint/test:
    post:
      operationId: testContextEndpoint
      summary: Send a signed test request to your context endpoint
      description: A passing test is required before the endpoint can be switched on. Admin key.
      tags:
        - Context endpoint
      security:
        - apiKeyAuth: []
      responses:
        "200":
          description: The test result
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Missing or invalid API key

  /context-endpoint/rotate-signing-secret:
    post:
      operationId: rotateContextEndpointSecret
      summary: Replace the signing secret (shown once)
      description: Admin key.
      tags:
        - Context endpoint
      security:
        - apiKeyAuth: []
      responses:
        "200":
          description: The new signing secret, shown only in this response
          content:
            application/json:
              schema:
                type: object
        "401":
          description: Missing or invalid API key

components:
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: "API key from onboarding (gsk_...), sent in the X-API-Key header"

  schemas:
    VerifyProofEnvelope:
      type: object
      required: [token_id, valid]
      properties:
        token_id:
          type: string
        valid:
          type: boolean
        signature_valid:
          type: [boolean, "null"]
        chain_integrity:
          type: [boolean, "null"]
        verdict:
          type: [string, "null"]
        agent_id:
          type: [string, "null"]
        org_id:
          type: [string, "null"]
        issued_at:
          description: When the token was issued
        key_id:
          type: [string, "null"]
        token:
          type: [object, "null"]
          description: The signed token, for checking offline against the published key
        error:
          type: [string, "null"]
    EndpointSettings:
      type: object
      required: [url, categories]
      properties:
        url:
          type: string
          maxLength: 2048
          description: HTTPS URL GaaS POSTs to (port 443)
        categories:
          type: array
          minItems: 1
          maxItems: 6
          items:
            type: string
            enum: [environmental, entity_state, regulatory, organizational, identity, security]
        auth_type:
          type: string
          enum: [none, bearer, header]
          default: none
        auth_header_name:
          type: [string, "null"]
          maxLength: 64
          description: For auth_type=header
        auth_secret:
          type: [string, "null"]
          maxLength: 4096
          writeOnly: true
          description: Write-only. Omit or leave empty to keep the saved secret. Never returned.
        timeout_ms:
          type: [integer, "null"]
          minimum: 200
          maximum: 3000
        enabled:
          type: [boolean, "null"]
          description: true needs a passing test on these settings
