{
 "openapi": "3.1.0",
 "info": {
  "title": "SatBotly API",
  "version": "1.1.0",
  "description": "Free, read-only search over the SatBotly pay-per-call API list and Bitcoin merchant list (/api/v1/lookup, no key, CORS open, about 60 requests per 10 minutes per IP, 429 with Retry-After past that), plus the paid Pro CSV export (/api/v1/pro, 9.00 USDC on Base via x402).",
  "license": {
   "name": "CC BY 4.0",
   "url": "https://creativecommons.org/licenses/by/4.0/"
  },
  "contact": {
   "email": "satoshi@satbotly.com"
  },
  "x-guidance": "Free: GET /api/v1/lookup?q=<text>. Paid: GET /api/v1/pro returns HTTP 402 with x402 v2 requirements (9.00 USDC on Base); pay, then use the returned token on /api/v1/pro/export?list=<payments|wallets|apis|bitcoin|mcp>. Full guide: https://satbotly.com/llms.txt"
 },
 "servers": [
  {
   "url": "https://satbotly.com"
  }
 ],
 "paths": {
  "/api/v1/lookup": {
   "get": {
    "operationId": "lookup",
    "summary": "Search APIs and Bitcoin merchants",
    "security": [],
    "description": "Case-insensitive substring match on name or id (and provider, for APIs). Returns at most 25 rows per list; counts holds the true totals.",
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": true,
      "description": "Search text, 2 to 100 characters after trimming.",
      "schema": {
       "type": "string",
       "minLength": 2,
       "maxLength": 100
      },
      "example": "bitrefill"
     }
    ],
    "responses": {
     "200": {
      "description": "Matches",
      "headers": {
       "Access-Control-Allow-Origin": {
        "schema": {
         "type": "string",
         "const": "*"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/LookupResult"
        }
       }
      }
     },
     "400": {
      "description": "q missing, shorter than 2 or longer than 100 characters",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "ok": false,
         "error": "q must be 2-100 characters"
        }
       }
      }
     },
     "405": {
      "description": "Method other than GET, HEAD or OPTIONS",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "429": {
      "description": "Rate limited",
      "headers": {
       "Retry-After": {
        "schema": {
         "type": "integer"
        },
        "description": "Seconds to wait"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        },
        "example": {
         "ok": false,
         "error": "rate"
        }
       }
      }
     },
     "500": {
      "description": "Server error",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  },
  "/api/v1/pro": {
   "get": {
    "operationId": "pro",
    "summary": "Buy SatBotly Pro: 30 days of CSV export (x402, 9.00 USDC on Base)",
    "security": [],
    "description": "Send GET with no payment to receive HTTP 402 with the x402 v2 requirements (also base64 in the PAYMENT-REQUIRED header). Sign an EIP-3009 USDC authorization for exactly the amount and send it as base64 JSON in the PAYMENT-SIGNATURE header. On success the response holds a 30-day bearer token for GET /api/v1/pro/export?list=<name>, which returns that list as CSV. Retrying the same signed authorization cannot charge twice.",
    "x-payment-info": {
     "price": {
      "mode": "fixed",
      "currency": "USD",
      "amount": "9.00"
     },
     "protocols": [
      {
       "x402": {
        "x402Version": 2,
        "scheme": "exact",
        "network": "eip155:8453",
        "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        "amount": "9000000",
        "payTo": "0xeDb324E75A7dD36846576b8D46d3b43D7Df4f0FA"
       }
      }
     ]
    },
    "parameters": [
     {
      "name": "PAYMENT-SIGNATURE",
      "in": "header",
      "required": false,
      "description": "x402 v2 PaymentPayload as base64 JSON. Omit it to get the 402 requirements.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Paid. Token for the Pro CSV export.",
      "headers": {
       "PAYMENT-RESPONSE": {
        "schema": {
         "type": "string"
        },
        "description": "Base64 settlement result"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ProToken"
        }
       }
      }
     },
     "400": {
      "description": "PAYMENT-SIGNATURE header unreadable or too large",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "402": {
      "description": "Payment Required: x402 v2 requirements for 9.00 USDC on Base",
      "headers": {
       "PAYMENT-REQUIRED": {
        "schema": {
         "type": "string"
        },
        "description": "Base64 copy of the JSON body"
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ProChallenge"
        }
       }
      }
     },
     "429": {
      "description": "Rate limited (20 payment attempts per hour per IP)",
      "headers": {
       "Retry-After": {
        "schema": {
         "type": "integer"
        }
       }
      },
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     },
     "502": {
      "description": "Facilitator unavailable, or payment still settling (retry the same request; it cannot charge twice)",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/Error"
        }
       }
      }
     }
    }
   }
  }
 },
 "components": {
  "schemas": {
   "LookupResult": {
    "type": "object",
    "required": [
     "ok",
     "q",
     "dataAsOf",
     "apis",
     "bitcoin",
     "counts",
     "truncated"
    ],
    "properties": {
     "ok": {
      "type": "boolean",
      "const": true
     },
     "q": {
      "type": "string"
     },
     "dataAsOf": {
      "type": "string",
      "format": "date"
     },
     "apis": {
      "type": "array",
      "maxItems": 25,
      "items": {
       "$ref": "#/components/schemas/Api"
      },
      "description": "Rows of https://satbotly.com/data/apis.json"
     },
     "bitcoin": {
      "type": "array",
      "maxItems": 25,
      "items": {
       "$ref": "#/components/schemas/Merchant"
      },
      "description": "Rows of https://satbotly.com/data/bitcoin.json"
     },
     "counts": {
      "type": "object",
      "properties": {
       "apis": {
        "type": "integer"
       },
       "bitcoin": {
        "type": "integer"
       }
      }
     },
     "truncated": {
      "type": "boolean",
      "description": "true when either list had more than 25 matches"
     }
    }
   },
   "Source": {
    "type": "object",
    "properties": {
     "url": {
      "type": "string",
      "format": "uri"
     },
     "quote": {
      "type": "string"
     },
     "type": {
      "type": "string"
     }
    }
   },
   "Api": {
    "type": "object",
    "additionalProperties": true,
    "properties": {
     "id": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "provider": {
      "type": "string"
     },
     "protocol": {
      "type": "string",
      "examples": [
       "L402",
       "x402",
       "MPP"
      ]
     },
     "asset": {
      "type": "string"
     },
     "priceSats": {
      "type": [
       "number",
       "null"
      ]
     },
     "priceUsd": {
      "type": "number"
     },
     "priceBasis": {
      "type": "string"
     },
     "category": {
      "type": "string"
     },
     "endpoint": {
      "type": "string",
      "format": "uri"
     },
     "method": {
      "type": "string"
     },
     "probe": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
       "status": {
        "type": "integer",
        "const": 402
       },
       "probedAt": {
        "type": "string"
       }
      }
     },
     "sources": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Source"
      }
     },
     "lastChecked": {
      "type": "string",
      "format": "date"
     }
    }
   },
   "Merchant": {
    "type": "object",
    "additionalProperties": true,
    "properties": {
     "id": {
      "type": "string"
     },
     "name": {
      "type": "string"
     },
     "category": {
      "type": "string"
     },
     "verdict": {
      "type": "string",
      "enum": [
       "YES",
       "KINDA",
       "NO"
      ]
     },
     "how": {
      "type": "string"
     },
     "note": {
      "type": "string"
     },
     "url": {
      "type": "string",
      "format": "uri"
     },
     "basis": {
      "type": "string",
      "enum": [
       "stated",
       "absence"
      ]
     },
     "sources": {
      "type": "array",
      "items": {
       "$ref": "#/components/schemas/Source"
      }
     },
     "lastChecked": {
      "type": "string",
      "format": "date"
     }
    }
   },
   "ProChallenge": {
    "type": "object",
    "required": [
     "x402Version",
     "accepts"
    ],
    "properties": {
     "x402Version": {
      "type": "integer",
      "const": 2
     },
     "error": {
      "type": "string"
     },
     "resource": {
      "type": "object",
      "additionalProperties": true
     },
     "accepts": {
      "type": "array",
      "items": {
       "type": "object",
       "properties": {
        "scheme": {
         "type": "string",
         "const": "exact"
        },
        "network": {
         "type": "string",
         "const": "eip155:8453"
        },
        "amount": {
         "type": "string",
         "const": "9000000",
         "description": "USDC atomic units (6 decimals)"
        },
        "asset": {
         "type": "string",
         "const": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
        },
        "payTo": {
         "type": "string",
         "const": "0xeDb324E75A7dD36846576b8D46d3b43D7Df4f0FA"
        },
        "maxTimeoutSeconds": {
         "type": "integer"
        },
        "extra": {
         "type": "object",
         "additionalProperties": true
        }
       }
      }
     },
     "extensions": {
      "type": "object",
      "additionalProperties": true
     }
    }
   },
   "ProToken": {
    "type": "object",
    "required": [
     "ok",
     "token",
     "expiresAt",
     "export",
     "lists"
    ],
    "properties": {
     "ok": {
      "type": "boolean",
      "const": true
     },
     "token": {
      "type": "string",
      "description": "Send as Authorization: Bearer <token>"
     },
     "expiresAt": {
      "type": "string",
      "format": "date-time"
     },
     "payer": {
      "type": [
       "string",
       "null"
      ]
     },
     "transaction": {
      "type": "string"
     },
     "network": {
      "type": "string"
     },
     "export": {
      "type": "string",
      "format": "uri",
      "description": "GET <export> with the token returns CSV; change list= to payments, wallets, apis, bitcoin or mcp"
     },
     "lists": {
      "type": "array",
      "items": {
       "type": "string"
      }
     }
    }
   },
   "Error": {
    "type": "object",
    "required": [
     "ok",
     "error"
    ],
    "properties": {
     "ok": {
      "type": "boolean",
      "const": false
     },
     "error": {
      "type": "string"
     }
    }
   }
  }
 }
}
