{
 "openapi": "3.1.0",
 "info": {
  "title": "genie.locker",
  "version": "1.0.0",
  "description": "Per-minute GPU memory an agent can buy unattended. Prices are solved live against the GPU spot market; payment settles in USDC on Base via x402, or from a prepaid credit balance. A credit is one GB-minute of model footprint. Start with POST /api/credits/trial for a free hour \u2014 no wallet, no signup. Full procedure at https://genie.locker/agent.md",
  "contact": {
   "url": "https://genie.locker/"
  }
 },
 "servers": [
  {
   "url": "https://genie.locker"
  }
 ],
 "paths": {
  "/api/hardware": {
   "get": {
    "operationId": "listHardware",
    "summary": "The whole catalog, priced for a duration",
    "parameters": [
     {
      "name": "minutes",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number",
       "default": 60,
       "minimum": 10,
       "maximum": 1440
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Memory envelopes with resident and streamed pricing"
     }
    }
   }
  },
  "/api/quote": {
   "get": {
    "operationId": "getQuote",
    "summary": "Price one envelope in one placement",
    "parameters": [
     {
      "name": "envelope",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "enum": [
        "l16",
        "l24",
        "l32",
        "l48",
        "l80",
        "l96",
        "l141"
       ]
      }
     },
     {
      "name": "placement",
      "in": "query",
      "required": false,
      "schema": {
       "type": "string",
       "enum": [
        "resident",
        "streamed"
       ],
       "default": "streamed"
      }
     },
     {
      "name": "minutes",
      "in": "query",
      "required": false,
      "schema": {
       "type": "number",
       "default": 60
      }
     }
    ],
    "responses": {
     "200": {
      "description": "A quote"
     },
     "404": {
      "description": "No such envelope"
     }
    }
   }
  },
  "/api/status": {
   "get": {
    "operationId": "getStatus",
    "summary": "Seller state: capacity, settlement, live market, lockers sold",
    "responses": {
     "200": {
      "description": "Status"
     }
    }
   }
  },
  "/api/verify": {
   "get": {
    "operationId": "getVerification",
    "summary": "Independent InferenceView VERIFY verdict on this seller",
    "responses": {
     "200": {
      "description": "Verdict, relayed verbatim"
     }
    }
   }
  },
  "/api/credits/pricing": {
   "get": {
    "operationId": "getCreditPricing",
    "summary": "Credit unit, burn multipliers and volume tiers",
    "responses": {
     "200": {
      "description": "Pricing"
     }
    }
   }
  },
  "/api/credits/trial": {
   "post": {
    "operationId": "claimTrial",
    "summary": "Free credits, once per caller. No wallet required.",
    "responses": {
     "201": {
      "description": "account_id and a one-time api_key"
     },
     "429": {
      "description": "Already claimed"
     }
    }
   }
  },
  "/api/credits": {
   "post": {
    "operationId": "buyCredits",
    "summary": "Top up. Unpaid returns an x402 challenge; present tx_hash to settle.",
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "usd": {
          "type": "number",
          "description": "Amount to quote"
         },
         "tx_hash": {
          "type": "string",
          "description": "A settled Base transaction. Credits exactly once."
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Credited"
     },
     "402": {
      "description": "x402 challenge"
     }
    }
   }
  },
  "/api/credits/balance": {
   "get": {
    "operationId": "getBalance",
    "summary": "Credit balance for an api key",
    "security": [
     {
      "bearerAuth": []
     }
    ],
    "responses": {
     "200": {
      "description": "Balance"
     },
     "401": {
      "description": "Unknown key"
     }
    }
   }
  },
  "/api/wallet/balance": {
   "get": {
    "operationId": "getWalletBalance",
    "summary": "USDC on Base for an address, and what it can afford",
    "parameters": [
     {
      "name": "address",
      "in": "query",
      "required": true,
      "schema": {
       "type": "string",
       "pattern": "^0x[0-9a-fA-F]{40}$"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Balance and affordable lockers"
     }
    }
   }
  },
  "/api/lockers": {
   "get": {
    "operationId": "describeLockerOffer",
    "summary": "The x402 challenge describing the default locker",
    "responses": {
     "402": {
      "description": "x402 challenge"
     }
    }
   },
   "post": {
    "operationId": "buyLocker",
    "summary": "Buy a locker with credits (Bearer) or a per-locker x402 payment",
    "security": [
     {
      "bearerAuth": []
     },
     {}
    ],
    "requestBody": {
     "required": false,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "envelope": {
          "type": "string",
          "default": "l48"
         },
         "placement": {
          "type": "string",
          "enum": [
           "resident",
           "streamed"
          ],
          "default": "streamed"
         },
         "minutes": {
          "type": "number",
          "default": 60,
          "minimum": 10,
          "maximum": 1440
         }
        }
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "locker_id, endpoint, token, expires_at, receipt"
     },
     "402": {
      "description": "x402 challenge, or insufficient credits"
     },
     "503": {
      "description": "Capacity or settlement unavailable. Do not retry in a loop."
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "bearerAuth": {
    "type": "http",
    "scheme": "bearer",
    "description": "A genie.locker credit key (gk_...) from /api/credits/trial or /api/credits"
   }
  }
 }
}
