{"openapi":"3.1.0","info":{"title":"nyquist API","version":"1.0.0","description":"自律的なエージェントのための仮想通貨ウォレットの API。エージェントは人間を介さずに登録し、自分の署名だけで Safe から送金する。nyquist は署名を中継してガス代を立て替え、Safe から払い戻しを受ける。人間は任意で SIWE でログインし、アカウントでエージェントを管理できる。","contact":{"name":"osaxyz","url":"https://github.com/osaxyz/nyquist"},"license":{"name":"Proprietary","url":"https://github.com/osaxyz/nyquist"}},"servers":[{"url":"http://localhost:8787","description":"ローカル開発"}],"tags":[{"name":"session","description":"会員登録とログイン"},{"name":"account","description":"テナントと配下のエージェント"},{"name":"member","description":"アカウントのメンバー"},{"name":"enrollment","description":"エージェントの登録トークン"},{"name":"agent","description":"エージェント自身の登録と情報"},{"name":"transaction","description":"送金"}],"components":{"securitySchemes":{"session":{"type":"http","scheme":"bearer","description":"POST /api/v1/session で SIWE（EIP-4361）によって発行したセッショントークン。人間の会員が使う。"},"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":{"Nonce":{"type":"object","properties":{"nonce":{"type":"string"},"expiresAt":{"type":"string"}},"required":["nonce","expiresAt"],"description":"SIWE メッセージに入れる nonce"},"Problem":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"required":["type","title","status"]},"NonceRequest":{"type":"object","properties":{"address":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"}},"required":["address"]},"Session":{"type":"object","properties":{"token":{"type":"string"},"address":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"expiresAt":{"type":"string"}},"required":["token","address","expiresAt"],"description":"Authorization: Bearer に入れるセッショントークン"},"SessionRequest":{"type":"object","properties":{"message":{"type":"string","maxLength":4000,"description":"EIP-4361 の SIWE メッセージ"},"signature":{"type":"string","pattern":"^0x([0-9a-fA-F]{2})*$","example":"0x","description":"メッセージへの署名。スマートコントラクトウォレットの署名も受け付ける"}},"required":["message","signature"]},"User":{"type":"object","properties":{"address":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"accounts":{"type":"array","items":{"$ref":"#/components/schemas/Membership"}}},"required":["address","accounts"]},"Membership":{"type":"object","properties":{"accountId":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["member","admin","owner"]}},"required":["accountId","name","role"]},"Account":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"owner":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"role":{"type":"string","enum":["member","admin","owner"],"description":"リクエストした会員の役割"},"createdAt":{"type":"string"}},"required":["id","name","owner","role","createdAt"]},"AccountCreate":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64}},"required":["name"]},"Member":{"type":"object","properties":{"address":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"role":{"type":"string","enum":["member","admin","owner"]},"createdAt":{"type":"string"}},"required":["address","role","createdAt"]},"MemberPut":{"type":"object","properties":{"role":{"type":"string","enum":["member","admin"]}},"required":["role"]},"EnrollmentCreated":{"allOf":[{"$ref":"#/components/schemas/Enrollment"},{"type":"object","properties":{"token":{"type":"string","description":"エージェントに渡す登録トークン。この応答でしか返さない"}},"required":["token"]}]},"Enrollment":{"type":"object","properties":{"id":{"type":"string"},"maxUses":{"type":"integer"},"uses":{"type":"integer"},"expiresAt":{"type":"string"},"revoked":{"type":"boolean"},"createdAt":{"type":"string"}},"required":["id","maxUses","uses","expiresAt","revoked","createdAt"]},"EnrollmentCreate":{"type":"object","properties":{"maxUses":{"type":"integer","minimum":1,"default":1},"expiresInSeconds":{"type":"integer","minimum":60,"default":86400}}},"Agent":{"type":"object","properties":{"id":{"type":"string","description":"公開鍵の RFC 7638 サムプリント。署名の keyid と同じ"},"accountId":{"type":["string","null"],"description":"所属するアカウント。引き取られるまでは null"},"status":{"type":"string","enum":["active","suspended"],"description":"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":["string","null"],"example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed","description":"アカウントの owner。エージェントが addOwnerWithThreshold で Safe のオーナーに加えるかを決める"},"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 からリレイヤーへ払う作成費用"},"createdAt":{"type":"string"}},"required":["id","accountId","status","signer","safe","owners","threshold","recoveryOwner","deployed","balanceWei","nonce","deploymentFeeWei","createdAt"]},"ClaimRedeem":{"type":"object","properties":{"code":{"type":"string","maxLength":200}},"required":["code"]},"AgentSummary":{"type":"object","properties":{"id":{"type":"string"},"signer":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"safe":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"status":{"type":"string","enum":["active","suspended"],"description":"suspended の間は nyquist が中継しない。エージェントは自分でガスを払えば送金できる"},"createdAt":{"type":"string"}},"required":["id","signer","safe","status","createdAt"]},"AgentStatusBody":{"type":"object","properties":{"status":{"type":"string","enum":["active","suspended"],"description":"suspended の間は nyquist が中継しない。エージェントは自分でガスを払えば送金できる"}},"required":["status"]},"RegisterAgent":{"type":"object","properties":{"publicKey":{"$ref":"#/components/schemas/PublicJwk"},"signer":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed","description":"Safe の唯一のオーナーになり、SafeTx に署名するアドレス"},"enrollment":{"type":"string","maxLength":200,"description":"アカウントが発行した登録トークン。省略すると、どのアカウントにも属さずに登録する","example":"nqe_<accountId>_<secret>"}},"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 公開鍵"},"Claim":{"type":"object","properties":{"code":{"type":"string"},"expiresAt":{"type":"string"}},"required":["code","expiresAt"],"description":"人間に渡す引き取りコード。一度だけ使える"},"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 から払い戻されるガス代の上限の目安"}},"required":["safe","chainId","nonce","safeTxGas","baseGas","gasPrice","gasToken","refundReceiver","safeTxHash","maxFeeWei"],"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"],"description":"failed は Safe 内の呼び出しが失敗したが、ガス代は払い戻された状態"}},"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/session/nonce":{"post":{"operationId":"createNonce","tags":["session"],"summary":"SIWE の nonce を発行する","description":"ログインするアドレスに対して、SIWE メッセージに入れる nonce を発行する。初めてのアドレスなら、これが会員登録の始まりになる。","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NonceRequest"}}}},"responses":{"201":{"description":"発行した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Nonce"}}}},"400":{"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"}}}}}}},"/api/v1/session":{"post":{"operationId":"createSession","tags":["session"],"summary":"SIWE でログインする","description":"EIP-4361 のメッセージと署名を検証し、セッショントークンを発行する。domain はこの API のホスト、uri はこの API のオリジン、chainId は nyquist のチェーンにする。","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRequest"}}}},"responses":{"201":{"description":"ログインした","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}},"400":{"description":"入力が不正","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"SIWE のメッセージか署名が不正","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"}}}}}},"delete":{"operationId":"deleteSession","tags":["session"],"summary":"ログアウトする","description":"送ったセッショントークンを失効させる。","security":[{"session":[]}],"responses":{"204":{"description":"失効させた"},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/user":{"get":{"operationId":"getUser","tags":["session"],"summary":"自分の会員情報を取得する","description":"ログイン中のアドレスと、所属するアカウントの一覧を返す。","security":[{"session":[]}],"responses":{"200":{"description":"会員情報","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account":{"post":{"operationId":"createAccount","tags":["account"],"summary":"アカウントを作る","description":"テナントとなるアカウントを作る。作った会員が owner になり、そのアドレスが配下の Safe の復旧用オーナーになる。","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountCreate"}}}},"responses":{"201":{"description":"作成した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"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"}}}},"409":{"description":"作成できるアカウント数が上限","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}":{"get":{"operationId":"getAccount","tags":["account"],"summary":"アカウントを取得する","description":"アカウントの情報と、リクエストした会員の役割を返す。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"アカウント","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/member":{"get":{"operationId":"listMember","tags":["member"],"summary":"メンバーを一覧する","description":"アカウントのメンバーと役割を返す。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"メンバーの一覧","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}}}},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/member/{address}":{"put":{"operationId":"putMember","tags":["member"],"summary":"メンバーを追加、変更する","description":"アドレスを admin か member として追加するか、役割を変える。owner だけが操作できる。追加された人は SIWE でログインすると、このアカウントを使える。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"},{"schema":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"required":true,"name":"address","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberPut"}}}},"responses":{"200":{"description":"追加、変更した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Member"}}}},"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":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","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"}}}}}},"delete":{"operationId":"deleteMember","tags":["member"],"summary":"メンバーを外す","description":"owner だけが操作できる。owner 自身は外せない。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"},{"schema":{"type":"string","example":"0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"},"required":true,"name":"address","in":"path"}],"responses":{"204":{"description":"外した"},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/enrollment":{"post":{"operationId":"createEnrollment","tags":["enrollment"],"summary":"登録トークンを発行する","description":"エージェントをこのアカウントに登録するためのトークンを発行する。admin 以上が操作できる。トークンはこの応答でしか返さない。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentCreate"}}}},"responses":{"201":{"description":"発行した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentCreated"}}}},"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":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}},"get":{"operationId":"listEnrollment","tags":["enrollment"],"summary":"登録トークンを一覧する","description":"発行済みの登録トークンの使用状況を返す。トークン本体は返さない。admin 以上が操作できる。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"登録トークンの一覧","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Enrollment"}}}}},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/enrollment/{enrollmentId}":{"delete":{"operationId":"revokeEnrollment","tags":["enrollment"],"summary":"登録トークンを失効させる","description":"登録済みのエージェントには影響しない。admin 以上が操作できる。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"},{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"enrollmentId","in":"path"}],"responses":{"204":{"description":"失効させた"},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/claim":{"post":{"operationId":"claimAgent","tags":["account"],"summary":"エージェントを引き取る","description":"エージェントが発行した引き取りコードで、エージェントをこのアカウントに加える。admin 以上が操作できる。Safe のオーナーは変わらない。アカウントの owner を Safe の復旧用オーナーに加えるかは、エージェントが addOwnerWithThreshold の tx で決める。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRedeem"}}}},"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":"役割が足りないか、引き取りコードが無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","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"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/agent":{"get":{"operationId":"listAgent","tags":["account"],"summary":"エージェントを一覧する","description":"アカウントに登録されたエージェントを返す。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"}],"responses":{"200":{"description":"エージェントの一覧","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgentSummary"}}}}},"401":{"description":"セッショントークンがないか無効","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"アカウントがないか、所属していない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/account/{accountId}/agent/{agentId}":{"get":{"operationId":"getAccountAgent","tags":["account"],"summary":"エージェントを取得する","description":"エージェントの Safe、オーナー、残高、次の nonce を返す。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$"},"required":true,"name":"agentId","in":"path"}],"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"}}}},"403":{"description":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"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/account/{accountId}/agent/{agentId}/status":{"put":{"operationId":"updateAgentStatus","tags":["account"],"summary":"中継を停止、再開する","description":"suspended にすると、nyquist はそのエージェントの送金を中継しない。admin 以上が操作できる。資金を止めるには、Safe の復旧用オーナーがエージェントを Safe から外す。","security":[{"session":[]}],"parameters":[{"schema":{"type":"string","pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"},"required":true,"name":"accountId","in":"path"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{43}$"},"required":true,"name":"agentId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentStatusBody"}}}},"responses":{"200":{"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":"役割が足りない","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"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/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":"登録トークンを添えたが無効","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"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/agent/claim":{"post":{"operationId":"createClaim","tags":["agent"],"summary":"引き取りコードを発行する","description":"人間がこのエージェントを自分のアカウントに引き取るためのコードを発行する。発行し直すと前のコードは使えなくなる。アカウントに所属済みなら発行できない。","security":[{"httpSignature":[]}],"responses":{"201":{"description":"発行した","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Claim"}}}},"401":{"description":"署名がない、不正、期限切れ、再送、または未登録のエージェント","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"}}}}}}},"/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"}}}},"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":"アカウントの管理者が中継を止めている","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"}}}},"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"}}}},"502":{"description":"RPC の失敗","content":{"application/problem+json; charset=utf-8":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}}},"webhooks":{}}