{"openapi":"3.1.0","info":{"title":"NodeOps MPP Gateway","version":"1.0.0","description":"Payment gateway for deploying projects to NodeOps infrastructure. Agents authenticate with wallet signatures, pay with ERC20 tokens (USDC/USDT) on EVM chains, and deploy autonomously. Pricing is dynamic with a minimum of $0.50."},"x-service-info":{"categories":["deployment","infrastructure","compute"],"payment":{"method":"evm","intent":"charge","recipient":"0x2664D5d0baa2D464D922c2137854ec33d95E12F8","default_chain":"base","supported_chains":[{"chain":"base","chain_id":8453,"tokens":["usdc","usdt"]},{"chain":"arbitrum","chain_id":42161,"tokens":["usdc","usdt"]}],"pricing":{"type":"dynamic","source":"NodeOps getProjectPricing API","minimum_usd":0.5,"credits_per_usd":100,"note":"Credits are consumed hourly. If wallet has credits and no active projects, deploys are free."}},"auth":{"type":"wallet_signature","message_format":"{wallet}:{timestamp}:{nonce}","algorithm":"EIP-191 (viem signMessage)","headers":["X-Wallet-Address","X-Signature","X-Timestamp","X-Nonce"]}},"paths":{"/health":{"get":{"summary":"Health check","responses":{"200":{"description":"{ \"status\": \"ok\" }"}}}},"/agent/deploy":{"post":{"summary":"Deploy a project to NodeOps","description":"No payment → returns 402 with quote (or deploys free if wallet has credits and no active projects). With X-Payment-Tx header → verifies on-chain payment, topups credits, deploys.","parameters":[{"name":"X-Wallet-Address","in":"header","required":true,"schema":{"type":"string"},"description":"EVM wallet address (0x...)"},{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"Signature of {wallet}:{timestamp}:{nonce}"},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix ms (within 60s of server)"},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"UUID, unique per request"},{"name":"X-Payment-Tx","in":"header","required":false,"schema":{"type":"string"},"description":"ERC20 transfer tx hash (only on second call)"},{"name":"X-Payment-Chain","in":"header","required":false,"schema":{"type":"string","default":"base"},"description":"Chain name (default from config)"},{"name":"X-Payment-Token","in":"header","required":false,"schema":{"type":"string","default":"usdc"},"description":"Token symbol (default usdc)"},{"name":"X-Use-Existing-Credits","in":"header","required":false,"schema":{"type":"string","enum":["true","false"]},"description":"Opt in to use existing credits even when active projects exist (will reduce their runtime)"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["uniqueName","displayName","upload"],"properties":{"uniqueName":{"type":"string","description":"Unique project identifier"},"displayName":{"type":"string","description":"Human-readable name"},"description":{"type":"string","description":"Optional description"},"months":{"type":"integer","default":1,"description":"Months of credit to topup (price multiplier)"},"upload":{"oneOf":[{"type":"object","properties":{"type":{"const":"files"},"files":{"type":"array"}}},{"type":"object","properties":{"type":{"const":"zip"},"data":{"type":"string","description":"base64"},"filename":{"type":"string"}}}]}}}}}},"x-payment-info":{"method":"evm","intent":"charge","description":"Dynamic pricing from NodeOps, $0.50 minimum. ERC20 payment on any supported EVM chain.","supported_chains":[{"chain":"base","chain_id":8453,"tokens":["usdc","usdt"]},{"chain":"arbitrum","chain_id":42161,"tokens":["usdc","usdt"]}]},"responses":{"200":{"description":"Deployment started — returns { projectId, deploymentId, status, message }"},"400":{"description":"Invalid body"},"401":{"description":"Bad signature, expired timestamp, or replayed nonce"},"402":{"description":"Payment Required — returns { amount_usd, amount_token, pay_to, payment_chain, supported_chains, current_credit_balance_usd, active_projects, warning? }"},"409":{"description":"Tx hash already used"},"429":{"description":"Rate limited (30/min per wallet+IP)"}}}},"/agent/deploy/{projectId}/{deploymentId}/status":{"get":{"summary":"Poll deployment status (deployer wallet only)","parameters":[{"name":"X-Wallet-Address","in":"header","required":true,"schema":{"type":"string"},"description":"EVM wallet address (0x...)"},{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"Signature of {wallet}:{timestamp}:{nonce}"},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix ms (within 60s of server)"},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"UUID, unique per request"},{"name":"projectId","in":"path","required":true,"schema":{"type":"string"}},{"name":"deploymentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Status: deploying | ready (with endpoint URL) | failed (with reason)"},"403":{"description":"Not authorized — wallet is not the deployer"}}}},"/agent/projects":{"get":{"summary":"List all projects for the wallet, with live URL of latest deployment","parameters":[{"name":"X-Wallet-Address","in":"header","required":true,"schema":{"type":"string"},"description":"EVM wallet address (0x...)"},{"name":"X-Signature","in":"header","required":true,"schema":{"type":"string"},"description":"Signature of {wallet}:{timestamp}:{nonce}"},{"name":"X-Timestamp","in":"header","required":true,"schema":{"type":"string"},"description":"Unix ms (within 60s of server)"},{"name":"X-Nonce","in":"header","required":true,"schema":{"type":"string"},"description":"UUID, unique per request"}],"responses":{"200":{"description":"{ wallet, count, projects: [{ id, name, displayName, status, url, createdAt }] }"}}}},"/agent/balance/{address}":{"get":{"summary":"Check ERC20 token balances on a chain (no auth required)","parameters":[{"name":"address","in":"path","required":true,"schema":{"type":"string"},"description":"EVM wallet address"},{"name":"chain","in":"query","required":false,"schema":{"type":"string","default":"base"},"description":"Chain name"}],"responses":{"200":{"description":"{ address, chain, chain_id, balances: [{ token, symbol, address, balance, balance_raw, decimals }] }"}}}},"/agent/chains":{"get":{"summary":"List supported chains and tokens (no auth required)","responses":{"200":{"description":"{ chains: [{ chain, chain_id, tokens }] }"}}}}}}