{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://openterms.com/schema/openterms.schema.json",
  "title": "OpenTerms",
  "description": "Machine-readable legal terms for the agentic web. The standard protocol for AI agents to understand what they're allowed to do on any service. Version 0.3.0.",
  "type": "object",
  "required": ["openterms_version", "service", "permissions"],
  "properties": {
    "$schema": {
      "type": "string",
      "format": "uri",
      "description": "Optional self-referencing schema URI for editor auto-completion and validation.",
      "examples": ["https://openterms.com/schema/openterms.schema.json"]
    },
    "@context": {
      "description": "Optional JSON-LD context for linked data interoperability. Enables semantic web tooling to interpret OpenTerms documents.",
      "oneOf": [
        {
          "type": "string",
          "format": "uri",
          "examples": ["https://openterms.com/context/v0.3"]
        },
        {
          "type": "object",
          "additionalProperties": true
        }
      ]
    },
    "openterms_version": {
      "type": "string",
      "description": "The version of the OpenTerms specification this file conforms to.",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "examples": ["0.3.0", "0.2.0", "0.1.0"]
    },
    "policy_id": {
      "type": "string",
      "description": "A globally unique identifier for this terms document. Useful for referencing in audit trails, ORS receipts, and compliance logs. Recommended format: reverse-domain + path.",
      "examples": ["com.acme.api.terms.2025", "org.example.platform-v2"]
    },
    "service": {
      "description": "Information about the service publishing these terms.",
      "oneOf": [
        {
          "type": "string",
          "description": "The domain of the service (shorthand).",
          "examples": ["acme.com"]
        },
        {
          "type": "object",
          "required": ["domain"],
          "properties": {
            "name": {
              "type": "string",
              "description": "Human-readable name of the service.",
              "examples": ["Acme Corp"]
            },
            "domain": {
              "type": "string",
              "description": "Primary domain of the service.",
              "pattern": "^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$",
              "examples": ["acme.com"]
            },
            "description": {
              "type": "string",
              "description": "Brief description of the service for agent context.",
              "examples": ["Cloud infrastructure and API platform"]
            },
            "tos_url": {
              "type": "string",
              "format": "uri",
              "description": "URL to the human-readable terms of service.",
              "examples": ["https://acme.com/terms"]
            },
            "privacy_url": {
              "type": "string",
              "format": "uri",
              "description": "URL to the privacy policy.",
              "examples": ["https://acme.com/privacy"]
            },
            "logo_url": {
              "type": "string",
              "format": "uri",
              "description": "URL to the service logo (for UI rendering)."
            }
          },
          "additionalProperties": false
        }
      ]
    },
    "permissions": {
      "type": "object",
      "description": "What AI agents are allowed to do on this service. Each key is a permission, each value is true (allowed), false (denied), null (unknown), or a condition object. Exactly seven canonical keys are defined; no additional keys are permitted.",
      "properties": {
        "read_content": {
          "description": "Can the agent read publicly available content?",
          "$ref": "#/definitions/permission_value"
        },
        "scrape_data": {
          "description": "Can the agent scrape or bulk-download data?",
          "$ref": "#/definitions/permission_value"
        },
        "api_access": {
          "description": "Can the agent access the service's API?",
          "$ref": "#/definitions/permission_value"
        },
        "create_account": {
          "description": "Can the agent create user accounts?",
          "$ref": "#/definitions/permission_value"
        },
        "make_purchases": {
          "description": "Can the agent make purchases or financial transactions?",
          "$ref": "#/definitions/permission_value"
        },
        "post_content": {
          "description": "Can the agent post, publish, or submit content?",
          "$ref": "#/definitions/permission_value"
        },
        "allow_training": {
          "description": "Can third parties (including the querying agent's principals) use this service's content or data for AI/ML model training?",
          "$ref": "#/definitions/permission_value"
        }
      },
      "additionalProperties": false
    },
    "rate_limits": {
      "type": "object",
      "description": "Rate limiting rules for AI agent requests.",
      "properties": {
        "requests_per_minute": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum requests per minute."
        },
        "requests_per_hour": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum requests per hour."
        },
        "requests_per_day": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum requests per day."
        },
        "concurrent_sessions": {
          "type": "integer",
          "minimum": 0,
          "description": "Maximum concurrent agent sessions allowed."
        }
      },
      "additionalProperties": false
    },
    "data_handling": {
      "type": "object",
      "description": "How the service handles data from AI agent interactions.",
      "properties": {
        "stores_agent_data": {
          "type": "boolean",
          "description": "Does the service store data about agent interactions?"
        },
        "shares_with_third_parties": {
          "type": "boolean",
          "description": "Does the service share agent interaction data with third parties?"
        },
        "retention_days": {
          "type": "integer",
          "minimum": 0,
          "description": "How many days agent interaction data is retained. 0 means no retention."
        },
        "gdpr_compliant": {
          "type": "boolean",
          "description": "Is the data handling GDPR compliant?"
        },
        "ccpa_compliant": {
          "type": "boolean",
          "description": "Is the data handling CCPA compliant?"
        },
        "hipaa_compliant": {
          "type": "boolean",
          "description": "Is the data handling HIPAA compliant?"
        },
        "data_residency": {
          "description": "Where agent data is stored geographically.",
          "oneOf": [
            { "type": "string", "examples": ["US", "EU", "US-VA"] },
            { "type": "array", "items": { "type": "string" }, "examples": [["US", "EU"]] }
          ]
        }
      },
      "additionalProperties": false
    },
    "authentication": {
      "type": "object",
      "description": "Authentication requirements for AI agent access.",
      "properties": {
        "required": {
          "type": "boolean",
          "description": "Is authentication required for agent access?"
        },
        "methods": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["api_key", "oauth2", "bearer_token", "basic_auth", "mTLS", "none"]
          },
          "description": "Supported authentication methods."
        },
        "registration_url": {
          "type": "string",
          "format": "uri",
          "description": "URL where agents/developers can register for API access."
        },
        "docs_url": {
          "type": "string",
          "format": "uri",
          "description": "URL to authentication documentation."
        }
      },
      "additionalProperties": false
    },
    "verification": {
      "type": "object",
      "description": "Cryptographic verification configuration. Enables ORS (Open Receipt Specification) integration for proving agents acknowledged terms before acting.",
      "properties": {
        "jwks_url": {
          "type": "string",
          "format": "uri",
          "description": "URL to JWKS (JSON Web Key Set) for verifying signed receipts."
        },
        "signing_algorithm": {
          "type": "string",
          "enum": ["Ed25519", "RS256", "ES256"],
          "description": "Signing algorithm used for receipt verification."
        },
        "policy_hash": {
          "type": "string",
          "description": "SHA-256 hash of the canonical terms document for integrity verification.",
          "pattern": "^[a-f0-9]{64}$"
        }
      },
      "additionalProperties": false
    },
    "requires_consent": {
      "type": "boolean",
      "description": "Must the agent obtain explicit consent before acting on this service?"
    },
    "jurisdiction": {
      "description": "Legal jurisdiction(s) governing these terms.",
      "oneOf": [
        {
          "type": "string",
          "description": "ISO 3166-1/2 jurisdiction code.",
          "examples": ["US-DE", "EU", "GB"]
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Multiple jurisdiction codes.",
          "examples": [["US-CA", "EU"]]
        }
      ]
    },
    "contact": {
      "description": "Contact for legal or compliance inquiries.",
      "oneOf": [
        {
          "type": "string",
          "format": "email",
          "description": "Contact email address.",
          "examples": ["legal@acme.com"]
        },
        {
          "type": "object",
          "properties": {
            "email": {
              "type": "string",
              "format": "email"
            },
            "name": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "format": "uri"
            }
          },
          "additionalProperties": false
        }
      ]
    },
    "last_updated": {
      "type": "string",
      "format": "date",
      "description": "Date these terms were last updated (ISO 8601 date).",
      "examples": ["2025-01-01"]
    },
    "expires": {
      "type": "string",
      "format": "date",
      "description": "Date these terms expire and should be re-fetched.",
      "examples": ["2026-01-01"]
    },
    "extensions": {
      "type": "object",
      "description": "Namespace for custom or industry-specific extensions. Use reverse-domain notation for keys to avoid conflicts. The 'com.openterms.meta' key is the first official namespace, used for generator and provenance metadata.",
      "examples": [{ "com.acme.custom_field": "value", "org.healthcare.phi_access": false }],
      "properties": {
        "com.openterms.meta": {
          "type": "object",
          "description": "Official OpenTerms metadata namespace (v0.3.1+). Records provenance: source, generator tool, and generation timestamp. This namespace lives in extensions (not at root) because the root schema uses additionalProperties: false.",
          "properties": {
            "source": {
              "type": "string",
              "description": "The origin of this file. 'self' means written by the domain owner. A domain (e.g. 'openterms.com') means auto-generated by that service.",
              "examples": ["self", "openterms.com"]
            },
            "generator": {
              "type": "string",
              "description": "The tool or service that generated this file, in reverse-domain/version format.",
              "examples": ["openterms.com/v0.3.0"]
            },
            "generated_at": {
              "type": "string",
              "format": "date-time",
              "description": "ISO 8601 timestamp of when this file was generated.",
              "examples": ["2025-06-01T12:00:00Z"]
            }
          },
          "additionalProperties": true
        }
      },
      "additionalProperties": true
    },
    "discovery": {
      "type": "object",
      "description": "Machine-readable pointers to agent-accessible interfaces and API specifications for this service.",
      "properties": {
        "mcp_servers": {
          "type": "array",
          "description": "MCP (Model Context Protocol) servers exposed by this service.",
          "items": {
            "type": "object",
            "required": ["url", "transport"],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri",
                "description": "URL of the MCP server endpoint."
              },
              "transport": {
                "type": "string",
                "enum": ["sse", "stdio", "streamable-http"],
                "description": "Transport protocol used by this MCP server."
              },
              "description": {
                "type": "string",
                "description": "Human-readable description of what this MCP server provides."
              }
            },
            "additionalProperties": false
          }
        },
        "api_specs": {
          "type": "array",
          "description": "API specification documents describing this service's interfaces.",
          "items": {
            "type": "object",
            "required": ["url", "type"],
            "properties": {
              "url": {
                "type": "string",
                "format": "uri",
                "description": "URL to the API specification document."
              },
              "type": {
                "type": "string",
                "enum": ["openapi_3", "swagger_2", "graphql_schema"],
                "description": "The specification format/type."
              },
              "description": {
                "type": "string",
                "description": "Human-readable description of this API spec."
              }
            },
            "additionalProperties": false
          }
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false,
  "definitions": {
    "permission_value": {
      "description": "A permission can be true (allowed), false (denied), null (unknown/not addressed), or a conditional object.",
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        },
        {
          "type": "object",
          "properties": {
            "allowed": {
              "type": "boolean",
              "description": "Whether this permission is granted."
            },
            "conditions": {
              "type": "string",
              "description": "Human-readable conditions or restrictions."
            },
            "requires_auth": {
              "type": "boolean",
              "description": "Whether this permission requires authentication."
            },
            "max_frequency": {
              "type": "string",
              "description": "Maximum frequency for this action (e.g., '10/hour', '100/day').",
              "examples": ["10/hour", "100/day", "1000/month"]
            },
            "scope": {
              "type": "string",
              "description": "What scope or data subset this permission applies to.",
              "examples": ["public", "authenticated", "premium"]
            }
          },
          "required": ["allowed"],
          "additionalProperties": false
        }
      ]
    }
  }
}
