{"openapi":"3.1.0","info":{"title":"nyquist API","version":"1.0.0","description":"自律的なエージェントのための仮想通貨ウォレットの API。エージェントは人間を介さずに登録し、自分の署名だけで Safe から送金する。nyquist は署名を中継してガス代を立て替え、Safe から払い戻しを受ける。","contact":{"name":"osaxyz","url":"https://github.com/osaxyz/nyquist"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://api.nyquist.sh","description":"メインネット"},{"url":"https://api.testnet.nyquist.sh","description":"Sepolia"},{"url":"http://localhost:8787","description":"ローカル開発"}],"tags":[{"name":"agent","description":"エージェント自身の登録と情報"},{"name":"transaction","description":"送金"}],"components":{"securitySchemes":{"httpSignature":{"type":"apiKey","in":"header","name":"Signature","description":"RFC 9421 の HTTP Message Signatures。Ed25519 で @method、@authority、@path、@query と、本文があれば content-digest に署名する。keyid は公開鍵 JWK の RFC 7638 サムプリント、created、expires、nonce は必須。"}},"schemas":{"Agent":{"type":"object","properties":{"id":{"type":"string","description":"公開鍵の RFC 7638 サムプリント。署名の keyid と同じ"},"accountId":{"type":"null","description":"以前の版との互換のために残している。常に null"},"status":{"type":"string","enum":["active","suspended"],"description":"revert が続いて中継を止めている間は suspended。その間 nyquist は中継しない"},"signer":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"safe":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"owners":{"type":"array","items":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"description":"Safe のオーナー。作成前は signer だけ"},"threshold":{"type":"integer"},"recoveryOwner":{"type":"null","description":"以前の版との互換のために残している。常に null"},"deployed":{"type":"boolean"},"balanceWei":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$","example":"1000000000000000"},"nonce":{"type":"string","description":"次の SafeTx に使う nonce"},"deploymentFeeWei":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$","example":"1000000000000000","description":"Safe の作成時に Safe からリレイヤーへ払う作成費用。0 なら、Safe は最初の送金と同じ tx で作り、作成のガスをその送金の baseGas に含める"},"createdAt":{"type":"string"}},"required":["id","accountId","status","signer","safe","owners","threshold","recoveryOwner","deployed","balanceWei","nonce","deploymentFeeWei","createdAt"]},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"RegisterAgent":{"type":"object","properties":{"publicKey":{"$ref":"#/components/schemas/PublicJwk"},"signer":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed","description":"Safe の唯一のオーナーになり、SafeTx に署名するアドレス"},"invite":{"type":"string","maxLength":200,"description":"招待制の API で、登録に添える招待コード。登録を誰にでも開いている API では無視する"}},"required":["publicKey","signer"]},"PublicJwk":{"type":"object","properties":{"kty":{"type":"string","enum":["OKP"]},"crv":{"type":"string","enum":["Ed25519"]},"x":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$"}},"required":["kty","crv","x"],"description":"エージェントの Ed25519 公開鍵"},"Quote":{"type":"object","properties":{"safe":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"chainId":{"type":"integer"},"nonce":{"type":"string"},"safeTxGas":{"type":"string"},"baseGas":{"type":"string"},"gasPrice":{"type":"string"},"gasToken":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"refundReceiver":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"safeTxHash":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$","example":"0xabababababababababababababababababababababababababababababababab","description":"参考値。エージェントは自分でも計算して一致を確かめる"},"maxFeeWei":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$","example":"1000000000000000","description":"Safe から払い戻されるガス代の上限の目安"},"feeGas":{"type":"string","description":"baseGas のうち、リレイヤーの手数料の分。Safe 内の呼び出しと baseGas の見積もりに公開している割合を掛けたもの"}},"required":["safe","chainId","nonce","safeTxGas","baseGas","gasPrice","gasToken","refundReceiver","safeTxHash","maxFeeWei","feeGas"],"description":"SafeTx に入れるガスの条件と払い戻し先。operation は常に 0"},"Call":{"type":"object","properties":{"to":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"value":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$","example":"1000000000000000"},"data":{"type":"string","pattern":"^0x([0-9a-fA-F]{2})*$","default":"0x","example":"0x"}},"required":["to","value"]},"Transaction":{"type":"object","properties":{"hash":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$","example":"0xabababababababababababababababababababababababababababababababab"},"safeTxHash":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$","example":"0xabababababababababababababababababababababababababababababababab"},"status":{"type":"string","enum":["pending","success","failed","reverted","dropped"],"description":"failed は Safe 内の呼び出しが失敗したが、ガス代は払い戻された状態。dropped は取り込まれないまま nyquist が取り消し、実行されなかった状態"}},"required":["hash","safeTxHash","status"]},"TransactionRequest":{"allOf":[{"$ref":"#/components/schemas/Call"},{"type":"object","properties":{"nonce":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$"},"safeTxGas":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$"},"baseGas":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$"},"gasPrice":{"type":"string","pattern":"^(0|[1-9][0-9]{0,77})$"},"signature":{"type":"string","pattern":"^0x[0-9a-fA-F]{130}$","example":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","description":"signer による SafeTx の EIP-712 署名。refundReceiver にはリレイヤー、gasToken には 0 を入れる"}},"required":["nonce","safeTxGas","baseGas","gasPrice","signature"]}]}},"parameters":{}},"paths":{"/api/v1/agent":{"post":{"operationId":"registerAgent","tags":["agent"],"summary":"エージェントを登録する","description":"エージェントの公開鍵と signer を登録し、signer だけがオーナーの Safe のアドレスを払い出す。人間の承認は要らない。Safe は作成費用以上の入金を確認したあと、最初の送金時に作る。署名の keyid は publicKey のサムプリントにする。","security":[{"httpSignature":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterAgent"}}}},"responses":{"201":{"description":"登録した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Agent"}}}},"400":{"description":"入力が不正","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"招待制の API で、招待コードがないか違う","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"登録済み","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"登録が多すぎる","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"getAgent","tags":["agent"],"summary":"自分の情報を取得する","description":"署名したエージェント自身の Safe、オーナー、残高、次の nonce を返す。","security":[{"httpSignature":[]}],"responses":{"200":{"description":"エージェントの情報","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Agent"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"リクエストが多すぎる","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/transaction/quote":{"post":{"operationId":"quoteTransaction","tags":["transaction"],"summary":"送金を見積もる","description":"SafeTx に入れる nonce と、ガスの払い戻し条件（baseGas、gasPrice、refundReceiver）を返す。リレイヤーが立て替えたガス代は、この条件で Safe から払い戻される。","security":[{"httpSignature":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Call"}}}},"responses":{"200":{"description":"見積もり","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"入力が不正","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"リクエストが多すぎる","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/transaction":{"post":{"operationId":"submitTransaction","tags":["transaction"],"summary":"送金する","description":"エージェントが署名した SafeTx を、リレイヤーからガス代を立て替えて送信する。確定を待って結果を返し、待ちきれなければ pending を返す。","security":[{"httpSignature":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionRequest"}}}},"responses":{"200":{"description":"送信した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"400":{"description":"入力や SafeTx の署名が不正","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"revert が続いて中継を止めているか、送金額の上限を超える","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"409":{"description":"作成費用が未入金か、nonce の不一致か、見積もりが古い","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"422":{"description":"送信前のシミュレーションで revert したか、ガス量が上限を超える","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"リクエストが多すぎる","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"503":{"description":"ガス代が高く、Safe を作成できない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/transaction/{hash}":{"get":{"operationId":"getTransaction","tags":["transaction"],"summary":"送金の状態を取得する","description":"自分が送信した tx の状態を返す。","security":[{"httpSignature":[]}],"parameters":[{"schema":{"type":"string","pattern":"^0x[0-9a-fA-F]{64}$","example":"0xabababababababababababababababababababababababababababababababab"},"required":true,"name":"hash","in":"path"}],"responses":{"200":{"description":"tx の状態","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"自分の tx ではない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"リクエストが多すぎる","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{}}