{"openapi":"3.1.0","info":{"title":"AI Bot Identity Registry API","description":"Authentication model: this API uses signed request payloads (not bearer tokens).\n\nFor mutation endpoints, clients must include exactly one authorization mode:\n- `proof`: single signer JWS\n- `proof_set`: multi-signer JWS set for m-of-n policy\n\nThe server verifies signatures over the JCS-canonicalized request payload with proof fields removed, resolves signer keys (including delegated controllers), and enforces policy thresholds.\n\nAuth-required mutation endpoints:\n- POST /v1/bots\n- PATCH /v1/bots/{bot_id}\n- POST /v1/bots/{bot_id}/keys\n- DELETE /v1/bots/{bot_id}/keys/{key_id}\n- POST /v1/bots/{bot_id}/rotate\n- POST /v1/bots/{bot_id}/revoke\n- POST /v1/attestations (attestation.signature must verify against issuer key)","license":{"name":"MIT","identifier":"MIT"},"version":"0.1.0"},"paths":{"/health":{"get":{"tags":["bot-registry"],"summary":"Health check (public)","operationId":"health","responses":{"200":{"description":"Liveness endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1":{"get":{"tags":["bot-registry"],"summary":"Service metadata (public)","operationId":"api_root","responses":{"200":{"description":"Service metadata and docs links.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootResponse"}}}}}}},"/v1/attestations":{"post":{"tags":["bot-registry"],"summary":"Publish attestation (signature required)","description":"Attach an attestation to a subject bot. The attestation itself must include a valid issuer signature in `attestation.signature`.","operationId":"publish_attestation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishAttestationRequest"}}},"required":true},"responses":{"201":{"description":"Attestation published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Attestation"}}}},"400":{"description":"Invalid attestation signature or payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Subject or issuer bot not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots":{"post":{"tags":["bot-registry"],"summary":"Create bot (auth required)","description":"Create a new bot identity record. Auth is proof-based: provide either `proof` (single signature) or `proof_set` (multi-signature), but not both. Signatures are verified over the JCS-canonicalized payload with proof fields removed.","operationId":"create_bot","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}},"required":true},"responses":{"201":{"description":"Bot created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid payload, signature, or policy inputs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Bot already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots/{bot_id}":{"get":{"tags":["bot-registry"],"summary":"Get bot (public)","operationId":"get_bot","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Bot record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"404":{"description":"Bot not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["bot-registry"],"summary":"Update bot (auth required)","description":"Update mutable fields on a bot record. Requires either `proof` or `proof_set`. The server verifies signatures from `proof` or `proof_set`, resolves controller keys when used, and enforces the bot's operation policy (including m-of-n threshold rules).","operationId":"update_bot","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}},"required":true},"responses":{"200":{"description":"Updated bot record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid payload/signature or policy threshold not met.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bot not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots/{bot_id}/keys":{"post":{"tags":["bot-registry"],"summary":"Add key (auth required)","description":"Add a new key to a bot. Requires either `proof` or `proof_set`; signatures are verified against the updated canonical payload and policy.","operationId":"add_key","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddKeyRequest"}}},"required":true},"responses":{"200":{"description":"Updated bot record with new key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid request/signature/policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bot not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Key ID or key material already exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots/{bot_id}/keys/{key_id}":{"delete":{"tags":["bot-registry"],"summary":"Revoke key (auth required)","description":"Revoke a key for a bot. Requires either `proof` or `proof_set`; the signer set must satisfy the policy for `revoke_key`.","operationId":"remove_key","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}},{"name":"key_id","in":"path","description":"Signing key identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveKeyRequest"}}},"required":true},"responses":{"200":{"description":"Updated bot record with key revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid request/signature/policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bot or key not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots/{bot_id}/revoke":{"post":{"tags":["bot-registry"],"summary":"Revoke bot (auth required)","description":"Revoke an entire bot identity. Requires either `proof` or `proof_set`; signatures must satisfy `revoke_bot` policy.","operationId":"revoke_bot","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeBotRequest"}}},"required":true},"responses":{"200":{"description":"Bot revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid request/signature/policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bot not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/bots/{bot_id}/rotate":{"post":{"tags":["bot-registry"],"summary":"Rotate key (auth required)","description":"Rotate a bot signing key in one operation (revoke old + add new). Requires either `proof` or `proof_set` and policy approval.","operationId":"rotate_key","parameters":[{"name":"bot_id","in":"path","description":"Bot identifier","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateKeyRequest"}}},"required":true},"responses":{"200":{"description":"Updated bot record with rotated key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotRecord"}}}},"400":{"description":"Invalid request/signature/policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Bot or old key not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"New key conflicts with an existing key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/nonce":{"get":{"tags":["bot-registry"],"summary":"Issue nonce (public)","operationId":"get_nonce","responses":{"200":{"description":"Fresh nonce for anti-replay usage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NonceResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/search":{"get":{"tags":["bot-registry"],"summary":"Search bots (public)","operationId":"search","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string"},"example":"alpha"},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/BotStatus"}},{"name":"capability","in":"query","required":false,"schema":{"type":"string"},"example":"calendar.read"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1},"example":50}],"responses":{"200":{"description":"Search results.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/stats":{"get":{"tags":["bot-registry"],"summary":"Registry stats (public)","operationId":"registry_stats","responses":{"200":{"description":"Current registry counts and health-adjacent metrics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistryStatsResponse"}}}},"500":{"description":"Server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"AddKeyRequest":{"type":"object","required":["public_key"],"properties":{"proof":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Proof","description":"Single-signature authorization proof for this mutation."}]},"proof_set":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProofItem"},"description":"Multi-signature authorization proofs for threshold policy checks."},"public_key":{"$ref":"#/components/schemas/PublicKey"}}},"Attestation":{"type":"object","required":["issuer_bot_id","type","statement","signature"],"properties":{"attestation_id":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"issued_at":{"type":["string","null"]},"issuer_bot_id":{"type":"string"},"signature":{"$ref":"#/components/schemas/SignatureRef"},"statement":{},"type":{"type":"string"}}},"BotRecord":{"type":"object","required":["status","public_keys"],"properties":{"attestations":{"type":["array","null"],"items":{"$ref":"#/components/schemas/Attestation"}},"bot_id":{"type":["string","null"]},"capabilities":{"type":["array","null"],"items":{"type":"string"}},"controllers":{"type":["array","null"],"items":{"$ref":"#/components/schemas/Controller"}},"created_at":{"type":["string","null"]},"description":{"type":["string","null"]},"display_name":{"type":["string","null"]},"endpoints":{"type":["array","null"],"items":{"$ref":"#/components/schemas/Endpoint"}},"evidence":{"type":["array","null"],"items":{"$ref":"#/components/schemas/Evidence"}},"owner":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Owner"}]},"parent_bot_id":{"type":["string","null"]},"policy":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Policy"}]},"proof":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Proof","description":"Single-signature authorization proof for bot mutations.\nThe JWS signs the JCS-canonicalized payload with proof fields removed."}]},"proof_set":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProofItem"},"description":"Multi-signature authorization proofs for m-of-n policy operations.\nEach signer must be unique by `(controller_bot_id, key_id)`."},"public_keys":{"type":"array","items":{"$ref":"#/components/schemas/PublicKey"}},"status":{"$ref":"#/components/schemas/BotStatus"},"updated_at":{"type":["string","null"]},"version":{"type":["integer","null"],"format":"int64","minimum":0}}},"BotStatus":{"type":"string","enum":["active","deprecated","revoked"]},"Controller":{"type":"object","required":["controller_bot_id"],"properties":{"controller_bot_id":{"type":"string"},"delegation":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Delegation"}]},"role":{"type":["string","null"]}}},"Delegation":{"type":"object","required":["allows"],"properties":{"allows":{"type":"array","items":{"type":"string"}},"constraints":{"type":["object","null"],"additionalProperties":{"type":"array","items":{"type":"string"}},"propertyNames":{"type":"string"}}}},"Endpoint":{"type":"object","required":["type","url"],"properties":{"auth":{"type":["string","null"]},"type":{"type":"string"},"url":{"type":"string"}}},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"Evidence":{"type":"object","required":["type","uri"],"properties":{"type":{"type":"string"},"uri":{"type":"string"}}},"HealthResponse":{"type":"object","required":["status"],"properties":{"status":{"type":"string"}}},"KeyOrigin":{"type":"object","required":["type"],"properties":{"derivation_path":{"type":["string","null"]},"master_fingerprint":{"type":["string","null"]},"note":{"type":["string","null"]},"scheme":{"type":["string","null"]},"type":{"type":"string"}}},"KeyRef":{"type":"object","required":["key_id"],"properties":{"controller_bot_id":{"type":["string","null"]},"key_id":{"type":"string"}}},"NonceResponse":{"type":"object","required":["nonce"],"properties":{"nonce":{"type":"string"}}},"Owner":{"type":"object","required":["type"],"properties":{"contact_uri":{"type":["string","null"]},"id":{"type":["string","null"]},"type":{"type":"string"}}},"Policy":{"type":"object","required":["version","updated_at","rules","signer_sets"],"properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/PolicyRule"}},"signer_sets":{"type":"array","items":{"$ref":"#/components/schemas/SignerSet"}},"updated_at":{"type":"string"},"version":{"type":"integer","format":"int64","minimum":0}}},"PolicyRule":{"type":"object","required":["operation","type","m","set_id"],"properties":{"m":{"type":"integer","format":"int32","minimum":0},"operation":{"type":"string"},"set_id":{"type":"string"},"type":{"type":"string"}}},"Proof":{"type":"object","required":["algorithm","key_id","created","jws"],"properties":{"algorithm":{"type":"string"},"created":{"type":"string"},"jws":{"type":"string"},"key_id":{"type":"string"},"nonce":{"type":["string","null"]}}},"ProofItem":{"type":"object","required":["algorithm","key_ref","created","jws"],"properties":{"algorithm":{"type":"string"},"created":{"type":"string"},"jws":{"type":"string"},"key_ref":{"$ref":"#/components/schemas/KeyRef"},"nonce":{"type":["string","null"]}}},"PublicKey":{"type":"object","required":["key_id","algorithm","public_key_multibase","purpose"],"properties":{"algorithm":{"type":"string"},"key_id":{"type":"string"},"origin":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/KeyOrigin"}]},"primary":{"type":["boolean","null"]},"public_key_multibase":{"type":"string"},"purpose":{"type":"array","items":{"type":"string"}},"revocation_reason":{"type":["string","null"]},"revoked_at":{"type":["string","null"]},"valid_from":{"type":["string","null"]},"valid_to":{"type":["string","null"]}}},"PublishAttestationRequest":{"type":"object","required":["subject_bot_id","attestation"],"properties":{"attestation":{"$ref":"#/components/schemas/Attestation"},"subject_bot_id":{"type":"string"}}},"RegistryStatsResponse":{"type":"object","required":["total_bots","active_bots","deprecated_bots","revoked_bots","total_keys","active_keys","revoked_keys","total_attestations","total_controllers","server_time"],"properties":{"active_bots":{"type":"integer","minimum":0},"active_keys":{"type":"integer","minimum":0},"deprecated_bots":{"type":"integer","minimum":0},"last_bot_update":{"type":["string","null"]},"revoked_bots":{"type":"integer","minimum":0},"revoked_keys":{"type":"integer","minimum":0},"server_time":{"type":"string"},"total_attestations":{"type":"integer","minimum":0},"total_bots":{"type":"integer","minimum":0},"total_controllers":{"type":"integer","minimum":0},"total_keys":{"type":"integer","minimum":0}}},"RemoveKeyRequest":{"type":"object","properties":{"proof":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Proof","description":"Single-signature authorization proof for this mutation."}]},"proof_set":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProofItem"},"description":"Multi-signature authorization proofs for threshold policy checks."},"reason":{"type":["string","null"]}}},"RevokeBotRequest":{"type":"object","properties":{"proof":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Proof","description":"Single-signature authorization proof for this mutation."}]},"proof_set":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProofItem"},"description":"Multi-signature authorization proofs for threshold policy checks."},"reason":{"type":["string","null"]}}},"RootResponse":{"type":"object","required":["service","status","docs","openapi","swagger","health","stats","install"],"properties":{"docs":{"type":"string"},"health":{"type":"string"},"install":{"type":"string"},"openapi":{"type":"string"},"service":{"type":"string"},"stats":{"type":"string"},"status":{"type":"string"},"swagger":{"type":"string"}}},"RotateKeyRequest":{"type":"object","required":["old_key_id","new_key"],"properties":{"new_key":{"$ref":"#/components/schemas/PublicKey"},"old_key_id":{"type":"string"},"proof":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Proof","description":"Single-signature authorization proof for this mutation."}]},"proof_set":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ProofItem"},"description":"Multi-signature authorization proofs for threshold policy checks."}}},"SearchResponse":{"type":"object","required":["count","results"],"properties":{"count":{"type":"integer","minimum":0},"results":{"type":"array","items":{"$ref":"#/components/schemas/BotRecord"}}}},"SignatureRef":{"type":"object","required":["algorithm","key_id","jws"],"properties":{"algorithm":{"type":"string"},"jws":{"type":"string"},"key_id":{"type":"string"}}},"SignerRef":{"type":"object","required":["ref"],"properties":{"ref":{"$ref":"#/components/schemas/KeyRef"}}},"SignerSet":{"type":"object","required":["set_id","members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/SignerRef"}},"set_id":{"type":"string"}}}}},"tags":[{"name":"bot-registry","description":"AI Bot Identity Registry endpoints. Mutation routes require proof-based signature auth."}]}