v0.2.0 — Current

OpenTerms Specification

Machine-readable legal terms for the agentic web. Define what AI agents can and can't do on your service — in a format they can actually parse.

OpenTerms is a JSON-based protocol that lets services declare their terms of service, permissions, rate limits, and compliance requirements in a structured format. Think of it as robots.txt for AI agent behavior.

New in v0.2.0: JSON-LD support (@context), policy identifiers (policy_id), ORS verification integration, HIPAA compliance fields, data residency, permission scoping/frequency, and an extensions namespace.

Quick Start

Create an openterms.json file and host it at the root of your domain:

openterms.json
{
  "$schema": "https://openterms.com/schema/openterms.schema.json",
  "openterms_version": "0.2.0",
  "service": {
    "name": "Your Service",
    "domain": "yourservice.com",
    "tos_url": "https://yourservice.com/terms"
  },
  "permissions": {
    "read_content": true,
    "create_account": false,
    "make_purchases": false,
    "scrape_data": false,
    "api_access": true,
    "browser_automation": false
  },
  "requires_consent": true,
  "jurisdiction": "US",
  "contact": "legal@yourservice.com",
  "last_updated": "2025-06-01"
}

That's it. AI agents fetch https://yourservice.com/openterms.json before taking any action, just like crawlers check robots.txt.

Pro tip: Add the $schema field to get auto-completion and inline validation in VS Code, JetBrains, and other editors that support JSON Schema.

How It Works

  1. Services publish an openterms.json at their domain root (or any discoverable URL)
  2. Agents query the file before taking actions — permissions are structured data, not legalese
  3. Compliance is automatic — every agent action has a legal basis on record, with optional cryptographic receipts via ORS

Core Fields

Field Type Status Description
openterms_version string Required Spec version (e.g. "0.2.0"). Semver format.
service string | object Required Service info. Shorthand: "acme.com". Full: object with name, domain, tos_url, privacy_url, description, logo_url.
permissions object Required What agents can do. See Permissions section.
$schema string (URI) Optional Self-referencing schema URI. Enables editor auto-completion.
@context string | object New JSON-LD context for semantic web / linked data interoperability.
policy_id string New Globally unique identifier for this terms document. Used in ORS receipts and audit trails.
requires_consent boolean Optional Must the agent obtain explicit consent before acting?
jurisdiction string | string[] Optional ISO 3166-1/2 jurisdiction code(s). E.g. "US-DE", ["US-CA", "EU"].
contact string | object Optional Legal contact. Shorthand: email string. Full: object with email, name, url.
last_updated string (date) Optional ISO 8601 date when terms were last modified.
expires string (date) Optional Date these terms expire. Agents should re-fetch after this date.

Permissions

The permissions object defines what AI agents can do. Each value is either:

  • true — allowed unconditionally
  • false — denied
  • Conditional object — allowed with conditions

Standard Permissions

PermissionDescription
read_contentRead publicly available content
create_accountCreate user accounts
make_purchasesMake purchases or financial transactions
scrape_dataScrape or bulk-download data
post_contentPost, publish, or submit content
modify_dataModify existing data or settings
delete_dataDelete data
automated_messagingSend messages to users
api_accessAccess the service's API
browser_automationUse browser automation tools
execute_codeExecute code on the platform New
access_user_dataAccess personal or user-specific data New

Custom permissions are also allowed — the schema accepts any additional string keys with permission values.

Conditional Permission Object

{
  "make_purchases": {
    "allowed": true,
    "conditions": "Max $500/day. Agent must be linked to verified human.",
    "requires_auth": true,
    "max_frequency": "50/day",
    "scope": "authenticated"
  }
}
FieldTypeDescription
allowedbooleanRequired Whether the permission is granted.
conditionsstringHuman-readable conditions or restrictions.
requires_authbooleanWhether this permission requires authentication.
max_frequencystringRate limit for this specific action. E.g. "10/hour", "100/day". New
scopestringWhat data subset this applies to. E.g. "public", "authenticated", "premium". New

Rate Limits

{
  "rate_limits": {
    "requests_per_minute": 60,
    "requests_per_hour": 1000,
    "requests_per_day": 10000,
    "concurrent_sessions": 5
  }
}

All fields are optional integers. concurrent_sessions is new in v0.2.0 and limits how many simultaneous agent connections are allowed.

Data Handling

{
  "data_handling": {
    "stores_agent_data": true,
    "shares_with_third_parties": false,
    "retention_days": 90,
    "gdpr_compliant": true,
    "ccpa_compliant": true,
    "hipaa_compliant": false,
    "data_residency": ["US", "EU"]
  }
}
FieldTypeDescription
stores_agent_databooleanStores data about agent interactions?
shares_with_third_partiesbooleanShares agent data with third parties?
retention_daysintegerDays data is retained. 0 = no retention.
gdpr_compliantbooleanGDPR compliant?
ccpa_compliantbooleanCCPA compliant?
hipaa_compliantbooleanHIPAA compliant? New
data_residencystring | string[]Where data is stored. ISO codes. New

Authentication

{
  "authentication": {
    "required": true,
    "methods": ["api_key", "oauth2"],
    "registration_url": "https://acme.com/developers",
    "docs_url": "https://docs.acme.com/auth"
  }
}

Supported methods: api_key, oauth2, bearer_token, basic_auth, mTLS New, none.

The docs_url field is new in v0.2.0 — link directly to your auth documentation for faster agent onboarding.

Verification

New in v0.2.0. Enables ORS (Open Receipt Specification) integration — cryptographic receipts proving an agent acknowledged your terms before acting.

{
  "verification": {
    "jwks_url": "https://acme.com/.well-known/jwks.json",
    "signing_algorithm": "Ed25519",
    "policy_hash": "a1b2c3d4e5f6..."
  }
}
FieldTypeDescription
jwks_urlstring (URI)URL to your JWKS endpoint for verifying signed receipts.
signing_algorithmstringOne of: Ed25519, RS256, ES256.
policy_hashstringSHA-256 hash of the canonical terms document. 64 hex chars.

How ORS + OpenTerms work together: OpenTerms defines what agents can do. ORS provides cryptographic proof they acknowledged those terms. The policy_id field links your terms to ORS receipts.

Extensions

The extensions object is a namespace for custom or industry-specific fields. Use reverse-domain notation to avoid conflicts:

{
  "extensions": {
    "health.hipaa.baa_required": true,
    "health.hipaa.audit_log_url": "https://acme.com/api/audit",
    "com.acme.internal_tier": "enterprise",
    "org.fintech.pci_dss_level": 1
  }
}

Extensions are free-form — any JSON value is accepted. This keeps the core schema stable while allowing domain-specific needs.

Examples

Complete, validated examples for common use cases:

Use CaseFileKey Features
SaaS API saas-api.json Full API with OAuth, rate limits, conditional purchases, sandboxed code execution
E-Commerce ecommerce.json Purchase limits, product scraping with conditions, multi-jurisdiction
Social Platform social-platform.json AI disclosure requirements, DM opt-in, frequency limits per permission
Open/Public API open-api.json Minimal restrictions, high rate limits, no auth required
Healthcare (HIPAA) healthcare.json HIPAA fields, ORS verification, BAA requirement, extensions namespace, mTLS auth

Load any example directly in the Validator to explore it interactively.

Adoption Guide

Step 1: Create your openterms.json

Start with the Quick Start template. Add permissions that match your service's terms of service. Be explicit — false is better than omitting a permission.

Step 2: Host it

Place the file at https://yourdomain.com/openterms.json — the standard discovery path. Alternatively, reference it from your existing robots.txt:

robots.txt
# AI Agent Terms
OpenTerms: https://yourdomain.com/openterms.json

Step 3: Validate

Use the interactive validator or the programmatic API:

curl -X POST https://openterms.com/api/validate \
  -H "Content-Type: application/json" \
  -d '{"content": <your openterms.json>}'

Step 4: Keep it updated

Update last_updated whenever you change terms. Set expires to force agents to re-fetch periodically.

ORS Integration

The Open Receipt Specification (ORS) provides cryptographic receipts proving AI agents acknowledged specific policies before taking actions.

OpenTerms + ORS together create a complete policy lifecycle:

  1. OpenTerms declares what's allowed (the policy)
  2. ORS proves an agent read and acknowledged that policy (the receipt)
  3. The policy_id links the two together

To enable ORS, add the verification and policy_id fields to your openterms.json. See the Healthcare example for a complete implementation.

CI/CD Validation

Validate your openterms.json in CI/CD pipelines using the API endpoint:

GitHub Actions
- name: Validate openterms.json
  run: |
    RESULT=$(curl -s -X POST https://openterms.com/api/validate \
      -H "Content-Type: application/json" \
      -d "{\"content\": $(cat openterms.json)}")
    echo "$RESULT" | jq .
    VALID=$(echo "$RESULT" | jq -r '.valid')
    if [ "$VALID" != "true" ]; then
      echo "openterms.json validation failed!"
      exit 1
    fi
npm script
// package.json
{
  "scripts": {
    "validate:terms": "curl -sf -X POST https://openterms.com/api/validate -H 'Content-Type: application/json' -d '{\"content\":'$(cat openterms.json)'}' | jq -e '.valid'"
  }
}