{
  "openapi": "3.1.0",
  "info": {
    "title": "Glyt API",
    "version": "0.1.0",
    "summary": "Human-in-the-loop approval for agent actions.",
    "description": "An agent asks its operator to approve a specific, cryptographically-bound action; Glyt issues a verifiable, action-bound receipt any downstream service can verify offline. Login with the Colony is the only auth — agents present a Colony token-exchange id_token as a Bearer token; there are no API keys.",
    "contact": { "name": "Glyt", "url": "https://glyt.net/developers" },
    "license": { "name": "Proprietary" }
  },
  "servers": [ { "url": "https://glyt.net" } ],
  "externalDocs": { "description": "Developer guide", "url": "https://glyt.net/developers" },
  "security": [ { "colonyTokenExchange": [] } ],
  "paths": {
    "/api/v1/requests": {
      "post": {
        "operationId": "createApprovalRequest",
        "summary": "Create an approval request for a specific action.",
        "description": "The agent presents a Colony token-exchange id_token. Glyt binds the request to the operator behind the agent (colony_operator_id); only that human may approve.",
        "security": [ { "colonyTokenExchange": [] } ],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateRequest" } } }
        },
        "responses": {
          "201": { "description": "Created (or immediately approved via a standing grant).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RequestView" } } } },
          "400": { "description": "The agent presented no colony_operator_id (needs a colony:operator-scoped token).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "401": { "description": "Missing or invalid Colony id_token.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "422": { "description": "Invalid action or stake_tier.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/requests/{id}": {
      "get": {
        "operationId": "getApprovalRequest",
        "summary": "Poll a request's state; returns the signed receipt once decided.",
        "security": [ { "colonyTokenExchange": [] } ],
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "responses": {
          "200": { "description": "The request's current state (and receipt if approved/denied).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RequestView" } } } },
          "401": { "description": "Missing or invalid Colony id_token.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } },
          "404": { "description": "No such request (or not this agent's).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/receipts/{id}": {
      "get": {
        "operationId": "getReceipt",
        "summary": "Fetch the signed, offline-verifiable receipt envelope.",
        "security": [],
        "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string", "format": "uuid" } } ],
        "responses": {
          "200": { "description": "The signed receipt envelope (ed25519 / did:key).", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReceiptEnvelope" } } } },
          "404": { "description": "No such receipt.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/api/v1/verify": {
      "post": {
        "operationId": "verifyReceipt",
        "summary": "Verify a receipt against an action.",
        "description": "Convenience verification. The authoritative check is offline: recompute the action digest and verify the ed25519 sigchain against the issuer did:key from /.well-known/glyt.json.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerifyRequest" } } }
        },
        "responses": {
          "200": { "description": "Verification result.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/VerifyResult" } } } },
          "422": { "description": "Missing action or receipt.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } }
        }
      }
    },
    "/.well-known/glyt.json": {
      "get": {
        "operationId": "discovery",
        "summary": "Service discovery: issuer did:key, receipt schema version, verification method.",
        "security": [],
        "responses": { "200": { "description": "Discovery document.", "content": { "application/json": { "schema": { "type": "object" } } } } }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "colonyTokenExchange": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "A Colony (thecolony.cc) id_token obtained via RFC 8693 token exchange, audienced to Glyt. Obtain it from the Colony with the requesting agent's credentials; no Glyt API key exists."
      }
    },
    "schemas": {
      "CreateRequest": {
        "type": "object",
        "required": [ "action" ],
        "properties": {
          "action": { "type": "object", "description": "The exact action to be approved. Canonicalised (RFC 8785 / JCS) and hashed into the digest the receipt binds to.", "additionalProperties": true },
          "summary": { "type": "string", "description": "Human-readable summary shown to the operator." },
          "stake_tier": { "type": "string", "enum": [ "low", "medium", "high" ], "default": "medium" },
          "callback_url": { "type": "string", "format": "uri", "description": "Optional. Receives an HMAC-signed webhook when the request settles." }
        }
      },
      "RequestView": {
        "type": "object",
        "properties": {
          "request_id": { "type": "string", "format": "uuid" },
          "state": { "type": "string", "enum": [ "pending", "approved", "denied", "expired" ] },
          "action_digest": { "type": "string", "example": "sha256:…" },
          "stake_tier": { "type": "string", "enum": [ "low", "medium", "high" ] },
          "expires_at": { "type": "string", "format": "date-time" },
          "receipt_id": { "type": "string", "format": "uuid" },
          "receipt": { "$ref": "#/components/schemas/ReceiptEnvelope" }
        }
      },
      "VerifyRequest": {
        "type": "object",
        "required": [ "action", "receipt" ],
        "properties": {
          "action": { "type": "object", "additionalProperties": true },
          "receipt": { "description": "The receipt envelope object or its JSON string.", "oneOf": [ { "type": "object" }, { "type": "string" } ] },
          "required_acr": { "type": "string", "enum": [ "single", "mfa" ] },
          "expected_agent_sub": { "type": "string" }
        }
      },
      "VerifyResult": {
        "type": "object",
        "properties": {
          "valid": { "type": "boolean" },
          "decision": { "type": "string", "enum": [ "approved", "denied", "invalid" ] },
          "acr": { "type": [ "string", "null" ] },
          "not_after": { "type": [ "string", "null" ] },
          "reasons": { "type": "array", "items": { "type": "string" } }
        }
      },
      "ReceiptEnvelope": {
        "type": "object",
        "description": "A signed, offline-verifiable attestation. Contains the issuer did:key, the witnessed claim (action digest + decision), the approver's acr/amr, a validity window, and an ed25519 sigchain.",
        "additionalProperties": true
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      }
    }
  }
}
