{"openapi":"3.1.0","info":{"title":"Spindle API","version":"1","description":"OpenAI-compatible inference API with signed receipts."},"servers":[{"url":"/"}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Authorization: Bearer sk-spdl-... (credit balance)"},"x402Payment":{"type":"apiKey","in":"header","name":"X-PAYMENT","description":"x402 exact: base64 payment payload for a PAYMENT-REQUIRED challenge"},"x402Session":{"type":"apiKey","in":"header","name":"X-Spindle-Session","description":"x402 session token"}},"schemas":{},"parameters":{}},"paths":{"/v1/models":{"get":{"summary":"List models","tags":["Buyer"],"responses":{"200":{"description":"Models","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["model"]},"owned_by":{"type":"string","enum":["spindle"]},"lanes":{"type":"array","items":{"type":"string","enum":["sealed","open"]}},"kind":{"type":"string","enum":["chat","embeddings","images"]},"available":{"type":"boolean"},"context_length":{"type":"integer","minimum":0},"sealed_available":{"type":"boolean"},"pricing":{"type":"object","properties":{"unitKind":{"type":"string","enum":["tokens_1m","image","job","gpu_hour"]},"buyerMicrosPerUnit":{"type":"string","pattern":"^\\d{1,78}$"}},"required":["unitKind","buyerMicrosPerUnit"]}},"required":["id","object","owned_by","lanes","kind","available","pricing"]}}},"required":["object","data"]}}}}}}},"/v1/chat/completions":{"post":{"summary":"Chat completion (stream or not)","tags":["Buyer"],"security":[{"apiKey":[]},{"x402Payment":[]},{"x402Session":[]}],"parameters":[{"schema":{"type":"string","enum":["open","sealed"],"description":"Defaults to open."},"required":false,"description":"Defaults to open.","name":"X-Spindle-Lane","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["system","user","assistant","tool"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string"}},"required":["type","text"]},{"type":"object","properties":{"type":{"type":"string","enum":["image_url"]},"image_url":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]}},"required":["type","image_url"]}]}},{"type":"null"}]},"name":{"type":"string"}},"required":["role","content"]},"minItems":1},"stream":{"type":"boolean"},"max_tokens":{"type":"integer","exclusiveMinimum":0,"maximum":8192},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"stop":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"maxItems":4}]},"seed":{"type":"integer"}},"required":["model","messages"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Spindle-Job-Id":{"description":"Job id","schema":{"type":"string"}},"X-Spindle-Receipt":{"description":"Relative receipt URL","schema":{"type":"string"}},"X-Spindle-Charge-Micros":{"description":"Exact charge in USDG micros","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["chat.completion"]},"created":{"type":"integer"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer"},"message":{"type":"object","properties":{"role":{"type":"string","enum":["assistant"]},"content":{"type":["string","null"]},"reasoning":{"type":"string"}},"required":["role","content"]},"finish_reason":{"type":["string","null"]}},"required":["index","message","finish_reason"]}},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"completion_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}},"required":["prompt_tokens","completion_tokens","total_tokens"]},"spindle":{"type":"object","properties":{"jobId":{"type":"string"},"chargeMicros":{"type":"string","pattern":"^\\d{1,78}$"},"receiptUrl":{"type":"string"},"paymentResponse":{"type":"string"}},"required":["jobId","chargeMicros","receiptUrl"]}},"required":["id","object","created","model","choices","usage","spindle"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"402":{"description":"x402 payment required (header PAYMENT-REQUIRED carries base64 of the same JSON) or insufficient balance","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/embeddings":{"post":{"summary":"Embeddings","tags":["Buyer"],"security":[{"apiKey":[]},{"x402Payment":[]},{"x402Session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string"},"input":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":48}]}},"required":["model","input"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Spindle-Job-Id":{"description":"Job id","schema":{"type":"string"}},"X-Spindle-Receipt":{"description":"Relative receipt URL","schema":{"type":"string"}},"X-Spindle-Charge-Micros":{"description":"Exact charge in USDG micros","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["embedding"]},"index":{"type":"integer"},"embedding":{"type":"array","items":{"type":"number"}}},"required":["object","index","embedding"]}},"model":{"type":"string"},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer"},"total_tokens":{"type":"integer"}},"required":["prompt_tokens","total_tokens"]},"spindle":{"type":"object","properties":{"jobId":{"type":"string"},"chargeMicros":{"type":"string","pattern":"^\\d{1,78}$"},"receiptUrl":{"type":"string"},"paymentResponse":{"type":"string"}},"required":["jobId","chargeMicros","receiptUrl"]}},"required":["object","data","model","usage","spindle"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"402":{"description":"x402 payment required (header PAYMENT-REQUIRED carries base64 of the same JSON) or insufficient balance","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/images/generations":{"post":{"summary":"Image generation (capacity dependent)","tags":["Buyer"],"security":[{"apiKey":[]},{"x402Payment":[]},{"x402Session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string"},"prompt":{"type":"string","minLength":1},"n":{"type":"integer","minimum":1,"maximum":4},"size":{"type":"string"}},"required":["model","prompt"]}}}},"responses":{"200":{"description":"OK","headers":{"X-Spindle-Job-Id":{"description":"Job id","schema":{"type":"string"}},"X-Spindle-Receipt":{"description":"Relative receipt URL","schema":{"type":"string"}},"X-Spindle-Charge-Micros":{"description":"Exact charge in USDG micros","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"created":{"type":"integer"},"data":{"type":"array","items":{"type":"object","properties":{"b64_json":{"type":"string"},"url":{"type":"string"}}}},"spindle":{"type":"object","properties":{"jobId":{"type":"string"},"chargeMicros":{"type":"string","pattern":"^\\d{1,78}$"},"receiptUrl":{"type":"string"},"paymentResponse":{"type":"string"}},"required":["jobId","chargeMicros","receiptUrl"]}},"required":["created","data","spindle"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"402":{"description":"x402 payment required (header PAYMENT-REQUIRED carries base64 of the same JSON) or insufficient balance","content":{"application/json":{"schema":{"type":"object","additionalProperties":{}}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/rate-card":{"get":{"summary":"Today's rate card","tags":["Public"],"responses":{"200":{"description":"Rate card","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"gpuClass":{"anyOf":[{"type":"number","enum":[0]},{"type":"number","enum":[1]},{"type":"number","enum":[2]},{"type":"number","enum":[3]},{"type":"number","enum":[4]}]},"lane":{"type":"string","enum":["sealed","open"]},"unitKind":{"type":"string","enum":["tokens_1m","image","job","gpu_hour"]},"providerMicrosPerUnit":{"type":"string","pattern":"^\\d{1,78}$"},"buyerMicrosPerUnit":{"type":"string","pattern":"^\\d{1,78}$"}},"required":["gpuClass","lane","unitKind","providerMicrosPerUnit","buyerMicrosPerUnit"]}}}}}}}},"/v1/receipts/{jobId}":{"get":{"summary":"Signed job receipt","tags":["Public"],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"jobId","in":"path"}],"responses":{"200":{"description":"Receipt","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string","format":"uuid"},"nodeId":{"type":"string"},"onchainNodeId":{"type":["string","null"]},"nodeKey":{"type":"string","pattern":"^0x[0-9a-f]{40}$"},"nodePubkey":{"type":"string","pattern":"^0x[0-9a-fA-F]+$"},"owner":{"type":"string","pattern":"^0x[0-9a-f]{40}$"},"lane":{"type":"string","enum":["sealed","open"]},"model":{"type":"string"},"usage":{"type":"object","properties":{"p":{"type":"integer"},"c":{"type":"integer"},"n":{"type":"integer"}},"required":["p","c"]},"cose":{"type":"string","description":"base64 COSE_Sign1"},"payload":{"type":"object","additionalProperties":{}},"verified":{"type":"boolean"},"reason":{"type":["string","null"]},"attestationRef":{"type":["string","null"]},"epoch":{"type":["integer","null"]}},"required":["jobId","nodeId","onchainNodeId","nodeKey","lane","model","usage","cose","payload","verified","reason","attestationRef","epoch"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/epochs":{"get":{"summary":"List epochs","tags":["Public"],"responses":{"200":{"description":"Epochs, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"epoch":{"type":"integer"},"root":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$"},"totalEarned":{"type":"string","pattern":"^\\d{1,78}$"},"owners":{"type":"integer"},"status":{"type":"string","enum":["built","posting","posted","vetoed","failed"]},"waitingFor":{"type":["string","null"],"enum":["settlement","keeper_gas","epoch_cap","other",null]},"postedAt":{"type":["string","null"],"format":"date-time"},"txHash":{"type":["string","null"],"pattern":"^0x[0-9a-fA-F]{64}$"},"claimableAt":{"type":["string","null"],"format":"date-time"}},"required":["epoch","root","totalEarned","owners","status","postedAt","txHash","claimableAt"]}},"nextCursor":{"type":["string","null"]}},"required":["items","nextCursor"]}}}}}}},"/v1/epochs/latest":{"get":{"summary":"Latest epoch","tags":["Public"],"responses":{"200":{"description":"Latest epoch","content":{"application/json":{"schema":{"type":"object","properties":{"epoch":{"type":"integer"},"root":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$"},"totalEarned":{"type":"string","pattern":"^\\d{1,78}$"},"postedAt":{"type":["string","null"],"format":"date-time"},"txHash":{"type":["string","null"],"pattern":"^0x[0-9a-fA-F]{64}$"},"claimableAt":{"type":["string","null"],"format":"date-time"}},"required":["epoch","root","totalEarned","postedAt","txHash","claimableAt"]}}}}}}},"/v1/epochs/{epoch}/tree":{"get":{"summary":"Epoch Merkle tree (StandardMerkleTree dump)","tags":["Public"],"parameters":[{"schema":{"type":"string","pattern":"^\\d+$"},"required":true,"name":"epoch","in":"path"}],"responses":{"200":{"description":"Tree","content":{"application/json":{"schema":{"type":"object","properties":{"format":{"type":"string"},"tree":{"type":"array","items":{"type":"string"}},"values":{"type":"array","items":{"type":"object","properties":{"value":{"type":"array","items":{"type":"string"}},"treeIndex":{"type":"integer"}},"required":["value","treeIndex"]}},"leafEncoding":{"type":"array","items":{"type":"string"}}},"required":["format","tree","values","leafEncoding"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/x402/sessions":{"post":{"summary":"Create an x402 session (returns Permit2 typed data to sign)","tags":["x402"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payer":{"type":"string","pattern":"^0x[0-9a-f]{40}$"},"capMicros":{"type":"string","pattern":"^\\d{1,78}$"},"ttlSec":{"type":"integer","minimum":60,"maximum":3600}},"required":["payer","capMicros","ttlSec"]}}}},"responses":{"200":{"description":"Session","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string"},"typedData":{"type":"object","properties":{"domain":{"type":"object","additionalProperties":{}},"types":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"type":{"type":"string"}},"required":["name","type"]}}},"primaryType":{"type":"string"},"message":{"type":"object","additionalProperties":{}}},"required":["domain","types","primaryType","message"]},"surchargeMicros":{"type":"string","pattern":"^\\d{1,78}$"},"expiresAt":{"type":"string","format":"date-time"}},"required":["sessionId","typedData","surchargeMicros","expiresAt"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/x402/sessions/{id}/open":{"post":{"summary":"Open a session with the signature","tags":["x402"],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signature":{"type":"string","pattern":"^0x[0-9a-fA-F]+$"}},"required":["signature"]}}}},"responses":{"200":{"description":"Session token","content":{"application/json":{"schema":{"type":"object","properties":{"sessionToken":{"type":"string"},"capMicros":{"type":"string","pattern":"^\\d{1,78}$"},"surchargeMicros":{"type":"string","pattern":"^\\d{1,78}$"},"spendableMicros":{"type":"string","pattern":"^\\d{1,78}$"},"expiresAt":{"type":"string","format":"date-time"}},"required":["sessionToken","capMicros","surchargeMicros","spendableMicros","expiresAt"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/x402/sessions/{id}":{"get":{"summary":"Session status","tags":["x402"],"security":[{"x402Session":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["open","closing","settling","settled","failed","expired"]},"usedMicros":{"type":"string","pattern":"^\\d{1,78}$"},"spendableMicros":{"type":"string","pattern":"^\\d{1,78}$"},"settleTx":{"type":["string","null"],"pattern":"^0x[0-9a-fA-F]{64}$"}},"required":["status","usedMicros","spendableMicros","settleTx"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}},"/v1/x402/sessions/{id}/close":{"post":{"summary":"Close a session","tags":["x402"],"security":[{"x402Session":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Closing","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["closing"]}},"required":["status"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"message":{"type":"string"},"type":{"type":"string"},"code":{"type":["string","null"]}},"required":["message","type","code"]}},"required":["error"]}}}}}}}},"webhooks":{}}