{
  "openapi": "3.1.0",
  "info": {
    "title": "EchoScan Agent Trial and Report API",
    "version": "1.0.0",
    "description": "Machine-readable contract for EchoScan Agent Trial discovery, x402-compatible activation, credential recovery, trial status, and canonical Lite Report retrieval. Product availability and payment terms are runtime data; clients must not infer production payment configuration from examples."
  },
  "servers": [{ "url": "https://api.echoscan.org" }],
  "externalDocs": {
    "description": "EchoScan Agent API guide",
    "url": "https://echoscan.org/pages/agent-api-en-US.html"
  },
  "tags": [
    {
      "name": "Agent Trial",
      "description": "Discover and activate an independent short-lived machine evaluation."
    },
    { "name": "Reports", "description": "Retrieve the existing Report API v1 response by Imprint." }
  ],
  "paths": {
    "/api/v1/agent/products": {
      "get": {
        "tags": ["Agent Trial"],
        "operationId": "listAgentProducts",
        "summary": "List machine-purchasable products and current availability",
        "description": "This endpoint is the live authority for availability, price, asset, network, duration, capabilities, and limits. Disabled or incomplete payment configuration returns available=false without a fabricated fallback quote; price is present only when available is true.",
        "responses": {
          "200": {
            "description": "Current product catalog",
            "headers": { "Link": { "$ref": "#/components/headers/ApiCatalogLink" } },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ProductCatalog" } }
            }
          },
          "429": { "$ref": "#/components/responses/Error" },
          "500": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/agent/trial-intents": {
      "post": {
        "tags": ["Agent Trial"],
        "operationId": "createAgentTrialIntent",
        "summary": "Create a short-lived purchase intent",
        "description": "Accepts one exact HTTP or HTTPS Origin. The claim token is returned once in the successful creation response and must remain in process memory.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": { "schema": { "$ref": "#/components/schemas/CreateIntentRequest" } }
          }
        },
        "responses": {
          "201": {
            "description": "Intent created; no payment challenge, usable Environment, or API key exists yet",
            "headers": { "Cache-Control": { "$ref": "#/components/headers/NoStore" } },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CreateIntentResponse" }
              }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" },
          "503": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/agent/trial-intents/{intentId}/activate": {
      "post": {
        "tags": ["Agent Trial"],
        "operationId": "activateAgentTrialIntent",
        "summary": "Activate an intent through an x402-compatible exact payment",
        "description": "The first request without PAYMENT-SIGNATURE returns a standard x402 v2 PAYMENT-REQUIRED challenge. An official x402 HTTP client signs and retries the same request. Before any new challenge, clients should query status and must not pay again after payment processing, provisioning, activation, or reconciliation begins.",
        "security": [{ "claimToken": [] }],
        "parameters": [
          { "$ref": "#/components/parameters/IntentId" },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "Standard x402 v2 payment payload created by an official client.",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Activation completed or the same intent is already recoverable; this response never contains credentials",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "Standard x402 v2 settlement response when settlement completed.",
                "schema": { "type": "string" }
              },
              "Cache-Control": { "$ref": "#/components/headers/NoStore" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ActivationResponse" }
              }
            }
          },
          "202": {
            "description": "External settlement completed or activation entered reconciliation; poll the same intent status URL and do not submit another payment",
            "headers": {
              "PAYMENT-RESPONSE": {
                "description": "Standard x402 v2 settlement response when settlement completed, including when local activation still requires reconciliation.",
                "schema": { "type": "string" }
              },
              "Cache-Control": { "$ref": "#/components/headers/NoStore" }
            },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } }
            }
          },
          "402": {
            "description": "x402 v2 payment is required",
            "headers": {
              "PAYMENT-REQUIRED": {
                "required": true,
                "description": "Base64-encoded x402 v2 PaymentRequired object containing the exact locked requirement. It may include the official Bazaar discovery extension when the server SDK supports it.",
                "schema": { "type": "string" }
              },
              "Cache-Control": { "$ref": "#/components/headers/NoStore" }
            },
            "content": {
              "application/json": { "schema": { "type": "object", "additionalProperties": true } }
            }
          },
          "400": { "$ref": "#/components/responses/Error" },
          "401": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" },
          "502": { "$ref": "#/components/responses/Error" },
          "503": { "$ref": "#/components/responses/Error" }
        },
        "x-x402": { "version": 2, "scheme": "exact", "terms": "runtime-product-quote" }
      }
    },
    "/api/v1/agent/trial-intents/{intentId}": {
      "get": {
        "tags": ["Agent Trial"],
        "operationId": "getAgentTrialIntent",
        "summary": "Poll status and retrieve active credentials during the delivery window",
        "security": [{ "claimToken": [] }],
        "parameters": [{ "$ref": "#/components/parameters/IntentId" }],
        "responses": {
          "200": {
            "description": "Current intent status; an active response delivers the trial credentials as top-level fields during the delivery window",
            "headers": { "Cache-Control": { "$ref": "#/components/headers/NoStore" } },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/IntentStatus" } }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/agent/trial": {
      "get": {
        "tags": ["Agent Trial"],
        "operationId": "getAgentTrialGrant",
        "summary": "Read the authenticated trial grant and remaining report units",
        "security": [{ "apiKey": [] }],
        "responses": {
          "200": {
            "description": "Grant status and remaining report, submit, and request limits without payment secrets",
            "headers": { "Cache-Control": { "$ref": "#/components/headers/NoStore" } },
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/TrialGrant" } }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    },
    "/api/v1/fingerprint/report/{imprint}": {
      "get": {
        "tags": ["Reports"],
        "operationId": "getFingerprintReport",
        "summary": "Retrieve the canonical report for an Imprint",
        "description": "For Agent Trial credentials this returns Lite depth only. A successful first delivery of a new Imprint consumes one report unit; re-reading the same Imprint is idempotent. Failed and missing lookups do not consume a unit.",
        "security": [{ "apiKey": [] }],
        "parameters": [{ "$ref": "#/components/parameters/Imprint" }],
        "responses": {
          "200": {
            "description": "Lite Report API v1 response for an Agent Trial key",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/LiteReport" } }
            }
          },
          "401": { "$ref": "#/components/responses/Error" },
          "403": { "$ref": "#/components/responses/Error" },
          "404": { "$ref": "#/components/responses/Error" },
          "409": { "$ref": "#/components/responses/Error" },
          "429": { "$ref": "#/components/responses/Error" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "claimToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "One-time intent claim token returned only at creation."
      },
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Secret server-side EchoScan key."
      }
    },
    "parameters": {
      "IntentId": {
        "name": "intentId",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "pattern": "^ati_[0-9a-f]{32}$" }
      },
      "Imprint": {
        "name": "imprint",
        "in": "path",
        "required": true,
        "schema": { "type": "string", "pattern": "^imp_[0-9a-f]{32}$" }
      }
    },
    "headers": {
      "ApiCatalogLink": {
        "description": "RFC 9727 API catalog discovery link.",
        "schema": { "type": "string", "const": "</.well-known/api-catalog>; rel=api-catalog" }
      },
      "NoStore": {
        "description": "Sensitive intent and credential responses are not cacheable.",
        "schema": { "type": "string", "enum": ["no-store", "private, no-store"] }
      }
    },
    "responses": {
      "Error": {
        "description": "Stable public error envelope",
        "headers": { "Cache-Control": { "$ref": "#/components/headers/NoStore" } },
        "content": {
          "application/json": { "schema": { "$ref": "#/components/schemas/ErrorEnvelope" } }
        }
      }
    },
    "schemas": {
      "ProductCatalog": {
        "type": "object",
        "required": ["products"],
        "properties": {
          "products": { "type": "array", "items": { "$ref": "#/components/schemas/AgentProduct" } }
        },
        "additionalProperties": false
      },
      "AgentProduct": {
        "type": "object",
        "required": [
          "code",
          "version",
          "display_name",
          "available",
          "protocol",
          "scheme",
          "report_units",
          "expires_in_hours",
          "report_depth",
          "capabilities",
          "limits",
          "docs_url"
        ],
        "properties": {
          "code": { "type": "string", "const": "agent_trial_lite_100" },
          "version": { "type": "string", "const": "v1" },
          "display_name": { "type": "string", "const": "Agent Trial — 100 Lite Reports" },
          "available": { "type": "boolean" },
          "protocol": { "type": "string", "const": "x402-compatible" },
          "scheme": { "type": "string", "const": "exact" },
          "price": { "$ref": "#/components/schemas/PaymentQuote" },
          "report_units": { "type": "integer", "const": 100 },
          "expires_in_hours": { "type": "integer", "const": 72 },
          "report_depth": { "type": "string", "const": "lite" },
          "capabilities": { "$ref": "#/components/schemas/AgentTrialCapabilities" },
          "limits": { "$ref": "#/components/schemas/AgentTrialProductLimits" },
          "docs_url": { "type": "string", "format": "uri" }
        },
        "additionalProperties": false,
        "allOf": [
          {
            "if": { "properties": { "available": { "const": true } }, "required": ["available"] },
            "then": { "required": ["price"] },
            "else": { "not": { "required": ["price"] } }
          }
        ]
      },
      "PaymentQuote": {
        "type": "object",
        "required": ["amount_atomic", "asset", "network", "pay_to"],
        "properties": {
          "amount_atomic": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Atomic asset units."
          },
          "asset": { "type": "string" },
          "network": {
            "type": "string",
            "description": "CAIP-2 network identifier, for example eip155:84532 on Base Sepolia."
          },
          "pay_to": { "type": "string", "description": "Runtime-configured recipient address." }
        },
        "additionalProperties": false
      },
      "AgentTrialCapabilities": {
        "type": "array",
        "prefixItems": [
          { "type": "string", "const": "fingerprint.submit" },
          { "type": "string", "const": "fingerprint.report.lite" },
          { "type": "string", "const": "agent.trial.status" }
        ],
        "minItems": 3,
        "maxItems": 3
      },
      "AgentTrialProductLimits": {
        "type": "object",
        "required": [
          "submit_requests",
          "report_requests",
          "requests_per_second",
          "intent_creates_per_ip_per_minute",
          "intent_activations_per_ip_and_intent_per_minute"
        ],
        "properties": {
          "submit_requests": { "type": "integer", "minimum": 1, "default": 300 },
          "report_requests": { "type": "integer", "minimum": 1, "default": 1000 },
          "requests_per_second": { "type": "integer", "minimum": 1, "default": 5 },
          "intent_creates_per_ip_per_minute": {
            "type": "integer",
            "minimum": 1,
            "default": 10
          },
          "intent_activations_per_ip_and_intent_per_minute": {
            "type": "integer",
            "minimum": 1,
            "default": 30
          }
        },
        "additionalProperties": false
      },
      "AgentTrialGrantLimits": {
        "type": "object",
        "required": [
          "submit_requests",
          "submit_requests_used",
          "report_requests",
          "report_requests_used",
          "requests_per_second"
        ],
        "properties": {
          "submit_requests": { "type": "integer", "minimum": 1 },
          "submit_requests_used": { "type": "integer", "minimum": 0 },
          "report_requests": { "type": "integer", "minimum": 1 },
          "report_requests_used": { "type": "integer", "minimum": 0 },
          "requests_per_second": { "type": "integer", "minimum": 1 }
        },
        "additionalProperties": false
      },
      "CreateIntentRequest": {
        "type": "object",
        "required": ["product_code", "origin"],
        "properties": {
          "product_code": { "type": "string", "const": "agent_trial_lite_100" },
          "origin": {
            "type": "string",
            "format": "uri",
            "description": "One exact HTTP or HTTPS Origin without path, query, fragment, wildcard, or user information."
          }
        },
        "additionalProperties": false
      },
      "CreateIntentResponse": {
        "type": "object",
        "required": ["intent_id", "claim_token", "status", "product", "activate_url", "status_url"],
        "properties": {
          "intent_id": { "type": "string" },
          "claim_token": {
            "type": "string",
            "description": "Returned exactly once. Keep only in process memory and send only as a Bearer credential.",
            "x-sensitive": true
          },
          "status": { "type": "string", "const": "payment_required" },
          "product": { "$ref": "#/components/schemas/IntentProduct" },
          "activate_url": { "type": "string", "format": "uri-reference" },
          "status_url": { "type": "string", "format": "uri-reference" }
        },
        "additionalProperties": false
      },
      "IntentProduct": {
        "type": "object",
        "required": ["code", "report_units", "expires_in_hours", "report_depth"],
        "properties": {
          "code": { "type": "string", "const": "agent_trial_lite_100" },
          "report_units": { "type": "integer", "const": 100 },
          "expires_in_hours": { "type": "integer", "const": 72 },
          "report_depth": { "type": "string", "const": "lite" }
        },
        "additionalProperties": false
      },
      "ActivationResponse": {
        "type": "object",
        "required": ["intent_id", "status", "status_url"],
        "properties": {
          "intent_id": { "type": "string" },
          "status": { "$ref": "#/components/schemas/IntentState" },
          "status_url": { "type": "string", "format": "uri-reference" }
        },
        "additionalProperties": false
      },
      "IntentStatus": {
        "oneOf": [
          { "$ref": "#/components/schemas/PendingIntentStatus" },
          { "$ref": "#/components/schemas/ActiveIntentStatus" }
        ]
      },
      "PendingIntentStatus": {
        "type": "object",
        "required": ["intent_id", "status", "expires_at"],
        "properties": {
          "intent_id": { "type": "string" },
          "status": {
            "type": "string",
            "enum": [
              "payment_required",
              "payment_in_progress",
              "payment_failed",
              "provisioning",
              "reconciliation_pending",
              "expired",
              "revoked"
            ]
          },
          "expires_at": { "type": "string", "format": "date-time" }
        },
        "additionalProperties": false
      },
      "ActiveIntentStatus": {
        "type": "object",
        "required": [
          "trial_id",
          "status",
          "environment_id",
          "allowed_origin",
          "quota",
          "expires_at",
          "report_endpoint"
        ],
        "properties": {
          "trial_id": { "type": "string", "pattern": "^trial_[a-zA-Z0-9_-]+$" },
          "status": { "type": "string", "const": "active" },
          "environment_id": { "type": "string", "pattern": "^env_[0-9a-f]{32}$" },
          "api_key": {
            "type": "string",
            "description": "Server-side secret delivered only while the credential-delivery window is open.",
            "x-sensitive": true
          },
          "credential_delivery_expired": {
            "type": "boolean",
            "const": true,
            "description": "Present instead of api_key after the encrypted delivery window closes."
          },
          "allowed_origin": { "type": "string", "format": "uri" },
          "quota": { "$ref": "#/components/schemas/ReportQuota" },
          "expires_at": { "type": "string", "format": "date-time" },
          "report_endpoint": { "type": "string", "const": "/api/v1/fingerprint/report/{imprint}" }
        },
        "oneOf": [
          { "required": ["api_key"], "not": { "required": ["credential_delivery_expired"] } },
          { "required": ["credential_delivery_expired"], "not": { "required": ["api_key"] } }
        ],
        "additionalProperties": false
      },
      "ReportQuota": {
        "type": "object",
        "required": ["total_reports", "used_reports", "remaining_reports"],
        "properties": {
          "total_reports": { "type": "integer", "const": 100 },
          "used_reports": { "type": "integer", "minimum": 0, "maximum": 100 },
          "remaining_reports": { "type": "integer", "minimum": 0, "maximum": 100 }
        },
        "additionalProperties": false
      },
      "IntentState": {
        "type": "string",
        "enum": [
          "payment_required",
          "payment_in_progress",
          "payment_failed",
          "provisioning",
          "reconciliation_pending",
          "active",
          "expired",
          "revoked"
        ]
      },
      "TrialGrant": {
        "type": "object",
        "required": [
          "status",
          "product_code",
          "total_report_units",
          "used_report_units",
          "remaining_report_units",
          "expires_at",
          "capabilities",
          "limits",
          "remaining_submit_requests",
          "remaining_report_requests"
        ],
        "properties": {
          "product_code": { "type": "string", "const": "agent_trial_lite_100" },
          "status": { "type": "string", "enum": ["active", "expired", "revoked"] },
          "total_report_units": { "type": "integer", "const": 100 },
          "used_report_units": { "type": "integer", "minimum": 0, "maximum": 100 },
          "remaining_report_units": { "type": "integer", "minimum": 0, "maximum": 100 },
          "expires_at": { "type": "string", "format": "date-time" },
          "capabilities": { "$ref": "#/components/schemas/AgentTrialCapabilities" },
          "limits": { "$ref": "#/components/schemas/AgentTrialGrantLimits" },
          "remaining_submit_requests": { "type": "integer", "minimum": 0, "maximum": 300 },
          "remaining_report_requests": { "type": "integer", "minimum": 0, "maximum": 1000 }
        },
        "additionalProperties": false
      },
      "LiteReport": {
        "type": "object",
        "required": [
          "schema_version",
          "imprint",
          "created_at",
          "device",
          "risk",
          "browser",
          "operating_system",
          "network"
        ],
        "properties": {
          "schema_version": { "type": "string" },
          "imprint": { "type": "string", "pattern": "^imp_[0-9a-f]{32}$" },
          "created_at": { "type": "string", "format": "date-time" },
          "device": { "type": "object", "additionalProperties": true },
          "risk": {
            "type": "object",
            "required": ["status"],
            "properties": {
              "status": { "type": "string", "enum": ["PASS", "SUSPICIOUS", "DECEPTIVE"] }
            },
            "additionalProperties": false
          },
          "browser": { "type": "object", "additionalProperties": true },
          "operating_system": { "type": "object", "additionalProperties": true },
          "network": { "type": "object", "additionalProperties": true }
        },
        "additionalProperties": true
      },
      "ErrorEnvelope": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": { "code": { "type": "string" }, "message": { "type": "string" } },
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      }
    }
  }
}
