{
  "openapi": "3.1.0",
  "info": {
    "title": "Toolshed — tools for agents",
    "version": "2026-09-29",
    "summary": "Hosted file conversions an agent can call over HTTP with nothing installed.",
    "description": "Post a file to a hosted tool and read the converted file back — nothing to install. Where we do not host the job, the entry names the tool worth reaching for and what bites about it. We prefer the plain deterministic tool wherever one works, and a model only where the answer is a judgment call.\n\nEvery hosted call is a paid call. There is no account and no key: a call with no payment answers HTTP 402 with an x402 envelope, and paying it is the whole authentication story. You are charged only for conversions that are actually served.\n\nThe same catalog is published as https://toolshed.lemon-agent.dev/catalog.json, https://toolshed.lemon-agent.dev/llms.txt and https://toolshed.lemon-agent.dev/llms-full.txt.",
    "x-guidance": "Toolshed sells 19 hosted file conversions over plain HTTP: POST the raw input as the request body of /convert/{id} — no JSON wrapper, no multipart, 256 KB cap — and the converted file comes back as the response body of the same request. Nothing is queued: there is no job id, nothing to poll and no expiring link. GET /check is free, touches no store and lists every conversion with its id, price and tier, so you can find the id you need and what it costs without spending anything. There is no account, no API key, no signup and no minimum. Every paid route answers an unpaid call with HTTP 402 carrying the full x402 quote — the v1 envelope in the body, the v2 envelope base64 in the PAYMENT-REQUIRED header — before the body is read or converted, so probing a price costs nothing and settles nothing. Prices are $0.002–$0.006 in USDC via x402, stated per tool in this document, in catalog.json and in the 402 itself; the quote you were handed is the amount that settles, because both come from one catalog. You are charged only for a conversion that is actually served — a 400, 413, 429 or 503 settles nothing.",
    "contact": {
      "name": "Lemon",
      "email": "support@lemon-agent.dev",
      "url": "https://lemon-agent.dev"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-Proprietary"
    }
  },
  "servers": [
    {
      "url": "https://toolshed.lemon-agent.dev",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "catalog",
      "description": "What this service can convert."
    },
    {
      "name": "convert",
      "description": "The hosted conversions. Priced per call in USDC via x402."
    }
  ],
  "paths": {
    "/check": {
      "get": {
        "operationId": "check",
        "summary": "List the conversions available for a pair.",
        "description": "Field-bound match: `from` is tested against the \"have\" side only, `to` against the \"need\" side only. Each parameter matches on a case-insensitive substring of the prose name OR on an exact alias, so extensions and MIME types work with or without a leading dot — `md`, `.md`, `text/markdown`. With no parameters the answer is every hosted tool. Touches no store, so it is exempt from every rate limit and costs nothing.",
        "tags": [
          "catalog"
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "What you have. Max 64 characters.",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "examples": {
              "prose": {
                "value": "markdown"
              },
              "extension": {
                "value": "md"
              },
              "dotted": {
                "value": ".md"
              },
              "mime": {
                "value": "text/markdown"
              }
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "What you need. Max 64 characters.",
            "schema": {
              "type": "string",
              "maxLength": 64
            },
            "examples": {
              "prose": {
                "value": "html"
              },
              "mime": {
                "value": "text/html"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The matching entries. An empty `matches` array is a valid answer, not an error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "query",
                    "matches"
                  ],
                  "properties": {
                    "query": {
                      "type": "object",
                      "properties": {
                        "from": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "to": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    },
                    "matches": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "x",
                          "y",
                          "hosted",
                          "local",
                          "url"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "The id to POST to /convert/{id}."
                          },
                          "x": {
                            "type": "string",
                            "description": "What it takes, in prose."
                          },
                          "y": {
                            "type": "string",
                            "description": "What it produces, in prose."
                          },
                          "hosted": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "Null for a local-only reference — there is no endpoint to call.",
                            "properties": {
                              "path": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "live",
                                  "planned"
                                ]
                              },
                              "free_tier_daily": {
                                "type": "integer",
                                "description": "Free conversions per caller per UTC day, as the Worker enforces it right now. 0 means every call is a paid call."
                              },
                              "price": {
                                "oneOf": [
                                  {
                                    "type": "string",
                                    "enum": [
                                      "free"
                                    ]
                                  },
                                  {
                                    "type": "object",
                                    "properties": {
                                      "amount_usd": {
                                        "type": "number"
                                      },
                                      "scheme": {
                                        "type": "string"
                                      }
                                    }
                                  }
                                ]
                              }
                            }
                          },
                          "local": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "The tool to run yourself instead.",
                            "properties": {
                              "tool": {
                                "type": "string"
                              },
                              "install": {
                                "type": "string"
                              }
                            }
                          },
                          "url": {
                            "type": "string",
                            "format": "uri"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter is longer than 64 characters.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "405": {
            "description": "GET only.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/html-markdown": {
      "post": {
        "operationId": "convert_html_markdown",
        "summary": "Saved HTML page / static HTML file to Markdown",
        "description": "For HTML already on disk, pandoc's reader is exact and fast, and `--wrap=none` keeps the output diff-friendly. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.006/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.006"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.006",
            "amount_atomic": "6000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw Saved HTML page / static HTML file file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted Markdown file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/md-html": {
      "post": {
        "operationId": "convert_md_html",
        "summary": "Markdown to HTML",
        "description": "Markdown to HTML is a solved parse, so the only real questions are which dialect and which extensions. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.004/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.004"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.004",
            "amount_atomic": "4000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw Markdown file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted HTML file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/html": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/json-yaml": {
      "post": {
        "operationId": "convert_json_yaml",
        "summary": "JSON to YAML",
        "description": "mikefarah's yq speaks both formats natively (`yq -P`) and preserves comments through YAML edits, which is the whole reason to use it on real config files. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw JSON file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted YAML file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/yaml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/yaml-json": {
      "post": {
        "operationId": "convert_yaml_json",
        "summary": "YAML to JSON",
        "description": "`yq -o=json` is the local answer, and the direction that bites is this one: YAML is the larger language, so anchors, multi-document streams and unquoted `no`/`yes` all have to land somewhere in JSON. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw YAML file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/csv-json": {
      "post": {
        "operationId": "convert_csv_json",
        "summary": "CSV to JSON",
        "description": "`csvjson data.csv` turns a header row plus records into an array of objects, which is the shape almost everything downstream wants. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw CSV file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/json-csv": {
      "post": {
        "operationId": "convert_json_csv",
        "summary": "JSON array of records to CSV with a header row",
        "description": "`in2csv --format json` is the local answer, and the hosted endpoint is the inverse of our own csv-json: an array of objects in, a header row plus one line per record out, RFC-4180 quoted so commas, quotes and newlines inside values survive. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw JSON array of records file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted CSV with a header row file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/csv-yaml": {
      "post": {
        "operationId": "convert_csv_yaml",
        "summary": "CSV to YAML",
        "description": "`yq -p=csv -o=yaml` does this locally; the hosted endpoint runs the same RFC-4180 parser csv-json uses and dumps block-style YAML, which is the shape you want when a spreadsheet export has to become a config file or a fixture. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw CSV file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted YAML file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/yaml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/yaml-csv": {
      "post": {
        "operationId": "convert_yaml_csv",
        "summary": "YAML list of records to CSV with a header row",
        "description": "`yq -o=csv` locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw YAML list of records file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted CSV with a header row file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/json-ndjson": {
      "post": {
        "operationId": "convert_json_ndjson",
        "summary": "JSON array to NDJSON (newline-delimited JSON)",
        "description": "`jq -c '.[]'` is the local one-liner and it is the right one. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw JSON array file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted NDJSON (newline-delimited JSON) file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/ndjson-json": {
      "post": {
        "operationId": "convert_ndjson_json",
        "summary": "NDJSON (newline-delimited JSON) to JSON array",
        "description": "`jq -s '.'` slurps a stream back into an array locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw NDJSON (newline-delimited JSON) file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON array file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/frontmatter-json": {
      "post": {
        "operationId": "convert_frontmatter_json",
        "summary": "Markdown with a frontmatter fence to JSON with the metadata and the body split apart",
        "description": "Splitting on the `---` fence is three lines of code that everyone writes slightly wrong: the fence has to be the first thing in the file, the closing fence has to be on its own line, and a `---` inside the body is a horizontal rule rather than a delimiter. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.004/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.004"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.004",
            "amount_atomic": "4000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw Markdown with a frontmatter fence file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON with the metadata and the body split apart file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/markdown-json": {
      "post": {
        "operationId": "convert_markdown_json",
        "summary": "Markdown to JSON token tree plus a table of contents",
        "description": "`pandoc -t json` gives you pandoc's AST locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.004/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.004"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.004",
            "amount_atomic": "4000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw Markdown file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON token tree plus a table of contents file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/srt-vtt": {
      "post": {
        "operationId": "convert_srt_vtt",
        "summary": "SubRip subtitle file (.srt) to WebVTT (.vtt)",
        "description": "`ffmpeg -i in.srt out.vtt` converts locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw SubRip subtitle file (.srt) file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted WebVTT (.vtt) file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/vtt": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/vtt-srt": {
      "post": {
        "operationId": "convert_vtt_srt",
        "summary": "WebVTT (.vtt) to SubRip subtitle file (.srt)",
        "description": "The harder direction, and the reason to use a parser: WebVTT is the larger format, so the `WEBVTT` header, `NOTE`/`STYLE`/`REGION` blocks, cue settings after the timestamp and hour-less `mm:ss.mmm` stamps all have to land somewhere in SubRip, which has none of them. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.002/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.002"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.002",
            "amount_atomic": "2000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw WebVTT (.vtt) file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted SubRip subtitle file (.srt) file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-subrip": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/toml-json": {
      "post": {
        "operationId": "convert_toml_json",
        "summary": "TOML config file to JSON",
        "description": "`dasel -r toml -w json` locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.004/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.004"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.004",
            "amount_atomic": "4000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw TOML config file file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/json-toml": {
      "post": {
        "operationId": "convert_json_toml",
        "summary": "JSON object to TOML",
        "description": "`dasel -r json -w toml` is the local answer. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.004/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.004"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.004",
            "amount_atomic": "4000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw JSON object file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted TOML file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/toml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/xml-json": {
      "post": {
        "operationId": "convert_xml_json",
        "summary": "XML document (feed, export, SOAP payload) to JSON",
        "description": "`yq -p=xml -o=json` locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.006/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.006"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.006",
            "amount_atomic": "6000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw XML document (feed, export, SOAP payload) file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/html-text": {
      "post": {
        "operationId": "convert_html_text",
        "summary": "Saved HTML page / static HTML file to Plain text, readable",
        "description": "`lynx -dump -nolist` is the classic local answer. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.006/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.006"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.006",
            "amount_atomic": "6000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw Saved HTML page / static HTML file file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted Plain text, readable file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/convert/html-json": {
      "post": {
        "operationId": "convert_html_json",
        "summary": "HTML page containing data tables to JSON rows keyed by the header row",
        "description": "`pandas.read_html` locally. POST the raw file as the request body — no JSON wrapper, no multipart — and the converted file comes back as the response body. Input is capped at 256 KB. Every call is priced at $0.006/call · x402; a call with no X-PAYMENT header answers 402 with the envelope to pay against.",
        "tags": [
          "convert"
        ],
        "x-payment-info": {
          "protocols": [
            {
              "x402": {}
            }
          ],
          "price": {
            "mode": "fixed",
            "currency": "USD",
            "amount": "0.006"
          }
        },
        "x-billing-terms": {
          "billable_unit": {
            "unit": "one served conversion",
            "price_usd": "0.006",
            "amount_atomic": "6000",
            "metered": false,
            "note": "One served conversion. A single signed authorization buys exactly one response at the listed price; the amount settled is that whole price, and there is no partial, metered or per-byte billing. Settlement is queued only after the converter has returned an output, and only for a payment the facilitator verified — a conversion served while the facilitator was unreachable settles nothing at all, and says so in its x-payment-verified header."
          },
          "hold": {
            "held": false,
            "note": "None. Verification is a read at the facilitator, so nothing is reserved, escrowed or held: the signed authorization moves no funds until it is submitted at settle, which is queued behind the response rather than run in front of it. An authorization that never reaches settle simply goes unused."
          },
          "idempotency": {
            "key": "sha256(payment header, as presented)",
            "headers": [
              "PAYMENT-SIGNATURE",
              "X-PAYMENT"
            ],
            "idempotency_key_header": null,
            "replay": {
              "status": 402,
              "error": "payment_already_used"
            },
            "note": "There is no idempotency-key header. The key is the SHA-256 of the payment header exactly as presented — `X-PAYMENT` for x402 v1, `PAYMENT-SIGNATURE` for x402 v2, and PAYMENT-SIGNATURE is the one read when a request carries both — claimed single-use between verification and the conversion. A retry carrying the same authorization, concurrently or an hour later, is answered 402 with invalidReason `payment_already_used` and the live terms attached; it converts nothing, serves no second response and settles nothing. Sign a fresh authorization, with a fresh nonce, to buy another conversion."
          },
          "post_payment_error": {
            "settles": false,
            "on_4xx": "authorization released",
            "on_5xx": "authorization released",
            "note": "Nothing is ever settled unless a conversion was served, and every exit after the claim hands the claim back, so the very same authorization can be presented again. That covers the 4xx paths — a body that cannot be read, an empty body, a body over the 256 KB cap, input the converter refused, anything unexpected — and the one 5xx after payment, a 503 raised when the metering store is unreachable and the route fails closed. The release is best-effort, so a retry that is nonetheless refused as already used means signing a fresh authorization. What is deliberately not given back is the per-caller daily ceiling: it bounds what a request costs us, and the facilitator round trip was made either way."
          },
          "refund": {
            "path": "none",
            "dispute": "none",
            "contact": "support@lemon-agent.dev",
            "note": "None. There is no refund, credit or dispute endpoint, and no reversal of a settled payment. The mechanism is non-charge rather than refund: an authorization for a conversion that was not served is never submitted, so no funds move. A settlement that fails after a conversion was served is recorded in the ledger with settle_ok = 0 and is not retried — the caller keeps the conversion. Anything else is support@lemon-agent.dev and a conversation, not a guaranteed remedy."
          }
        },
        "parameters": [
          {
            "name": "X-PAYMENT",
            "in": "header",
            "required": false,
            "description": "A base64-encoded x402 v1 payment payload, signed against the envelope in the 402 body.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "PAYMENT-SIGNATURE",
            "in": "header",
            "required": false,
            "description": "The x402 v2 equivalent: a base64-encoded v2 payment payload, signed against the envelope in the 402 PAYMENT-REQUIRED header. Send one header or the other, not both.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "description": "The raw HTML page containing data tables file, as the body. Up to 256 KB.",
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The converted JSON rows keyed by the header row file.",
            "headers": {
              "x-payment-verified": {
                "description": "true when the payment was checked with the facilitator before serving.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "x-payment-error": {
                "description": "Present when the call was served WITHOUT its payment being verified.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "The input could not be converted. Never charged: settlement is queued only for a conversion that was actually served.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "402": {
            "description": "Payment required, in both x402 protocol versions at once. The body is the x402 v1 envelope; pay it with a v1 client and retry the same request with an X-PAYMENT header. The same 402 also carries the x402 v2 envelope, base64, in the PAYMENT-REQUIRED response header — that is where a v2 client looks, and it pays with a PAYMENT-SIGNATURE header. A body that also carries `invalidReason` means a payment WAS presented and the facilitator rejected it — retrying the same payload will fail identically.",
            "headers": {
              "PAYMENT-REQUIRED": {
                "description": "The x402 v2 PaymentRequired envelope, base64-encoded JSON: { x402Version: 2, resource, accepts, extensions.bazaar }. The same rails at the same prices as the v1 body, in v2 spelling — `amount` instead of `maxAmountRequired`, CAIP-2 networks (`eip155:8453` for `base`, `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` for `solana`), and the outputSchema moved into extensions.bazaar. Entry i here is entry i of the v1 body.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "x402Version",
                    "accepts"
                  ],
                  "properties": {
                    "x402Version": {
                      "type": "integer",
                      "enum": [
                        1
                      ]
                    },
                    "error": {
                      "type": "string"
                    },
                    "invalidReason": {
                      "type": "string"
                    },
                    "invalidMessage": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "accepts": {
                      "type": "array",
                      "minItems": 1,
                      "description": "The rails this call can be paid on, best first. Usually USDC on Base; a deployment with the Solana rail configured offers USDC on Solana as a second entry at the same price. Take the first entry you can pay — do not assume there is exactly one.",
                      "items": {
                        "type": "object",
                        "description": "An x402 v1 payment requirements envelope — the terms to pay against.",
                        "required": [
                          "scheme",
                          "network",
                          "maxAmountRequired",
                          "resource",
                          "payTo",
                          "asset"
                        ],
                        "properties": {
                          "scheme": {
                            "type": "string",
                            "enum": [
                              "exact"
                            ]
                          },
                          "network": {
                            "type": "string",
                            "enum": [
                              "base",
                              "solana"
                            ],
                            "description": "The chain this entry is payable on, in x402 v1 spelling. Read it rather than assuming: `accepts` can carry more than one entry, and `asset`, `payTo` and `extra` all change with it."
                          },
                          "maxAmountRequired": {
                            "type": "string",
                            "description": "Price in atomic units of `asset`. USDC has 6 decimals, so \"2000\" is $0.002. Each tool names its own amount; do not assume one price across the API.",
                            "examples": [
                              "5000"
                            ]
                          },
                          "resource": {
                            "type": "string",
                            "format": "uri",
                            "description": "The URL being paid for."
                          },
                          "description": {
                            "type": "string"
                          },
                          "mimeType": {
                            "type": "string",
                            "description": "Content type of the conversion this pays for."
                          },
                          "payTo": {
                            "type": "string",
                            "description": "The receiving address."
                          },
                          "maxTimeoutSeconds": {
                            "type": "integer",
                            "examples": [
                              60
                            ]
                          },
                          "asset": {
                            "type": "string",
                            "description": "USDC, on the network this entry names — the Base contract on `base`, the SPL mint on `solana`. Six decimals on both, so one price serves either rail.",
                            "examples": [
                              "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
                              "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                            ]
                          },
                          "extra": {
                            "type": "object",
                            "description": "Per-network signing detail, and its contents depend on `network`. On `base` it is the EIP-712 domain the client signs over — USDC's on-chain name() is \"USD Coin\", which is not its ticker, and a client that signs over the wrong domain produces a payment the facilitator cannot recover. On `solana` it is instead { feePayer }, the account that pays the transaction fee; there is no EIP-712 domain to sign on that rail.",
                            "properties": {
                              "name": {
                                "type": "string"
                              },
                              "version": {
                                "type": "string"
                              },
                              "feePayer": {
                                "type": "string",
                                "description": "Solana only. The fee-paying account."
                              }
                            }
                          },
                          "outputSchema": {
                            "type": "object",
                            "description": "How to call the resource and what comes back. `input.discoverable` marks it for indexing.",
                            "properties": {
                              "input": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string",
                                    "enum": [
                                      "http"
                                    ]
                                  },
                                  "method": {
                                    "type": "string",
                                    "enum": [
                                      "POST"
                                    ]
                                  },
                                  "discoverable": {
                                    "type": "boolean"
                                  },
                                  "bodyType": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              },
                              "output": {
                                "type": "object",
                                "properties": {
                                  "type": {
                                    "type": "string"
                                  },
                                  "description": {
                                    "type": "string"
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The body is larger than the 256 KB cap. Refused on the declared size, before any work.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Either this deployment has no receiving address configured (nothing to pay, so nothing to offer), or the per-caller daily ceiling on served calls is reached.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "The rate-limit store is unreachable. /convert fails closed rather than open.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "string",
                      "description": "A plain sentence naming what went wrong."
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
