{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "ApiSpec",
  "type": "object",
  "required": [
    "category",
    "description",
    "endpoints",
    "name",
    "routing",
    "subdomain",
    "title",
    "version"
  ],
  "properties": {
    "accounting": {
      "description": "How volume tiers are tracked: pooled (shared counter) or per_agent (per wallet).",
      "default": "pooled",
      "allOf": [
        {
          "$ref": "#/definitions/AccountingMode"
        }
      ]
    },
    "category": {
      "$ref": "#/definitions/ApiCategory"
    },
    "description": {
      "type": "string"
    },
    "endpoints": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Endpoint"
      }
    },
    "env": {
      "description": "Environment variables to set when the spec is loaded. Static values are set directly; `${VAR}` references the runtime environment.",
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "free_tier": {
      "anyOf": [
        {
          "$ref": "#/definitions/FreeTier"
        },
        {
          "type": "null"
        }
      ]
    },
    "name": {
      "type": "string"
    },
    "notes": {
      "type": [
        "string",
        "null"
      ]
    },
    "operator": {
      "description": "Operator config — how this proxy instance runs (signer, recipient, currency).",
      "anyOf": [
        {
          "$ref": "#/definitions/OperatorConfig"
        },
        {
          "type": "null"
        }
      ]
    },
    "quotas": {
      "anyOf": [
        {
          "$ref": "#/definitions/QuotaSpec"
        },
        {
          "type": "null"
        }
      ]
    },
    "recipients": {
      "description": "Named recipient aliases for use in payment splits.",
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/RecipientAlias"
      }
    },
    "routing": {
      "description": "Routing — how requests are handled (proxied upstream or responded to directly).",
      "allOf": [
        {
          "$ref": "#/definitions/RoutingConfig"
        }
      ]
    },
    "session": {
      "description": "Session channel parameters. When set, the middleware issues a 402 with `intent=\"session\"` and accepts signed vouchers instead of per-request charges.",
      "anyOf": [
        {
          "$ref": "#/definitions/SessionSpec"
        },
        {
          "type": "null"
        }
      ]
    },
    "subdomain": {
      "description": "Subdomain for this API: `{subdomain}.agents.solana.com`",
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "version": {
      "type": "string"
    }
  },
  "definitions": {
    "AccessTokenExpiryFormat": {
      "description": "Supported absolute expiry encodings for fetched access tokens.",
      "oneOf": [
        {
          "description": "Unix epoch seconds.",
          "type": "string",
          "enum": [
            "unix_seconds"
          ]
        }
      ]
    },
    "AccessTokenFetchConfig": {
      "description": "How an `auth.method: access_token` flow mints a token from a token endpoint.",
      "type": "object",
      "required": [
        "response",
        "url"
      ],
      "properties": {
        "auth": {
          "description": "Optional nested auth applied to the token request itself.",
          "anyOf": [
            {
              "$ref": "#/definitions/AuthConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "method": {
          "description": "HTTP method used for the token fetch request.",
          "default": "GET",
          "allOf": [
            {
              "$ref": "#/definitions/HttpMethod"
            }
          ]
        },
        "prepare": {
          "description": "Header/query bindings applied before the token request is signed/sent.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/HmacPrepareBinding"
          }
        },
        "response": {
          "description": "How to extract the token and expiry from the token endpoint response.",
          "allOf": [
            {
              "$ref": "#/definitions/AccessTokenResponseConfig"
            }
          ]
        },
        "url": {
          "description": "Token endpoint URL.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "AccessTokenInjectConfig": {
      "description": "Destination and rendering template for a fetched access token.",
      "type": "object",
      "required": [
        "target",
        "template"
      ],
      "properties": {
        "target": {
          "description": "Header/query location that receives the rendered token.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacTarget"
            }
          ]
        },
        "template": {
          "description": "Output template. Supported token is `{token}`.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "AccessTokenResponseConfig": {
      "description": "JSON extraction and cache semantics for a fetched access token.",
      "type": "object",
      "required": [
        "token_json_pointer"
      ],
      "properties": {
        "expires_at_format": {
          "description": "Encoding of the absolute expiry value.",
          "default": "unix_seconds",
          "allOf": [
            {
              "$ref": "#/definitions/AccessTokenExpiryFormat"
            }
          ]
        },
        "expires_at_json_pointer": {
          "description": "JSON Pointer selecting an absolute expiry timestamp.",
          "type": [
            "string",
            "null"
          ]
        },
        "expires_in_json_pointer": {
          "description": "JSON Pointer selecting a relative `expires_in` lifetime in seconds.",
          "type": [
            "string",
            "null"
          ]
        },
        "refresh_skew_seconds": {
          "description": "Seconds of safety margin subtracted before a cached token is treated as expired and refreshed.",
          "default": 60,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "token_json_pointer": {
          "description": "JSON Pointer selecting the access token string.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "AccountingMode": {
      "description": "How volume tier counters are scoped.",
      "oneOf": [
        {
          "description": "All agents share one counter. The Foundation's upstream quota is consumed collectively.",
          "type": "string",
          "enum": [
            "pooled"
          ]
        },
        {
          "description": "Each wallet address has its own counter. Volume discounts are per-agent.",
          "type": "string",
          "enum": [
            "per_agent"
          ]
        }
      ]
    },
    "ApiCategory": {
      "type": "string",
      "enum": [
        "ai_ml",
        "cloud",
        "compute",
        "data",
        "devtools",
        "finance",
        "identity",
        "maps",
        "media",
        "messaging",
        "other",
        "productivity",
        "search",
        "security",
        "shopping",
        "storage",
        "translation"
      ]
    },
    "AuthConfig": {
      "description": "How the proxy injects upstream API credentials after payment succeeds. All secret values are resolved from environment variables at runtime.",
      "oneOf": [
        {
          "description": "Inject as a query parameter (e.g. `?key=API_KEY`).",
          "type": "object",
          "required": [
            "key",
            "method",
            "value_from_env"
          ],
          "properties": {
            "key": {
              "description": "Query parameter name (e.g. \"key\").",
              "type": "string"
            },
            "method": {
              "type": "string",
              "enum": [
                "query_param"
              ]
            },
            "value_from_env": {
              "description": "Environment variable holding the value.",
              "type": "string"
            }
          }
        },
        {
          "description": "Inject as an HTTP header (e.g. `Authorization: Bearer TOKEN`).",
          "type": "object",
          "required": [
            "key",
            "method",
            "value_from_env"
          ],
          "properties": {
            "key": {
              "description": "Header name (e.g. \"Authorization\").",
              "type": "string"
            },
            "method": {
              "type": "string",
              "enum": [
                "header"
              ]
            },
            "prefix": {
              "description": "Optional prefix (e.g. \"Bearer \").",
              "type": [
                "string",
                "null"
              ]
            },
            "value_from_env": {
              "description": "Environment variable holding the value.",
              "type": "string"
            }
          }
        },
        {
          "description": "Generic HMAC request signing.",
          "type": "object",
          "required": [
            "algorithm",
            "canonical",
            "method",
            "secret_from_env",
            "signature"
          ],
          "properties": {
            "algorithm": {
              "description": "HMAC hash algorithm.",
              "allOf": [
                {
                  "$ref": "#/definitions/HmacAlgorithm"
                }
              ]
            },
            "canonical": {
              "description": "Canonical string construction rules.",
              "allOf": [
                {
                  "$ref": "#/definitions/HmacCanonicalConfig"
                }
              ]
            },
            "key_id_from_env": {
              "description": "Optional env var containing a public key identifier used by the signature destination template.",
              "type": [
                "string",
                "null"
              ]
            },
            "method": {
              "type": "string",
              "enum": [
                "hmac"
              ]
            },
            "prepare": {
              "description": "Header/query bindings to apply before canonicalization.",
              "type": "array",
              "items": {
                "$ref": "#/definitions/HmacPrepareBinding"
              }
            },
            "secret_from_env": {
              "description": "Env var containing the raw HMAC secret key.",
              "type": "string"
            },
            "secret_suffix": {
              "description": "Optional suffix appended to the resolved secret before signing.",
              "type": [
                "string",
                "null"
              ]
            },
            "signature": {
              "description": "Signature output encoding and destination.",
              "allOf": [
                {
                  "$ref": "#/definitions/HmacSignatureConfig"
                }
              ]
            }
          }
        },
        {
          "description": "Fetch and cache an access token with a nested upstream request, then inject the token into the paid upstream call.",
          "type": "object",
          "required": [
            "fetch",
            "inject",
            "method"
          ],
          "properties": {
            "fetch": {
              "description": "How to mint and cache the access token.",
              "allOf": [
                {
                  "$ref": "#/definitions/AccessTokenFetchConfig"
                }
              ]
            },
            "inject": {
              "description": "Where the fetched token is written on the paid upstream request.",
              "allOf": [
                {
                  "$ref": "#/definitions/AccessTokenInjectConfig"
                }
              ]
            },
            "method": {
              "type": "string",
              "enum": [
                "access_token"
              ]
            },
            "prepare": {
              "description": "Header/query bindings applied to the paid upstream request before the fetched token is injected.",
              "type": "array",
              "items": {
                "$ref": "#/definitions/HmacPrepareBinding"
              }
            }
          }
        },
        {
          "description": "OAuth2 — fetch access token and inject as `Authorization: Bearer`.",
          "type": "object",
          "required": [
            "method",
            "token_url"
          ],
          "properties": {
            "client_id_from_env": {
              "description": "Env var for client_id (for client_credentials grant).",
              "type": [
                "string",
                "null"
              ]
            },
            "client_secret_from_env": {
              "description": "Env var for client_secret (for client_credentials grant).",
              "type": [
                "string",
                "null"
              ]
            },
            "headers": {
              "description": "Extra headers to inject, each value resolved from an env var.",
              "type": "object",
              "additionalProperties": {
                "$ref": "#/definitions/EnvRef"
              }
            },
            "method": {
              "type": "string",
              "enum": [
                "oauth2"
              ]
            },
            "scopes": {
              "description": "OAuth2 scopes to request.",
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "token_url": {
              "description": "Token endpoint URL (e.g. `https://oauth2.googleapis.com/token`). Special value `\"gcp_metadata\"` uses the GCP metadata server.",
              "type": "string"
            }
          }
        }
      ]
    },
    "BillingPeriod": {
      "type": "string",
      "enum": [
        "per_second",
        "per_hour",
        "per_day",
        "per_month"
      ]
    },
    "BillingUnit": {
      "type": "string",
      "enum": [
        "tokens",
        "characters",
        "requests",
        "minutes",
        "hours",
        "seconds",
        "pages",
        "documents",
        "invocations",
        "bytes",
        "GiB",
        "TiB",
        "vCPU",
        "quota_units",
        "instances"
      ]
    },
    "CompareOp": {
      "type": "string",
      "enum": [
        "<=",
        "<",
        ">=",
        ">",
        "=="
      ]
    },
    "Endpoint": {
      "type": "object",
      "required": [
        "method",
        "path"
      ],
      "properties": {
        "description": {
          "type": [
            "string",
            "null"
          ]
        },
        "metering": {
          "description": "Billing config for this endpoint. None = free / not billed.",
          "anyOf": [
            {
              "$ref": "#/definitions/Metering"
            },
            {
              "type": "null"
            }
          ]
        },
        "method": {
          "$ref": "#/definitions/HttpMethod"
        },
        "path": {
          "type": "string"
        },
        "resource": {
          "description": "Resource group (e.g. \"models\", \"tunedModels\", \"files\").",
          "type": [
            "string",
            "null"
          ]
        },
        "routing": {
          "description": "Per-endpoint routing override. If set, takes precedence over the top-level `routing` config for this endpoint.",
          "anyOf": [
            {
              "$ref": "#/definitions/RoutingConfig"
            },
            {
              "type": "null"
            }
          ]
        },
        "subscription": {
          "description": "Recurring subscription gating for this endpoint. Mutually exclusive with `metering` per the v0 design (one endpoint exposes either a per-call charge OR a recurring subscription, never both).",
          "anyOf": [
            {
              "$ref": "#/definitions/SubscriptionEndpoint"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "EnvRef": {
      "description": "A value resolved from an environment variable.",
      "type": "object",
      "required": [
        "from_env"
      ],
      "properties": {
        "from_env": {
          "type": "string"
        }
      }
    },
    "FreeTier": {
      "type": "object",
      "properties": {
        "amount": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "period": {
          "anyOf": [
            {
              "$ref": "#/definitions/BillingPeriod"
            },
            {
              "type": "null"
            }
          ]
        },
        "unit": {
          "anyOf": [
            {
              "$ref": "#/definitions/BillingUnit"
            },
            {
              "type": "null"
            }
          ]
        }
      }
    },
    "HmacAlgorithm": {
      "oneOf": [
        {
          "description": "HMAC-SHA1.",
          "type": "string",
          "enum": [
            "sha1"
          ]
        },
        {
          "description": "HMAC-SHA256.",
          "type": "string",
          "enum": [
            "sha256"
          ]
        },
        {
          "description": "HMAC-SHA512.",
          "type": "string",
          "enum": [
            "sha512"
          ]
        }
      ]
    },
    "HmacCanonicalComponent": {
      "description": "One piece of the canonical string used as the HMAC message.",
      "oneOf": [
        {
          "description": "The HTTP method, for example `GET` or `POST`.",
          "type": "object",
          "required": [
            "from"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "method"
              ]
            }
          }
        },
        {
          "description": "The final upstream path after any path rewrites.",
          "type": "object",
          "required": [
            "from"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "path"
              ]
            }
          }
        },
        {
          "description": "The final upstream query string.",
          "type": "object",
          "required": [
            "from",
            "style"
          ],
          "properties": {
            "encoding": {
              "description": "Optional encoding applied after the query string is rendered.",
              "default": "none",
              "allOf": [
                {
                  "$ref": "#/definitions/HmacStringEncoding"
                }
              ]
            },
            "from": {
              "type": "string",
              "enum": [
                "query"
              ]
            },
            "style": {
              "$ref": "#/definitions/HmacQueryStyle"
            }
          }
        },
        {
          "description": "A single header value, looked up case-insensitively.",
          "type": "object",
          "required": [
            "from",
            "name"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "header"
              ]
            },
            "name": {
              "type": "string"
            }
          }
        },
        {
          "description": "A rendered group of headers, typically for schemes that sign `name:value` lines in a fixed order.",
          "type": "object",
          "required": [
            "format",
            "from",
            "join_with",
            "names"
          ],
          "properties": {
            "format": {
              "type": "string"
            },
            "from": {
              "type": "string",
              "enum": [
                "headers"
              ]
            },
            "join_with": {
              "type": "string"
            },
            "names": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          }
        },
        {
          "description": "A literal string inserted verbatim.",
          "type": "object",
          "required": [
            "from",
            "value"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "literal"
              ]
            },
            "value": {
              "type": "string"
            }
          }
        }
      ]
    },
    "HmacCanonicalConfig": {
      "description": "Canonical-string construction rules for `auth.method: hmac`.",
      "type": "object",
      "required": [
        "components",
        "join_with"
      ],
      "properties": {
        "components": {
          "description": "Ordered canonical-string components.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/HmacCanonicalComponent"
          }
        },
        "join_with": {
          "description": "Separator inserted between rendered components.",
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "HmacDigestAlgorithm": {
      "description": "Digest algorithms available to `prepare.value.from: body_digest`.",
      "oneOf": [
        {
          "description": "MD5 digest of the raw request body.",
          "type": "string",
          "enum": [
            "md5"
          ]
        },
        {
          "description": "SHA-256 digest of the raw request body.",
          "type": "string",
          "enum": [
            "sha256"
          ]
        },
        {
          "description": "SHA-512 digest of the raw request body.",
          "type": "string",
          "enum": [
            "sha512"
          ]
        }
      ]
    },
    "HmacEncoding": {
      "description": "Output encoding for digests and signatures emitted by `auth.method: hmac`.",
      "oneOf": [
        {
          "description": "Standard RFC 4648 base64 without line wrapping.",
          "type": "string",
          "enum": [
            "base64"
          ]
        },
        {
          "description": "Lowercase hexadecimal.",
          "type": "string",
          "enum": [
            "hex"
          ]
        }
      ]
    },
    "HmacPrepareBinding": {
      "description": "A single pre-sign mutation applied to the upstream request.\n\n`prepare` runs before canonicalization, so these bindings can populate headers or query params that are later referenced by the canonical string.",
      "type": "object",
      "required": [
        "target",
        "value"
      ],
      "properties": {
        "target": {
          "description": "Where to write the derived value.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacTarget"
            }
          ]
        },
        "value": {
          "description": "How the value is produced at request time.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacPrepareValue"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HmacPrepareValue": {
      "description": "Runtime value sources for `prepare` bindings.",
      "oneOf": [
        {
          "description": "Use a literal string.",
          "type": "object",
          "required": [
            "from",
            "value"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "literal"
              ]
            },
            "value": {
              "type": "string"
            }
          }
        },
        {
          "description": "Read the value from an environment variable at request time.",
          "type": "object",
          "required": [
            "from",
            "from_env"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "env"
              ]
            },
            "from_env": {
              "type": "string"
            }
          }
        },
        {
          "description": "Use the final upstream host, including `:port` when present.",
          "type": "object",
          "required": [
            "from"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "upstream_host"
              ]
            }
          }
        },
        {
          "description": "Generate a timestamp at signing time.",
          "type": "object",
          "required": [
            "format",
            "from"
          ],
          "properties": {
            "format": {
              "$ref": "#/definitions/HmacTimestampFormat"
            },
            "from": {
              "type": "string",
              "enum": [
                "timestamp"
              ]
            }
          }
        },
        {
          "description": "Generate a random UUIDv4 string.",
          "type": "object",
          "required": [
            "from"
          ],
          "properties": {
            "from": {
              "type": "string",
              "enum": [
                "uuid_v4"
              ]
            }
          }
        },
        {
          "description": "Generate a lowercase random hex string from the given byte length.",
          "type": "object",
          "required": [
            "bytes",
            "from"
          ],
          "properties": {
            "bytes": {
              "type": "integer",
              "format": "uint16",
              "minimum": 0.0
            },
            "from": {
              "type": "string",
              "enum": [
                "random_hex"
              ]
            }
          }
        },
        {
          "description": "Digest the raw request body and encode the result.",
          "type": "object",
          "required": [
            "algorithm",
            "encoding",
            "from"
          ],
          "properties": {
            "algorithm": {
              "$ref": "#/definitions/HmacDigestAlgorithm"
            },
            "encoding": {
              "$ref": "#/definitions/HmacEncoding"
            },
            "from": {
              "type": "string",
              "enum": [
                "body_digest"
              ]
            }
          }
        }
      ]
    },
    "HmacQueryStyle": {
      "description": "How the final query string should be represented inside the canonical string before signing.",
      "oneOf": [
        {
          "description": "Use the final query string exactly as it appears on the upstream URL, without the leading `?`.",
          "type": "string",
          "enum": [
            "raw"
          ]
        },
        {
          "description": "Sort the final query parameters by name and then value, and join them as `k=v&...`.",
          "type": "string",
          "enum": [
            "sorted_pairs"
          ]
        }
      ]
    },
    "HmacSignatureConfig": {
      "description": "Controls how the computed HMAC signature is encoded and where it is written on the upstream request.",
      "type": "object",
      "required": [
        "destination",
        "encoding"
      ],
      "properties": {
        "destination": {
          "description": "Signature destination and rendering template.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacSignatureDestination"
            }
          ]
        },
        "encoding": {
          "description": "Encoding applied to the raw HMAC bytes.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacEncoding"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HmacSignatureDestination": {
      "description": "Where the rendered signature is emitted after canonicalization.",
      "type": "object",
      "required": [
        "name",
        "template",
        "type"
      ],
      "properties": {
        "name": {
          "description": "Header/query parameter name that receives the rendered signature.",
          "type": "string"
        },
        "template": {
          "description": "Output template. Supported tokens are `{signature}` and `{key_id}`.",
          "type": "string"
        },
        "type": {
          "description": "Whether the signature is sent as a header or query param.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacTargetType"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HmacStringEncoding": {
      "description": "Extra text encodings applied while rendering canonical HMAC components.",
      "oneOf": [
        {
          "description": "Leave the rendered value unchanged.",
          "type": "string",
          "enum": [
            "none"
          ]
        },
        {
          "description": "Percent-encode the rendered value using RFC 3986 rules.",
          "type": "string",
          "enum": [
            "percent_rfc3986"
          ]
        }
      ]
    },
    "HmacTarget": {
      "description": "A writable location on the upstream request used by HMAC prepare/signature steps.",
      "type": "object",
      "required": [
        "name",
        "type"
      ],
      "properties": {
        "name": {
          "description": "Header name or query parameter name.",
          "type": "string"
        },
        "type": {
          "description": "Whether the target is a header or query param.",
          "allOf": [
            {
              "$ref": "#/definitions/HmacTargetType"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "HmacTargetType": {
      "description": "Where an HMAC-derived value should be written on the upstream request.",
      "oneOf": [
        {
          "description": "An HTTP request header.",
          "type": "string",
          "enum": [
            "header"
          ]
        },
        {
          "description": "A query-string parameter on the final upstream URL.",
          "type": "string",
          "enum": [
            "query_param"
          ]
        }
      ]
    },
    "HmacTimestampFormat": {
      "description": "Timestamp encodings available to `prepare.value.from: timestamp`.",
      "oneOf": [
        {
          "description": "RFC 1123 timestamp in GMT, for example `Wed, 26 Aug 2015 17:01:00 GMT`.",
          "type": "string",
          "enum": [
            "rfc_1123_gmt"
          ]
        },
        {
          "description": "ISO 8601 UTC timestamp, for example `2019-04-18T08:32:31Z`.",
          "type": "string",
          "enum": [
            "iso_8601_zulu"
          ]
        },
        {
          "description": "Unix epoch seconds.",
          "type": "string",
          "enum": [
            "unix_seconds"
          ]
        }
      ]
    },
    "HttpMethod": {
      "type": "string",
      "enum": [
        "GET",
        "POST",
        "PUT",
        "PATCH",
        "DELETE"
      ]
    },
    "MeterCondition": {
      "description": "A condition the proxy can evaluate against request properties.",
      "oneOf": [
        {
          "description": "Total input token count (from request body or content-length estimation).",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "input_tokens"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Total input character count.",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "input_characters"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Context window size (prompt + history tokens).",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "context_length"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Request body size in bytes.",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "body_size"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Audio/video duration in seconds.",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "duration_seconds"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Number of items in a batch request.",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "batch_size"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        },
        {
          "description": "Image resolution (width * height pixels).",
          "type": "object",
          "required": [
            "field",
            "op",
            "value"
          ],
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "image_pixels"
              ]
            },
            "op": {
              "$ref": "#/definitions/CompareOp"
            },
            "value": {
              "type": "integer",
              "format": "uint64",
              "minimum": 0.0
            }
          }
        }
      ]
    },
    "MeterDimension": {
      "type": "object",
      "required": [
        "direction",
        "scale",
        "tiers",
        "unit"
      ],
      "properties": {
        "direction": {
          "$ref": "#/definitions/MeterDirection"
        },
        "period": {
          "description": "Billing period when the unit is time-derived (e.g. GiB billed per_month).",
          "anyOf": [
            {
              "$ref": "#/definitions/BillingPeriod"
            },
            {
              "type": "null"
            }
          ]
        },
        "scale": {
          "description": "Price is quoted per `scale` units. e.g. scale=1000000 → \"per 1M tokens\".",
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "tiers": {
          "description": "Volume tiers. Evaluated in order — first matching tier applies.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/PriceTier"
          }
        },
        "unit": {
          "$ref": "#/definitions/BillingUnit"
        }
      }
    },
    "MeterDirection": {
      "type": "string",
      "enum": [
        "input",
        "output",
        "usage",
        "storage"
      ]
    },
    "MeterVariant": {
      "description": "A variant represents a pricing path selected by a request parameter. The proxy extracts `param` from the URL path or request body and matches it against `value`.",
      "type": "object",
      "required": [
        "dimensions",
        "param",
        "value"
      ],
      "properties": {
        "dimensions": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/MeterDimension"
          }
        },
        "param": {
          "description": "The parameter to match against (e.g. \"model\", \"voice\").",
          "type": "string"
        },
        "value": {
          "description": "The value to match (e.g. \"gemini-2.5-pro\", \"chirp-3-hd\").",
          "type": "string"
        }
      }
    },
    "Metering": {
      "type": "object",
      "properties": {
        "dimensions": {
          "description": "Direct pricing dimensions (when there's a single pricing model).",
          "type": "array",
          "items": {
            "$ref": "#/definitions/MeterDimension"
          }
        },
        "min_usd": {
          "description": "Minimum settled amount (USD) for usage-metered `x402-upto`. The tier price is the *ceiling* the client authorizes; absent a real usage meter, the operator settles a voucher for this `min` (clamped to the ceiling) on a successful serve, refunding the rest. `None` settles the full ceiling.",
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "schemes": {
          "description": "Per-call schemes this endpoint accepts. `None` defaults to charge-only (`[mpp-charge]`); session and the x402 schemes must be listed explicitly.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "$ref": "#/definitions/Scheme"
          }
        },
        "sku_tiers": {
          "description": "Maps Platform SKU tiers.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/SkuTier"
          }
        },
        "splits": {
          "description": "Payment splits — how the charge is distributed to named recipients. Applied to all tiers unless overridden at the tier level.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/SplitRule"
          }
        },
        "variants": {
          "description": "Variant-specific pricing (e.g. different models have different costs). The proxy matches the variant using a path/body parameter.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/MeterVariant"
          }
        }
      }
    },
    "OperatorConfig": {
      "description": "Operator-level configuration for a proxy instance. Controls signing, payment recipient, and currency.",
      "type": "object",
      "properties": {
        "challenge_binding_secret": {
          "description": "HMAC secret used by the MPP `subscription` + `authenticate` handlers to bind each challenge to its server (the secret signs the nonce so verify can reject tampered or replayed challenges without per-challenge server state). Must be stable across restarts — rotating it invalidates every outstanding session token. Required when any endpoint declares a `subscription:` block.\n\nGenerate one with `openssl rand -hex 32`.",
          "type": [
            "string",
            "null"
          ]
        },
        "currencies": {
          "description": "Payment currencies grouped by unit, e.g. `{ usd: [USDC, USDT, CASH] }`. When present, charge endpoints advertise one challenge per listed currency.",
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "fee_payer": {
          "description": "Whether the operator sponsors transaction fees.",
          "default": false,
          "type": "boolean"
        },
        "network": {
          "description": "Solana network (mainnet, devnet, localnet).",
          "type": [
            "string",
            "null"
          ]
        },
        "realm": {
          "description": "Realm string surfaced in `WWW-Authenticate: Payment realm=\"…\"` for subscription + authenticate challenges. Pick a stable label for your service — clients tag cached SIWMPP tokens by realm. Required when any endpoint declares a `subscription:` block.",
          "type": [
            "string",
            "null"
          ]
        },
        "recipient": {
          "description": "Payment recipient wallet address (base58). Overrides --recipient CLI flag.",
          "type": [
            "string",
            "null"
          ]
        },
        "rpc_url": {
          "description": "Solana RPC URL. Overrides --rpc-url CLI flag.",
          "type": [
            "string",
            "null"
          ]
        },
        "signer": {
          "description": "Signing backend for fee sponsorship and settlement.",
          "anyOf": [
            {
              "$ref": "#/definitions/SignerConfig"
            },
            {
              "type": "null"
            }
          ]
        }
      },
      "additionalProperties": false
    },
    "PathRewrite": {
      "description": "A path rewrite rule — matches a prefix pattern in the request path and substitutes `{placeholder}` segments with an env var value.\n\nExample: prefix `v3/projects/{projectId}` with env `GCP_PROJECT=gateway-402` rewrites `/v3/projects/any-value/locations/global:translateText` to      `/v3/projects/gateway-402/locations/global:translateText`.",
      "type": "object",
      "required": [
        "env",
        "prefix"
      ],
      "properties": {
        "env": {
          "description": "Environment variable whose value replaces the placeholder.",
          "type": "string"
        },
        "prefix": {
          "description": "Path prefix template with a `{placeholder}` (e.g. `v3/projects/{projectId}`).",
          "type": "string"
        }
      }
    },
    "PriceTier": {
      "description": "A volume-based price tier. `up_to: None` means \"and above\" (final tier).",
      "type": "object",
      "required": [
        "price_usd"
      ],
      "properties": {
        "condition": {
          "description": "Machine-readable condition that must hold for this tier to apply.",
          "anyOf": [
            {
              "$ref": "#/definitions/MeterCondition"
            },
            {
              "type": "null"
            }
          ]
        },
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "price_usd": {
          "type": "number",
          "format": "double"
        },
        "splits": {
          "description": "Per-tier split overrides. If present, these replace the metering-level splits.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/SplitRule"
          }
        },
        "up_to": {
          "description": "Volume ceiling for this tier. None = unlimited (catch-all).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        }
      }
    },
    "QuotaSpec": {
      "type": "object",
      "properties": {
        "notes": {
          "type": [
            "string",
            "null"
          ]
        },
        "per_user_requests_per_second": {
          "description": "Per-user rate limit (requests per second per wallet).",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "quota_units_per_day": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "requests_per_100_seconds": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "requests_per_day": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "requests_per_minute": {
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        }
      }
    },
    "RecipientAlias": {
      "description": "Named recipient alias declared at the API spec level. Used in split rules to reference wallet accounts by name.",
      "type": "object",
      "required": [
        "account"
      ],
      "properties": {
        "account": {
          "description": "Wallet account — literal base58 pubkey or `${VAR}` for runtime resolution. Runtime variables are resolved from request query parameters.",
          "type": "string"
        },
        "label": {
          "description": "Human-readable label (shown in debugger UI and receipts).",
          "type": [
            "string",
            "null"
          ]
        }
      }
    },
    "RoutingConfig": {
      "description": "How a request is handled after payment verification.\n\n```yaml # Proxy — forward to an upstream API routing: type: proxy url: https://generativelanguage.googleapis.com/ auth: method: query_param key: \"key\" value_from_env: GOOGLE_API_KEY\n\n# Respond — return 200 with verified signature (no upstream) routing: type: respond ```",
      "oneOf": [
        {
          "description": "Forward request to an upstream API.",
          "type": "object",
          "required": [
            "type",
            "url"
          ],
          "properties": {
            "auth": {
              "description": "How the proxy injects upstream API credentials after payment.",
              "anyOf": [
                {
                  "$ref": "#/definitions/AuthConfig"
                },
                {
                  "type": "null"
                }
              ]
            },
            "path_rewrites": {
              "description": "Optional path segments prepended to the request path. Each segment's value is resolved from an environment variable.\n\n```yaml routing: type: proxy url: https://translation.googleapis.com path_rewrites: - prefix: \"v3/projects/{projectId}\" env: GOOGLE_PROJECT_ID ```\n\nGiven `GOOGLE_PROJECT_ID=my-proj`, a request to `/v3/projects/any-value/locations/global:translateText` is rewritten to `https://translation.googleapis.com/v3/projects/my-proj/locations/global:translateText`.",
              "type": "array",
              "items": {
                "$ref": "#/definitions/PathRewrite"
              }
            },
            "type": {
              "type": "string",
              "enum": [
                "proxy"
              ]
            },
            "url": {
              "description": "Upstream base URL (e.g. `https://generativelanguage.googleapis.com/`).",
              "type": "string"
            }
          }
        },
        {
          "description": "Respond directly — return 200 with the verified payment signature, or 401 if the request was denied. No upstream call.",
          "type": "object",
          "required": [
            "type"
          ],
          "properties": {
            "type": {
              "type": "string",
              "enum": [
                "respond"
              ]
            }
          }
        }
      ]
    },
    "Scheme": {
      "description": "A per-call payment scheme a metered endpoint can accept. The endpoint opts into specific schemes via [`Metering::schemes`]; the gate advertises a 402 challenge for each accepted scheme that the server has a backend for, and verifies a presented credential against the matching scheme.\n\n`subscription` is intentionally absent — it is a distinct recurring-billing model declared via [`Endpoint::subscription`], mutually exclusive with per-call metering.",
      "oneOf": [
        {
          "description": "MPP `intent=charge` — one settled credential per request.",
          "type": "string",
          "enum": [
            "mpp-charge"
          ]
        },
        {
          "description": "MPP `intent=session` — open a channel, stream off-chain vouchers.",
          "type": "string",
          "enum": [
            "mpp-session"
          ]
        },
        {
          "description": "x402 `exact` — pay an exact amount per request.",
          "type": "string",
          "enum": [
            "x402-exact"
          ]
        },
        {
          "description": "x402 `upto` — usage-based, operator settles a voucher up to a cap.",
          "type": "string",
          "enum": [
            "x402-upto"
          ]
        },
        {
          "description": "x402 `batch-settlement` — high-throughput batched channel settlement.",
          "type": "string",
          "enum": [
            "x402-batch-settlement"
          ]
        }
      ]
    },
    "SessionPullVoucherStrategy": {
      "type": "string",
      "enum": [
        "disabled",
        "client_voucher",
        "operated_voucher"
      ]
    },
    "SessionSpec": {
      "description": "Session channel parameters — emitted by the server when the API is configured for MPP session payments (off-chain vouchers).",
      "type": "object",
      "required": [
        "cap_usdc"
      ],
      "properties": {
        "batch_open_interval_ms": {
          "description": "Legacy pull-mode channel-open batch flush interval in milliseconds.\n\nDefaults to `400` when omitted.",
          "default": 400,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "cap_usdc": {
          "description": "Default channel cap offered to clients (USDC, human-readable). Clients may request a lower cap; the server will not exceed this.",
          "type": "number",
          "format": "double"
        },
        "close_delay_ms": {
          "description": "Idle delay before the operator closes and settles the payment channel.\n\nDefaults to `15000` when omitted. Set to `0` to disable automatic close.",
          "default": 15000,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "min_voucher_delta": {
          "description": "Minimum voucher increment (base units = µUSDC). Prevents spam vouchers smaller than one API call's cost.",
          "default": 0,
          "type": "integer",
          "format": "uint64",
          "minimum": 0.0
        },
        "modes": {
          "description": "Session modes this server accepts.\n\nAllowed values: `\"push\"` (payment channel, client-funded) and/or `\"pull\"` (SPL token delegation, operator fee-pays the approve tx).\n\nDefaults to `[\"push\"]` when omitted.\n\nExample YAML: ```yaml session: cap_usdc: 10.0 modes: [push, pull] ```",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "pull_voucher_strategy": {
          "description": "Pull voucher strategy.\n\nThis disambiguates pull-mode sessions: - `disabled`: do not advertise or accept pull sessions. - `client_voucher`: client signs vouchers; no multi-delegate setup. - `operated_voucher`: operator signs vouchers after metering and uses multi-delegate setup for delegated token movement.",
          "default": "disabled",
          "allOf": [
            {
              "$ref": "#/definitions/SessionPullVoucherStrategy"
            }
          ]
        },
        "splits": {
          "description": "Channel settlement splits. Session splits are percentage-only and are converted to basis points for the payment channel distribution.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/SplitRule"
          }
        }
      }
    },
    "SignerConfig": {
      "description": "Signing backend configuration.\n\nTells the server how to load the wallet that co-signs as `fee_payer`. When `operator.fee_payer: true` is set in the YAML, exactly one of these variants must be configured (or the server must be started in `--sandbox` mode, which auto-loads a localnet ephemeral).",
      "oneOf": [
        {
          "description": "GCP Cloud KMS — Ed25519 HSM key. Private key never leaves the HSM. Recommended for production. Requires the `gcp_kms` build feature.",
          "type": "object",
          "required": [
            "backend",
            "key_name",
            "pubkey"
          ],
          "properties": {
            "backend": {
              "type": "string",
              "enum": [
                "gcp-kms"
              ]
            },
            "key_name": {
              "description": "Full KMS key version resource name.",
              "type": "string"
            },
            "pubkey": {
              "description": "Solana public key (base58) derived from the KMS key.",
              "type": "string"
            }
          }
        },
        {
          "description": "Named account from `~/.config/pay/accounts.yml`. Loaded via the regular keystore path — for `apple-keychain`/`gnome-keyring`/ `windows-hello`/`1password` entries this triggers the OS auth prompt **once at server startup** (not per-payment). For `ephemeral` entries no prompt fires.",
          "type": "object",
          "required": [
            "backend",
            "name"
          ],
          "properties": {
            "backend": {
              "type": "string",
              "enum": [
                "account"
              ]
            },
            "name": {
              "description": "Account name as it appears under `accounts:` in accounts.yml.",
              "type": "string"
            }
          }
        },
        {
          "description": "Inline keypair file on disk (Solana CLI's standard JSON format — a 64-byte u8 array). Bypasses the keystore entirely. Useful for dev/CI machines where the wallet doesn't need OS-level protection.",
          "type": "object",
          "required": [
            "backend",
            "path"
          ],
          "properties": {
            "backend": {
              "type": "string",
              "enum": [
                "file"
              ]
            },
            "path": {
              "description": "Path to the keypair JSON file. `~` is expanded.",
              "type": "string"
            }
          }
        }
      ]
    },
    "SkuLevel": {
      "type": "string",
      "enum": [
        "essentials",
        "pro",
        "enterprise"
      ]
    },
    "SkuTier": {
      "description": "Maps Platform SKU tier.",
      "type": "object",
      "required": [
        "level",
        "sku"
      ],
      "properties": {
        "level": {
          "$ref": "#/definitions/SkuLevel"
        },
        "sku": {
          "type": "string"
        }
      }
    },
    "SplitRule": {
      "description": "A single split directive — either a fixed USD amount or a percentage of the total.\n\nExactly one of `amount` or `percent` must be set.\n\n**Semantics:** - `amount`: fixed USD value deducted from the charge. - `percent`: percentage of the **original total charge** (not the remaining balance).\n\nThis means reordering splits does not change anyone's payout — both fixed and percentage splits reference the same original total, following the standard payment processing model (Stripe, Adyen).",
      "type": "object",
      "required": [
        "recipient"
      ],
      "properties": {
        "amount": {
          "description": "Fixed USD amount to send to this recipient.",
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "memo": {
          "description": "Human-readable memo (shown in debugger + on-chain).",
          "type": [
            "string",
            "null"
          ]
        },
        "percent": {
          "description": "Percentage of the original total charge to send to this recipient.",
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "recipient": {
          "description": "Reference to a named recipient alias (key in `ApiSpec.recipients`).",
          "type": "string"
        }
      }
    },
    "SubscriptionEndpoint": {
      "description": "Server-side subscription pricing declaration for an endpoint. Maps to the `subscription` payment intent (`draft-solana-subscription-00`) when the payment middleware emits a 402 challenge.\n\nThe shape is deliberately small: it captures only what a developer can reasonably write by hand. The on-chain `Plan` PDA is published separately by `pay server plans publish`, which writes its address back into `plan_id` once it exists.",
      "type": "object",
      "required": [
        "currency",
        "period"
      ],
      "properties": {
        "amount_base_units": {
          "description": "Explicit base-unit override. Wins over `price_usd` when both are set; useful for pricing in a non-pegged token where USD conversion would be misleading.",
          "type": [
            "string",
            "null"
          ]
        },
        "currency": {
          "description": "Stablecoin symbol (e.g. `\"USDC\"`) or mint address (base58). Resolved against the operator's network at challenge time.",
          "type": "string"
        },
        "expires_at": {
          "description": "HTTP-layer subscription expiry. Mirrors the spec's optional `subscriptionExpires` field; after this timestamp the server refuses to renew and serves a fresh challenge.",
          "type": [
            "string",
            "null"
          ]
        },
        "free_trial_days": {
          "description": "Free-trial length in days. Reserved for a future iteration — `pay server` ignores this in v0 and surfaces a warning.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint32",
          "minimum": 0.0
        },
        "period": {
          "description": "Billing period, written as a count + unit (`\"30d\"` or `\"2w\"`). The Solana profile of the subscription intent rejects `month`, so only `d` (day) and `w` (week) suffixes are accepted at parse time.",
          "type": "string"
        },
        "plan_bump": {
          "description": "Plan PDA bump seed. Saves the on-chain `Subscribe` instruction a `find_program_address` call. Written by `pay server plans publish`.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint8",
          "minimum": 0.0
        },
        "plan_created_at": {
          "description": "Plan's on-chain `created_at` unix timestamp. Set by the program when the Plan account is created; written into the YAML after `pay server plans publish` broadcasts and reads back the new account. Must be passed verbatim into `SubscribeData` or the program rejects with a terms mismatch.",
          "type": [
            "integer",
            "null"
          ],
          "format": "int64"
        },
        "plan_id": {
          "description": "Base58 of the on-chain `Plan` PDA (the spec's `externalId`). Empty at author time; populated in place by `pay server plans publish`.",
          "type": [
            "string",
            "null"
          ]
        },
        "plan_id_numeric": {
          "description": "The numeric `plan_id` (u64) the on-chain program reads from `SubscribeData`. The string `plan_id` above is the PDA derived from this number + the operator wallet. `pay server plans publish` writes both at the same time.",
          "type": [
            "integer",
            "null"
          ],
          "format": "uint64",
          "minimum": 0.0
        },
        "price_usd": {
          "description": "Per-period price in USD. Converted to mint base units at challenge time using the configured mint's decimals.",
          "type": [
            "number",
            "null"
          ],
          "format": "double"
        },
        "puller": {
          "description": "Server's puller pubkey. Defaults to the operator-level account if unset.",
          "type": [
            "string",
            "null"
          ]
        },
        "recipient": {
          "description": "Recipient wallet for the per-period charge. Must appear in the on-chain `plan.destinations` whitelist. Defaults to the operator-level recipient when unset.",
          "type": [
            "string",
            "null"
          ]
        }
      }
    }
  }
}
