diff --git a/src/keria/app/agenting.py b/src/keria/app/agenting.py index caae9c3f..cb0873de 100644 --- a/src/keria/app/agenting.py +++ b/src/keria/app/agenting.py @@ -904,11 +904,11 @@ def on_get(req, rep): - Key Event Log parameters: - in: path - name: prefix + name: pre + description: qb64 identifier prefix of KEL to load schema: type: string required: true - description: qb64 identifier prefix of KEL to load responses: 200: description: Key event log and key state of identifier @@ -955,7 +955,7 @@ def on_get(req, rep): - Key Event Log parameters: - in: path - name: prefix + name: pre schema: type: string required: true @@ -1013,12 +1013,13 @@ def on_post(req, rep): content: application/json: schema: - description: OOBI - properties: + description: OOBI + oneOf: + - type: object + properties: oobialias: type: string description: alias to assign to the identifier resolved from this OOBI - required: false url: type: string description: URL OOBI @@ -1165,13 +1166,24 @@ def on_post(req, rep): identifier along with the KEL and all associated signatures and receipts tags: - Query - parameters: - - in: body - name: pre - schema: - type: string - required: true - description: qb64 identifier prefix of KEL to load + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - pre + properties: + pre: + type: string + description: qb64 identifier prefix of KEL to load + anchor: + type: string + description: Anchor + sn: + type: string + description: Serial number responses: 200: description: Key event log and key state of identifier diff --git a/src/keria/app/aiding.py b/src/keria/app/aiding.py index fa8ef21a..ec2fa9ac 100644 --- a/src/keria/app/aiding.py +++ b/src/keria/app/aiding.py @@ -86,6 +86,25 @@ def on_get(self, _, rep, caid): rep: falcon.Response HTTP response caid(str): qb64 identifier prefix of Controller + --- + summary: Retrieve key state record of an agent by controller AID. + description: This endpoint retrieves the key state record for a given controller of an agent. + tags: + - Agent + parameters: + - in: path + name: caid + schema: + type: string + required: true + description: The qb64 identifier prefix of Controller. + responses: + 200: + description: Successfully retrieved the key state record. + 400: + description: Bad request. This could be due to an invalid agent or controller configuration. + 404: + description: The requested controller or agent was not found. """ agent = self.agency.get(caid) if agent is None: @@ -133,6 +152,53 @@ def on_put(self, req, rep, caid): rep (Response): falcon.Response HTTP response caid(str): qb64 identifier prefix of Controller + --- + summary: Update agent configuration by controller AID. + description: This endpoint updates the agent configuration based on the provided request parameters and body. + tags: + - Agent + parameters: + - in: path + name: caid + schema: + type: string + required: true + description: The qb64 identifier prefix of Controller. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - rot + - sigs + - sxlt + - kyes + properties: + rot: + type: object + description: The rotation event. + sigs: + type: array + items: + type: string + description: The signatures. + sxlt: + type: string + description: The salty parameters. + keys: + type: object + description: The keys. + responses: + 204: + description: Successfully updated the agent configuration. + 400: + description: Bad request. This could be due to missing or invalid parameters. + 404: + description: The requested agent was not found. + 500: + description: Internal server error. This could be due to an issue with updating the agent configuration. """ agent = self.agency.get(caid) if agent is None: @@ -262,6 +328,24 @@ def on_get(req, rep): req: falcon.Request HTTP request rep: falcon.Response HTTP response + --- + summary: Retrieve a list of identifiers associated with the agent. + description: This endpoint retrieves a list of identifiers associated with the agent. + It supports pagination through the 'Range' header. + tags: + - Identifier + parameters: + - in: header + name: Range + schema: + type: string + required: false + description: The 'Range' header is used for pagination. The default range is 0-9. + responses: + 200: + description: Successfully retrieved identifiers. + 206: + description: Successfully retrieved identifiers within the specified range. """ agent = req.context.agent res = [] @@ -308,6 +392,45 @@ def on_post(req, rep): req (Request): falcon.Request HTTP request object rep (Response): falcon.Response HTTP response object + --- + summary: Create an identifier. + description: This endpoint creates an identifier with the provided inception event, name, and signatures. + tags: + - Identifier + requestBody: + content: + application/json: + schema: + type: object + properties: + icp: + type: object + description: The inception event for the identifier. + name: + type: string + description: The name of the identifier. + sigs: + type: array + items: + type: string + description: The signatures for the inception event. + group: + type: object + description: Multisig group information. + salty: + type: object + description: Salty parameters. + randy: + type: object + description: Randomly generated materials. + extern: + type: object + description: External parameters. + responses: + 202: + description: Identifier creation is in progress. The response is a long running operation. + 400: + description: Bad request. This could be due to missing or invalid parameters. """ agent = req.context.agent try: @@ -449,8 +572,27 @@ def on_get(req, rep, name): Parameters: req: falcon.Request HTTP request rep: falcon.Response HTTP response - name (str): human readable name for Hab to GET + name (str): human-readable name for Hab to GET + --- + summary: Retrieve an identifier. + description: This endpoint retrieves an identifier by its human-readable name. + tags: + - Identifier + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The human-readable name of the identifier. + responses: + 200: + description: Successfully retrieved the identifier details. + 400: + description: Bad request. This could be due to a missing or invalid name parameter. + 404: + description: The requested identifier was not found. """ if not name: raise falcon.HTTPBadRequest(description="name is required") @@ -473,6 +615,36 @@ def on_put(self, req, rep, name): rep (Response): falcon.Response HTTP response object name (str): human readable name for Hab to rename + --- + summary: Rename an identifier. + description: This endpoint renames an identifier with the provided new name. + tags: + - Identifier + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The current human-readable name of the identifier. + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: The new name for the identifier. + required: + - name + responses: + 200: + description: Successfully renamed the identifier and returns the updated information. + 400: + description: Bad request. This could be due to a missing or invalid name parameter. + 404: + description: The requested identifier was not found. """ if not name: raise falcon.HTTPBadRequest(description="name is required") @@ -502,8 +674,26 @@ def on_delete(self, req, rep, name): Parameters: req (Request): falcon.Request HTTP request object rep (Response): falcon.Response HTTP response object - name (str): human readable name for Hab to delete - + name (str): human-readable name for Hab to delete + --- + summary: Delete an identifier. + description: This endpoint deletes an identifier by its name. + tags: + - Identifier + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The human-readable name of the identifier. + responses: + 200: + description: Successfully deleted the identifier. + 400: + description: Bad request. This could be due to a missing or invalid name parameter. + 404: + description: The requested identifier was not found. """ if not name: raise falcon.HTTPBadRequest(description="name is required") @@ -520,8 +710,42 @@ def on_post(self, req, rep, name): Parameters: req (Request): falcon.Request HTTP request object rep (Response): falcon.Response HTTP response object - name (str): human readable name for Hab to rotate or interact + name (str): human-readable name for Hab to rotate or interact + --- + summary: Process identifier events. + description: This endpoint handles the 'rot' or 'ixn' events of an identifier based on the provided request. + tags: + - Identifier + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The human-readable name of the identifier. + requestBody: + content: + application/json: + schema: + type: object + properties: + rot: + type: object + description: The rotation event details. + ixn: + type: object + description: The interaction event details. + oneOf: + - required: + - rot + - required: + - ixn + responses: + 200: + description: Successfully processed the identifier's event. + 400: + description: Bad request. This could be due to missing or invalid parameters. """ if not name: raise falcon.HTTPBadRequest(description="name is required") @@ -802,6 +1026,38 @@ def on_get(req, rep, name=None, aid=None, role=None): aid (str): aid to use instead of name role (str): optional role to search for + --- + summary: Retrieve end roles. + description: This endpoint retrieves the end roles associated with AID or human-readable name. + It can also filter the end roles based on a specific role. + tags: + - End Role + parameters: + - in: path + name: name + schema: + type: string + required: false + description: The human-readable name of the identifier. + - in: path + name: aid + schema: + type: string + required: false + description: The identifier (AID). + - in: path + name: role + schema: + type: string + required: false + description: The specific role to filter the end roles. + responses: + 200: + description: Successfully retrieved the end roles. The response body contains the end roles. + 400: + description: Bad request. This could be due to missing or invalid parameters. + 404: + description: The requested identifier was not found. """ agent = req.context.agent @@ -839,6 +1095,45 @@ def on_post(req, rep, name, aid=None, role=None): aid (str): Not supported for POST. If provided, a 404 is returned role (str): Not supported for POST. If provided, a 404 is returned + --- + summary: Create an end role. + description: This endpoint creates an end role associated with a given identifier (AID) or name. + tags: + - End Role + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The human-readable name of the identifier. + - in: path + name: aid + schema: + type: string + required: false + description: Not supported for POST. If provided, a 404 is returned. + requestBody: + content: + application/json: + schema: + type: object + properties: + rpy: + type: object + description: The reply object. + sigs: + type: array + items: + type: string + description: The signatures. + responses: + 202: + description: Accepted. The end role creation is in progress. + 400: + description: Bad request. This could be due to missing or invalid parameters. + 404: + description: Not found. The requested identifier was not found. """ if role is not None or aid is not None: raise falcon.HTTPNotFound(description="route not found") @@ -888,6 +1183,31 @@ class RpyEscrowCollectionEnd: @staticmethod def on_get(req, rep): + """ + GET endpoint for reply escrow collection + + Parameters: + req (falcon.Request): The request object. + rep (falcon.Response): The response object. + + --- + summary: Retrieve reply escrows. + description: This endpoint retrieves the reply escrows and can filter the collection based on a specific route. + tags: + - Reply Escrow + parameters: + - in: query + name: route + schema: + type: string + required: false + description: The specific route to filter the reply escrow collection. + responses: + 200: + description: Successfully retrieved the reply escrows. + 400: + description: Bad request. This could be due to missing or invalid parameters. + """ agent = req.context.agent # Optional Route parameter @@ -923,7 +1243,7 @@ def on_get(req, rep): - in: query name: strength schema: - type: int + type: integer description: cryptographic strength of word list required: false responses: @@ -1041,7 +1361,7 @@ def on_post(req, rep, source): - Challenge/Response parameters: - in: path - name: name + name: source schema: type: string required: true @@ -1095,12 +1415,12 @@ def on_put(req, rep, source): tags: - Challenge/Response parameters: - - in: path - name: name - schema: - type: string - required: true - description: Human readable alias for the identifier to create + - in: path + name: source + schema: + type: string + required: true + description: Human readable alias for the identifier to create requestBody: required: true content: diff --git a/src/keria/app/credentialing.py b/src/keria/app/credentialing.py index 8201b3d7..6be45528 100644 --- a/src/keria/app/credentialing.py +++ b/src/keria/app/credentialing.py @@ -393,12 +393,6 @@ def on_post(req, rep): tags: - Credentials parameters: - - in: path - name: aid - schema: - type: string - required: true - description: identifier to load credentials for - in: query name: type schema: @@ -604,12 +598,6 @@ def on_get(req, rep, said): tags: - Credentials parameters: - - in: path - name: aid - schema: - type: string - required: true - description: The identifier to create - in: path name: said schema: @@ -624,7 +612,8 @@ def on_get(req, rep, said): schema: description: Credential type: object - + 400: + description: The requested credential was not found. """ agent = req.context.agent accept = req.get_header("accept") diff --git a/src/keria/core/longrunning.py b/src/keria/core/longrunning.py index 06016184..35fc1ff7 100644 --- a/src/keria/core/longrunning.py +++ b/src/keria/core/longrunning.py @@ -427,11 +427,23 @@ def on_get(req, rep): description: filter list of long running operations by type responses: 200: + description: list of long running operations content: application/json: schema: type: array - + items: + properties: + name: + type: string + metadata: + type: object + done: + type: boolean + error: + type: object + response: + type: object """ agent = req.context.agent type = req.params.get("type") @@ -454,6 +466,23 @@ def on_get(req, rep, name): req (Request): Falcon HTTP Request object rep (Response): Falcon HTTP Response object name (str): Long running operation resource name to load + --- + summary: Retrieve a specific long running operation. + description: This endpoint retrieves the status of a long running operation by its name. + tags: + - Operation + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The name of the long running operation to retrieve. + responses: + 200: + description: Successfully retrieved the status of the long running operation. + 404: + description: The requested long running operation was not found. """ agent = req.context.agent @@ -472,7 +501,25 @@ def on_delete(req, rep, name): req (Request): Falcon HTTP Request object rep (Response): Falcon HTTP Response object name (str): Long running operation resource name to load - + --- + summary: Remove a specific long running operation. + description: This endpoint removes a long running operation by its name. + tags: + - Operation + parameters: + - in: path + name: name + schema: + type: string + required: true + description: The name of the long running operation to remove. + responses: + 204: + description: Successfully removed the long running operation. + 404: + description: The requested long running operation was not found. + 500: + description: Internal server error. This could be due to an issue with removing the operation. """ agent = req.context.agent diff --git a/src/keria/peer/exchanging.py b/src/keria/peer/exchanging.py index 3a98cf7e..fa615db2 100644 --- a/src/keria/peer/exchanging.py +++ b/src/keria/peer/exchanging.py @@ -91,6 +91,34 @@ def on_post(req, rep): req (Request): falcon HTTP request object rep (Response): falcon HTTP response object + --- + summary: Query exchange message collection. + description: This endpoint retrieves the exchange messages based on the provided query parameters. + tags: + - Exchange Message + requestBody: + content: + application/json: + schema: + type: object + properties: + filter: + type: object + description: The filter criteria to apply on the exchange messages. + sort: + type: object + description: The sorting criteria to apply on the exchange messages. + skip: + type: integer + description: The number of exchange messages to skip. (default=0) + limit: + type: integer + description: The maximum number of exchange messages to return. (default=25) + responses: + 200: + description: Successfully retrieved the exchange messages. + 400: + description: Bad request. This could be due to missing or invalid parameters. """ agent = req.context.agent @@ -146,6 +174,23 @@ def on_get(req, rep, said): rep (Response): falcon HTTP response object said (str): qb64 SAID of exchange message to retrieve + --- + summary: Retrieve a specific exchange message. + description: This endpoint retrieves a specific exchange message based on the provided SAID. + tags: + - Exchange Message + parameters: + - in: path + name: said + schema: + type: string + required: true + description: The qb64 SAID of the exchange message to retrieve. + responses: + 200: + description: Successfully retrieved the exchange message. + 404: + description: The requested exchange message was not found. """ agent = req.context.agent serder, pathed = exchanging.cloneMessage(agent.hby, said) diff --git a/tests/app/test_specing.py b/tests/app/test_specing.py index 77115bd1..f7829424 100644 --- a/tests/app/test_specing.py +++ b/tests/app/test_specing.py @@ -46,7 +46,7 @@ def test_spec_resource(helpers): js = json.dumps(sd) print(js) # Assert on the entire JSON to ensure we are getting all the docs - assert js == """{"paths": {"/operations": {"get": {"summary": "Get list of long running operations", "parameters": [{"in": "query", "name": "type", "schema": {"type": "string"}, "required": false, "description": "filter list of long running operations by type"}], "responses": {"200": {"content": {"application/json": {"schema": {"type": "array"}}}}}}}, "/oobis": {"post": {"summary": "Resolve OOBI and assign an alias for the remote identifier", "description": "Resolve OOBI URL or `rpy` message by process results of request and assign 'alias' in contact data for resolved identifier", "tags": ["OOBIs"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "OOBI", "properties": {"oobialias": {"type": "string", "description": "alias to assign to the identifier resolved from this OOBI", "required": false}, "url": {"type": "string", "description": "URL OOBI"}, "rpy": {"type": "object", "description": "unsigned KERI `rpy` event message with endpoints"}}}}}}, "responses": {"202": {"description": "OOBI resolution to key state successful"}}}}, "/states": {"get": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Key Event Log"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of KEL to load"}], "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/events": {"get": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Key Event Log"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of KEL to load"}], "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/queries": {"post": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Query"], "parameters": [{"in": "body", "name": "pre", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of KEL to load"}], "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/identifiers": {"get": {}, "options": {}, "post": {}}, "/challenges": {"get": {"summary": "Get random list of words for a 2 factor auth challenge", "description": "Get the list of identifiers associated with this agent", "tags": ["Challenge/Response"], "parameters": [{"in": "query", "name": "strength", "schema": {"type": "int"}, "description": "cryptographic strength of word list", "required": false}], "responses": {"200": {"description": "An array of random words", "content": {"application/json": {"schema": {"description": "Random word list", "type": "object", "properties": {"words": {"type": "array", "description": "random challenge word list", "items": {"type": "string"}}}}}}}}}}, "/contacts": {"get": {"summary": "Get list of contact information associated with remote identifiers", "description": "Get list of contact information associated with remote identifiers. All information is metadata and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "query", "name": "group", "schema": {"type": "string"}, "required": false, "description": "field name to group results by"}, {"in": "query", "name": "filter_field", "schema": {"type": "string"}, "description": "field name to search", "required": false}, {"in": "query", "name": "filter_value", "schema": {"type": "string"}, "description": "value to search for", "required": false}], "responses": {"200": {"description": "List of contact information for remote identifiers"}}}}, "/notifications": {"get": {"summary": "Get list of notifications for the controller of the agent", "description": "Get list of notifications for the controller of the agent. Notifications will be sorted by creation date/time", "parameters": [{"in": "header", "name": "Range", "schema": {"type": "string"}, "required": false, "description": "size of the result list. Defaults to 25"}], "tags": ["Notifications"], "responses": {"200": {"description": "List of contact information for remote identifiers"}}}}, "/oobi": {"get": {}}, "/": {"post": {"summary": "Accept KERI events with attachment headers and parse", "description": "Accept KERI events with attachment headers and parse.", "tags": ["Events"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "description": "KERI event message"}}}}, "responses": {"204": {"description": "KEL EXN, QRY, RPY event accepted."}}}, "put": {"summary": "Accept KERI events with attachment headers and parse", "description": "Accept KERI events with attachment headers and parse.", "tags": ["Events"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "description": "KERI event message"}}}}, "responses": {"200": {"description": "Mailbox query response for server sent events"}, "204": {"description": "KEL or EXN event accepted."}}}}, "/operations/{name}": {"delete": {}, "get": {}}, "/oobis/{alias}": {"get": {"summary": "Get OOBI for specific identifier", "description": "Generate OOBI for the identifier of the specified alias and role", "tags": ["OOBIs"], "parameters": [{"in": "path", "name": "alias", "schema": {"type": "string"}, "required": true, "description": "human readable alias for the identifier generate OOBI for"}, {"in": "query", "name": "role", "schema": {"type": "string"}, "required": true, "description": "role for which to generate OOBI"}], "responses": {"200": {"description": "An array of Identifier key state information", "content": {"application/json": {"schema": {"description": "Key state information for current identifiers", "type": "object"}}}}}}}, "/agent/{caid}": {"get": {}, "put": {}}, "/identifiers/{name}": {"delete": {}, "get": {}, "post": {}, "put": {}}, "/endroles/{aid}": {"get": {}, "post": {}}, "/escrows/rpy": {"get": {}}, "/challenges/{name}": {"post": {"summary": "Sign challenge message and forward to peer identifier", "description": "Sign a challenge word list received out of bands and send `exn` peer to peer message to recipient", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"recipient": {"type": "string", "description": "human readable alias recipient identifier to send signed challenge to"}, "words": {"type": "array", "description": "challenge in form of word list", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}}, "/challenges_verify/{source}": {"post": {"summary": "Sign challenge message and forward to peer identifier", "description": "Sign a challenge word list received out of bands and send `exn` peer to peer message to recipient", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"recipient": {"type": "string", "description": "human readable alias recipient identifier to send signed challenge to"}, "words": {"type": "array", "description": "challenge in form of word list", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}, "put": {"summary": "Mark challenge response exn message as signed", "description": "Mark challenge response exn message as signed", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"aid": {"type": "string", "description": "aid of signer of accepted challenge response"}, "said": {"type": "array", "description": "SAID of challenge message signed", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}}, "/contacts/{prefix}": {"delete": {"summary": "Delete contact information associated with remote identifier", "description": "Delete contact information associated with remote identifier", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact to delete"}], "responses": {"202": {"description": "Contact information successfully deleted for prefix"}, "404": {"description": "No contact information found for prefix"}}}, "get": {"summary": "Get contact information associated with single remote identifier", "description": "Get contact information associated with single remote identifier. All information is meta-data and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact to get"}], "responses": {"200": {"description": "Contact information successfully retrieved for prefix"}, "404": {"description": "No contact information found for prefix"}}}, "post": {"summary": "Create new contact information for an identifier", "description": "Creates new information for an identifier, overwriting all existing information for that identifier", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix to add contact metadata to"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Contact information", "type": "object"}}}}, "responses": {"200": {"description": "Updated contact information for remote identifier"}, "400": {"description": "Invalid identifier used to update contact information"}, "404": {"description": "Prefix not found in identifier contact information"}}}, "put": {"summary": "Update provided fields in contact information associated with remote identifier prefix", "description": "Update provided fields in contact information associated with remote identifier prefix. All information is metadata and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix to add contact metadata to"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Contact information", "type": "object"}}}}, "responses": {"200": {"description": "Updated contact information for remote identifier"}, "400": {"description": "Invalid identifier used to update contact information"}, "404": {"description": "Prefix not found in identifier contact information"}}}}, "/notifications/{said}": {"delete": {"summary": "Delete notification", "description": "Delete notification", "tags": ["Notifications"], "parameters": [{"in": "path", "name": "said", "schema": {"type": "string"}, "required": true, "description": "qb64 said of note to delete"}], "responses": {"202": {"description": "Notification successfully deleted for prefix"}, "404": {"description": "No notification information found for prefix"}}}, "put": {"summary": "Mark notification as read", "description": "Mark notification as read", "tags": ["Notifications"], "parameters": [{"in": "path", "name": "said", "schema": {"type": "string"}, "required": true, "description": "qb64 said of note to mark as read"}], "responses": {"202": {"description": "Notification successfully marked as read for prefix"}, "404": {"description": "No notification information found for SAID"}}}}, "/oobi/{aid}": {"get": {}}, "/identifiers/{name}/events": {"delete": {}, "get": {}, "post": {}, "put": {}}, "/identifiers/{name}/oobis": {"get": {}}, "/identifiers/{name}/endroles": {"get": {}, "post": {}}, "/identifiers/{name}/members": {"get": {}}, "/endroles/{aid}/{role}": {"get": {}, "post": {}}, "/contacts/{prefix}/img": {"get": {"summary": "Get contact image for identifer prefix", "description": "Get contact image for identifer prefix", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact image to get"}], "responses": {"200": {"description": "Contact information successfully retrieved for prefix", "content": {"image/jpg": {"schema": {"description": "Image", "type": "binary"}}}}, "404": {"description": "No contact information found for prefix"}}}, "post": {"summary": "Uploads an image to associate with identifier.", "description": "Uploads an image to associate with identifier.", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "description": "identifier prefix to associate image to", "required": true}], "requestBody": {"required": true, "content": {"image/jpg": {"schema": {"type": "string", "format": "binary"}}, "image/png": {"schema": {"type": "string", "format": "binary"}}}}, "responses": {"200": {"description": "Image successfully uploaded"}}}}, "/oobi/{aid}/{role}": {"get": {}}, "/identifiers/{name}/endroles/{role}": {"get": {}, "post": {}}, "/oobi/{aid}/{role}/{eid}": {"get": {}}, "/identifiers/{name}/endroles/{role}/{eid}": {"delete": {}}}, "info": {"title": "KERIA Interactive Web Interface API", "version": "1.0.1"}, "openapi": "3.1.0"}""" + assert js == """{"paths": {"/operations": {"get": {"summary": "Get list of long running operations", "parameters": [{"in": "query", "name": "type", "schema": {"type": "string"}, "required": false, "description": "filter list of long running operations by type"}], "responses": {"200": {"description": "list of long running operations", "content": {"application/json": {"schema": {"type": "array", "items": {"properties": {"name": {"type": "string"}, "metadata": {"type": "object"}, "done": {"type": "boolean"}, "error": {"type": "object"}, "response": {"type": "object"}}}}}}}}}}, "/oobis": {"post": {"summary": "Resolve OOBI and assign an alias for the remote identifier", "description": "Resolve OOBI URL or `rpy` message by process results of request and assign 'alias' in contact data for resolved identifier", "tags": ["OOBIs"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "OOBI", "oneOf": [{"type": "object", "properties": {"oobialias": {"type": "string", "description": "alias to assign to the identifier resolved from this OOBI"}, "url": {"type": "string", "description": "URL OOBI"}, "rpy": {"type": "object", "description": "unsigned KERI `rpy` event message with endpoints"}}}]}}}}, "responses": {"202": {"description": "OOBI resolution to key state successful"}}}}, "/states": {"get": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Key Event Log"], "parameters": [{"in": "path", "name": "pre", "description": "qb64 identifier prefix of KEL to load", "schema": {"type": "string"}, "required": true}], "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/events": {"get": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Key Event Log"], "parameters": [{"in": "path", "name": "pre", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of KEL to load"}], "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/queries": {"post": {"summary": "Display key event log (KEL) for given identifier prefix", "description": "If provided qb64 identifier prefix is in Kevers, return the current state of the identifier along with the KEL and all associated signatures and receipts", "tags": ["Query"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["pre"], "properties": {"pre": {"type": "string", "description": "qb64 identifier prefix of KEL to load"}, "anchor": {"type": "string", "description": "Anchor"}, "sn": {"type": "string", "description": "Serial number"}}}}}}, "responses": {"200": {"description": "Key event log and key state of identifier"}, "404": {"description": "Identifier not found in Key event database"}}}}, "/identifiers": {"get": {"summary": "Retrieve a list of identifiers associated with the agent.", "description": "This endpoint retrieves a list of identifiers associated with the agent. It supports pagination through the 'Range' header.", "tags": ["Identifier"], "parameters": [{"in": "header", "name": "Range", "schema": {"type": "string"}, "required": false, "description": "The 'Range' header is used for pagination. The default range is 0-9."}], "responses": {"200": {"description": "Successfully retrieved identifiers."}, "206": {"description": "Successfully retrieved identifiers within the specified range."}}}, "options": {}, "post": {"summary": "Create an identifier.", "description": "This endpoint creates an identifier with the provided inception event, name, and signatures.", "tags": ["Identifier"], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"icp": {"type": "object", "description": "The inception event for the identifier."}, "name": {"type": "string", "description": "The name of the identifier."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures for the inception event."}, "group": {"type": "object", "description": "Multisig group information."}, "salty": {"type": "object", "description": "Salty parameters."}, "randy": {"type": "object", "description": "Randomly generated materials."}, "extern": {"type": "object", "description": "External parameters."}}}}}}, "responses": {"202": {"description": "Identifier creation is in progress. The response is a long running operation."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}}}}, "/challenges": {"get": {"summary": "Get random list of words for a 2 factor auth challenge", "description": "Get the list of identifiers associated with this agent", "tags": ["Challenge/Response"], "parameters": [{"in": "query", "name": "strength", "schema": {"type": "integer"}, "description": "cryptographic strength of word list", "required": false}], "responses": {"200": {"description": "An array of random words", "content": {"application/json": {"schema": {"description": "Random word list", "type": "object", "properties": {"words": {"type": "array", "description": "random challenge word list", "items": {"type": "string"}}}}}}}}}}, "/contacts": {"get": {"summary": "Get list of contact information associated with remote identifiers", "description": "Get list of contact information associated with remote identifiers. All information is metadata and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "query", "name": "group", "schema": {"type": "string"}, "required": false, "description": "field name to group results by"}, {"in": "query", "name": "filter_field", "schema": {"type": "string"}, "description": "field name to search", "required": false}, {"in": "query", "name": "filter_value", "schema": {"type": "string"}, "description": "value to search for", "required": false}], "responses": {"200": {"description": "List of contact information for remote identifiers"}}}}, "/notifications": {"get": {"summary": "Get list of notifications for the controller of the agent", "description": "Get list of notifications for the controller of the agent. Notifications will be sorted by creation date/time", "parameters": [{"in": "header", "name": "Range", "schema": {"type": "string"}, "required": false, "description": "size of the result list. Defaults to 25"}], "tags": ["Notifications"], "responses": {"200": {"description": "List of contact information for remote identifiers"}}}}, "/oobi": {"get": {}}, "/": {"post": {"summary": "Accept KERI events with attachment headers and parse", "description": "Accept KERI events with attachment headers and parse.", "tags": ["Events"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "description": "KERI event message"}}}}, "responses": {"204": {"description": "KEL EXN, QRY, RPY event accepted."}}}, "put": {"summary": "Accept KERI events with attachment headers and parse", "description": "Accept KERI events with attachment headers and parse.", "tags": ["Events"], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "description": "KERI event message"}}}}, "responses": {"200": {"description": "Mailbox query response for server sent events"}, "204": {"description": "KEL or EXN event accepted."}}}}, "/operations/{name}": {"delete": {"summary": "Remove a specific long running operation.", "description": "This endpoint removes a long running operation by its name.", "tags": ["Operation"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The name of the long running operation to remove."}], "responses": {"204": {"description": "Successfully removed the long running operation."}, "404": {"description": "The requested long running operation was not found."}, "500": {"description": "Internal server error. This could be due to an issue with removing the operation."}}}, "get": {"summary": "Retrieve a specific long running operation.", "description": "This endpoint retrieves the status of a long running operation by its name.", "tags": ["Operation"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The name of the long running operation to retrieve."}], "responses": {"200": {"description": "Successfully retrieved the status of the long running operation."}, "404": {"description": "The requested long running operation was not found."}}}}, "/oobis/{alias}": {"get": {"summary": "Get OOBI for specific identifier", "description": "Generate OOBI for the identifier of the specified alias and role", "tags": ["OOBIs"], "parameters": [{"in": "path", "name": "alias", "schema": {"type": "string"}, "required": true, "description": "human readable alias for the identifier generate OOBI for"}, {"in": "query", "name": "role", "schema": {"type": "string"}, "required": true, "description": "role for which to generate OOBI"}], "responses": {"200": {"description": "An array of Identifier key state information", "content": {"application/json": {"schema": {"description": "Key state information for current identifiers", "type": "object"}}}}}}}, "/agent/{caid}": {"get": {"summary": "Retrieve key state record of an agent by controller AID.", "description": "This endpoint retrieves the key state record for a given controller of an agent.", "tags": ["Agent"], "parameters": [{"in": "path", "name": "caid", "schema": {"type": "string"}, "required": true, "description": "The qb64 identifier prefix of Controller."}], "responses": {"200": {"description": "Successfully retrieved the key state record."}, "400": {"description": "Bad request. This could be due to an invalid agent or controller configuration."}, "404": {"description": "The requested controller or agent was not found."}}}, "put": {"summary": "Update agent configuration by controller AID.", "description": "This endpoint updates the agent configuration based on the provided request parameters and body.", "tags": ["Agent"], "parameters": [{"in": "path", "name": "caid", "schema": {"type": "string"}, "required": true, "description": "The qb64 identifier prefix of Controller."}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "required": ["rot", "sigs", "sxlt", "kyes"], "properties": {"rot": {"type": "object", "description": "The rotation event."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures."}, "sxlt": {"type": "string", "description": "The salty parameters."}, "keys": {"type": "object", "description": "The keys."}}}}}}, "responses": {"204": {"description": "Successfully updated the agent configuration."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "The requested agent was not found."}, "500": {"description": "Internal server error. This could be due to an issue with updating the agent configuration."}}}}, "/identifiers/{name}": {"delete": {"summary": "Delete an identifier.", "description": "This endpoint deletes an identifier by its name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "responses": {"200": {"description": "Successfully deleted the identifier."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}, "get": {"summary": "Retrieve an identifier.", "description": "This endpoint retrieves an identifier by its human-readable name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "responses": {"200": {"description": "Successfully retrieved the identifier details."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Process identifier events.", "description": "This endpoint handles the 'rot' or 'ixn' events of an identifier based on the provided request.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rot": {"type": "object", "description": "The rotation event details."}, "ixn": {"type": "object", "description": "The interaction event details."}}, "oneOf": [{"required": ["rot"]}, {"required": ["ixn"]}]}}}}, "responses": {"200": {"description": "Successfully processed the identifier's event."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}}}, "put": {"summary": "Rename an identifier.", "description": "This endpoint renames an identifier with the provided new name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The current human-readable name of the identifier."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "The new name for the identifier."}}, "required": ["name"]}}}}, "responses": {"200": {"description": "Successfully renamed the identifier and returns the updated information."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}}, "/endroles/{aid}": {"get": {"summary": "Retrieve end roles.", "description": "This endpoint retrieves the end roles associated with AID or human-readable name. It can also filter the end roles based on a specific role.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "The identifier (AID)."}, {"in": "path", "name": "role", "schema": {"type": "string"}, "required": true, "description": "The specific role to filter the end roles."}], "responses": {"200": {"description": "Successfully retrieved the end roles. The response body contains the end roles."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Create an end role.", "description": "This endpoint creates an end role associated with a given identifier (AID) or name.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "Not supported for POST. If provided, a 404 is returned."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rpy": {"type": "object", "description": "The reply object."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures."}}}}}}, "responses": {"202": {"description": "Accepted. The end role creation is in progress."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "Not found. The requested identifier was not found."}}}}, "/escrows/rpy": {"get": {"summary": "Retrieve reply escrows.", "description": "This endpoint retrieves the reply escrows and can filter the collection based on a specific route.", "tags": ["Reply Escrow"], "parameters": [{"in": "query", "name": "route", "schema": {"type": "string"}, "required": false, "description": "The specific route to filter the reply escrow collection."}], "responses": {"200": {"description": "Successfully retrieved the reply escrows."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}}}}, "/challenges/{name}": {"post": {"summary": "Sign challenge message and forward to peer identifier", "description": "Sign a challenge word list received out of bands and send `exn` peer to peer message to recipient", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"recipient": {"type": "string", "description": "human readable alias recipient identifier to send signed challenge to"}, "words": {"type": "array", "description": "challenge in form of word list", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}}, "/challenges_verify/{source}": {"post": {"summary": "Sign challenge message and forward to peer identifier", "description": "Sign a challenge word list received out of bands and send `exn` peer to peer message to recipient", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "source", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"recipient": {"type": "string", "description": "human readable alias recipient identifier to send signed challenge to"}, "words": {"type": "array", "description": "challenge in form of word list", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}, "put": {"summary": "Mark challenge response exn message as signed", "description": "Mark challenge response exn message as signed", "tags": ["Challenge/Response"], "parameters": [{"in": "path", "name": "source", "schema": {"type": "string"}, "required": true, "description": "Human readable alias for the identifier to create"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Challenge response", "properties": {"aid": {"type": "string", "description": "aid of signer of accepted challenge response"}, "said": {"type": "array", "description": "SAID of challenge message signed", "items": {"type": "string"}}}}}}}, "responses": {"202": {"description": "Success submission of signed challenge/response"}}}}, "/contacts/{prefix}": {"delete": {"summary": "Delete contact information associated with remote identifier", "description": "Delete contact information associated with remote identifier", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact to delete"}], "responses": {"202": {"description": "Contact information successfully deleted for prefix"}, "404": {"description": "No contact information found for prefix"}}}, "get": {"summary": "Get contact information associated with single remote identifier", "description": "Get contact information associated with single remote identifier. All information is meta-data and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact to get"}], "responses": {"200": {"description": "Contact information successfully retrieved for prefix"}, "404": {"description": "No contact information found for prefix"}}}, "post": {"summary": "Create new contact information for an identifier", "description": "Creates new information for an identifier, overwriting all existing information for that identifier", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix to add contact metadata to"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Contact information", "type": "object"}}}}, "responses": {"200": {"description": "Updated contact information for remote identifier"}, "400": {"description": "Invalid identifier used to update contact information"}, "404": {"description": "Prefix not found in identifier contact information"}}}, "put": {"summary": "Update provided fields in contact information associated with remote identifier prefix", "description": "Update provided fields in contact information associated with remote identifier prefix. All information is metadata and kept in local storage only", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix to add contact metadata to"}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"description": "Contact information", "type": "object"}}}}, "responses": {"200": {"description": "Updated contact information for remote identifier"}, "400": {"description": "Invalid identifier used to update contact information"}, "404": {"description": "Prefix not found in identifier contact information"}}}}, "/notifications/{said}": {"delete": {"summary": "Delete notification", "description": "Delete notification", "tags": ["Notifications"], "parameters": [{"in": "path", "name": "said", "schema": {"type": "string"}, "required": true, "description": "qb64 said of note to delete"}], "responses": {"202": {"description": "Notification successfully deleted for prefix"}, "404": {"description": "No notification information found for prefix"}}}, "put": {"summary": "Mark notification as read", "description": "Mark notification as read", "tags": ["Notifications"], "parameters": [{"in": "path", "name": "said", "schema": {"type": "string"}, "required": true, "description": "qb64 said of note to mark as read"}], "responses": {"202": {"description": "Notification successfully marked as read for prefix"}, "404": {"description": "No notification information found for SAID"}}}}, "/oobi/{aid}": {"get": {}}, "/identifiers/{name}/events": {"delete": {"summary": "Delete an identifier.", "description": "This endpoint deletes an identifier by its name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "responses": {"200": {"description": "Successfully deleted the identifier."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}, "get": {"summary": "Retrieve an identifier.", "description": "This endpoint retrieves an identifier by its human-readable name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "responses": {"200": {"description": "Successfully retrieved the identifier details."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Process identifier events.", "description": "This endpoint handles the 'rot' or 'ixn' events of an identifier based on the provided request.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rot": {"type": "object", "description": "The rotation event details."}, "ixn": {"type": "object", "description": "The interaction event details."}}, "oneOf": [{"required": ["rot"]}, {"required": ["ixn"]}]}}}}, "responses": {"200": {"description": "Successfully processed the identifier's event."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}}}, "put": {"summary": "Rename an identifier.", "description": "This endpoint renames an identifier with the provided new name.", "tags": ["Identifier"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The current human-readable name of the identifier."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"name": {"type": "string", "description": "The new name for the identifier."}}, "required": ["name"]}}}}, "responses": {"200": {"description": "Successfully renamed the identifier and returns the updated information."}, "400": {"description": "Bad request. This could be due to a missing or invalid name parameter."}, "404": {"description": "The requested identifier was not found."}}}}, "/identifiers/{name}/oobis": {"get": {}}, "/identifiers/{name}/endroles": {"get": {"summary": "Retrieve end roles.", "description": "This endpoint retrieves the end roles associated with AID or human-readable name. It can also filter the end roles based on a specific role.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "The identifier (AID)."}, {"in": "path", "name": "role", "schema": {"type": "string"}, "required": true, "description": "The specific role to filter the end roles."}], "responses": {"200": {"description": "Successfully retrieved the end roles. The response body contains the end roles."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Create an end role.", "description": "This endpoint creates an end role associated with a given identifier (AID) or name.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "Not supported for POST. If provided, a 404 is returned."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rpy": {"type": "object", "description": "The reply object."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures."}}}}}}, "responses": {"202": {"description": "Accepted. The end role creation is in progress."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "Not found. The requested identifier was not found."}}}}, "/identifiers/{name}/members": {"get": {}}, "/endroles/{aid}/{role}": {"get": {"summary": "Retrieve end roles.", "description": "This endpoint retrieves the end roles associated with AID or human-readable name. It can also filter the end roles based on a specific role.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "The identifier (AID)."}, {"in": "path", "name": "role", "schema": {"type": "string"}, "required": true, "description": "The specific role to filter the end roles."}], "responses": {"200": {"description": "Successfully retrieved the end roles. The response body contains the end roles."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Create an end role.", "description": "This endpoint creates an end role associated with a given identifier (AID) or name.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "Not supported for POST. If provided, a 404 is returned."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rpy": {"type": "object", "description": "The reply object."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures."}}}}}}, "responses": {"202": {"description": "Accepted. The end role creation is in progress."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "Not found. The requested identifier was not found."}}}}, "/contacts/{prefix}/img": {"get": {"summary": "Get contact image for identifer prefix", "description": "Get contact image for identifer prefix", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "required": true, "description": "qb64 identifier prefix of contact image to get"}], "responses": {"200": {"description": "Contact information successfully retrieved for prefix", "content": {"image/jpg": {"schema": {"description": "Image", "type": "binary"}}}}, "404": {"description": "No contact information found for prefix"}}}, "post": {"summary": "Uploads an image to associate with identifier.", "description": "Uploads an image to associate with identifier.", "tags": ["Contacts"], "parameters": [{"in": "path", "name": "prefix", "schema": {"type": "string"}, "description": "identifier prefix to associate image to", "required": true}], "requestBody": {"required": true, "content": {"image/jpg": {"schema": {"type": "string", "format": "binary"}}, "image/png": {"schema": {"type": "string", "format": "binary"}}}}, "responses": {"200": {"description": "Image successfully uploaded"}}}}, "/oobi/{aid}/{role}": {"get": {}}, "/identifiers/{name}/endroles/{role}": {"get": {"summary": "Retrieve end roles.", "description": "This endpoint retrieves the end roles associated with AID or human-readable name. It can also filter the end roles based on a specific role.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "The identifier (AID)."}, {"in": "path", "name": "role", "schema": {"type": "string"}, "required": true, "description": "The specific role to filter the end roles."}], "responses": {"200": {"description": "Successfully retrieved the end roles. The response body contains the end roles."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "The requested identifier was not found."}}}, "post": {"summary": "Create an end role.", "description": "This endpoint creates an end role associated with a given identifier (AID) or name.", "tags": ["End Role"], "parameters": [{"in": "path", "name": "name", "schema": {"type": "string"}, "required": true, "description": "The human-readable name of the identifier."}, {"in": "path", "name": "aid", "schema": {"type": "string"}, "required": true, "description": "Not supported for POST. If provided, a 404 is returned."}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": {"rpy": {"type": "object", "description": "The reply object."}, "sigs": {"type": "array", "items": {"type": "string"}, "description": "The signatures."}}}}}}, "responses": {"202": {"description": "Accepted. The end role creation is in progress."}, "400": {"description": "Bad request. This could be due to missing or invalid parameters."}, "404": {"description": "Not found. The requested identifier was not found."}}}}, "/oobi/{aid}/{role}/{eid}": {"get": {}}, "/identifiers/{name}/endroles/{role}/{eid}": {"delete": {}}}, "info": {"title": "KERIA Interactive Web Interface API", "version": "1.0.1"}, "openapi": "3.1.0"}""" "" \ No newline at end of file