

```json
{
  "openapi": "3.0.0",
  "info": {
    "title": "Safe Voice Client API",
    "version": "v1",
    "description": "## Overview\n\nThe Safe Voice Client API allows you to perform various game client operations\nrelating to Safe Voice.\n\nThis includes the player consent api, which lets the game client to update the\nconsent status for a player. The consent status is used to determine if the player's\naudio can be recorded and processed for content moderation.\n\nFor more information, please refer to our [Documentation](https://docs.unity.com/ugs/manual/safe-voice/manual/home).",
    "contact": {
      "name": "Safe Voice Support",
      "x-slack-channel": "#devs-safevoice",
      "email": "safe-voice-support@unity3d.com"
    }
  },
  "servers": [
    {
      "url": "https://vivox.services.api.unity.com"
    }
  ],
  "tags": [
    {
      "name": "Consent Management",
      "description": "Operations related to player consent management"
    }
  ],
  "paths": {
    "/v1/projects/{projectId}/environments/{environmentId}/players/{playerId}/consents": {
      "parameters": [
        {
          "$ref": "#/components/parameters/projectId"
        },
        {
          "$ref": "#/components/parameters/environmentId"
        },
        {
          "$ref": "#/components/parameters/playerId"
        }
      ],
      "put": {
        "operationId": "update consent status",
        "summary": "Update the player consent status",
        "description": "Update the player consent status in the Safe Voice for consent tracking",
        "tags": [
          "Consent Management"
        ],
        "security": [
          {
            "Client": []
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConsentSpecification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consent update successful",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentSpecification"
                }
              }
            }
          },
          "400": {
            "description": "bad request body",
            "content": {
              "application/json+problem": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseBadRequest"
                }
              }
            }
          },
          "404": {
            "description": "projectId/environmentId not found",
            "content": {
              "application/json+problem": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseNotFound"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json+problem": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseInternalServerError"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get consent status",
        "summary": "Get the player consent status",
        "description": "Get the player consent status in the Safe Voice for consent tracking",
        "tags": [
          "Consent Management"
        ],
        "security": [
          {
            "Client": []
          }
        ],
        "responses": {
          "200": {
            "description": "Consent status retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConsentSpecification"
                }
              }
            }
          },
          "404": {
            "description": "projectId/environmentId not found",
            "content": {
              "application/json+problem": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseNotFound"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json+problem": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseInternalServerError"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "playerId": {
        "name": "playerId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "ID of the user"
      },
      "projectId": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "ID of the project"
      },
      "environmentId": {
        "name": "environmentId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "ID of the environment"
      },
      "organizationId": {
        "name": "organizationId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        },
        "description": "ID of the organization"
      }
    },
    "schemas": {
      "BasicErrorResponse": {
        "description": "Referenced from - https://tools.ietf.org/html/rfc7807#page-3 Consumers MUST use the 'type' string as the primary identifier for the problem type; the 'title' string is advisory and included only for users who are not aware of the semantics of the URI and do not have the ability to discover them (for example, offline log analysis). Consumers SHOULD NOT automatically dereference the type URI. The \"status\" member, if present, is only advisory; it conveys the HTTP status code used for the convenience of the consumer. Generators MUST use the same status code in the actual HTTP response, to assure that generic HTTP software that does not understand this format still behaves correctly.  See Section 5 for further caveats regarding its use. Consumers can use the status member to determine what the original status code used by the generator was, in cases where it has been changed (for example, by an intermediary or cache), and when message bodies persist without HTTP information.  Generic HTTP software still uses the HTTP status code. The \"detail\" member, if present, should focus on helping the client correct the problem, rather than giving debugging information.\n",
        "type": "object",
        "x-examples": {
          "example-1": {
            "type": "problems/basic",
            "title": "Internal Server Error",
            "status": 500,
            "code": 43000,
            "detail": "unexpected error",
            "requestId": "aad109f8-033f-4a24-8b77-5032eb3a6158"
          }
        },
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference [RFC3986] that identifies the problem type. This specification encourages that, when dereferenced, it provide human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be \"about:blank\"."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization (e.g., using proactive content negotiation; see [RFC7231], Section 3.4).",
            "example": "Bad Request"
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.",
            "example": 400
          },
          "code": {
            "type": "integer",
            "description": "Service specific error code. Check out the specific error codes in our [Documentation](https://docs.unity.com/safe-voice/en/manual/error-codes)\n"
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem.",
            "example": "Failed to parse request body. Error: Unexpected end of JSON input"
          },
          "instance": {
            "type": "string",
            "description": "A URI reference that identifies the specific occurrence of the problem. It may or may not yield further information if dereferenced."
          },
          "details": {
            "type": "array",
            "description": "Machine readable service specific errors.",
            "items": {
              "type": "object"
            },
            "maxItems": 100
          },
          "requestId": {
            "type": "string",
            "format": "uuid",
            "description": "Request correlation ID",
            "example": "aad109f8-033f-4a24-8b77-5032eb3a6158"
          }
        },
        "required": [
          "type"
        ]
      },
      "ConflictErrorResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          },
          {
            "type": "object",
            "title": "ConflictErrorResponse",
            "example": {
              "type": "problems/basic",
              "title": "Conflict",
              "status": 409,
              "code": 58,
              "detail": "Deletion request already exists with the same player ID"
            }
          }
        ]
      },
      "ErrorResponseBadRequest": {
        "description": "Bad Request. Returned code indicates one of:\n   - Request parameter validation failure\n   - Other\n See the response schema for more details",
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          }
        ]
      },
      "ErrorResponseForbidden": {
        "description": "Forbidden",
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          }
        ]
      },
      "ErrorResponseNotFound": {
        "description": "Not Found",
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          }
        ],
        "example": {
          "type": "string",
          "title": "Not Found",
          "status": 404,
          "code": 0,
          "detail": "projectId/orgId not found",
          "instance": "string",
          "details": [
            {}
          ],
          "requestId": "aad109f8-033f-4a24-8b77-5032eb3a6158"
        }
      },
      "ErrorResponseUnauthorized": {
        "description": "Unauthorized",
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          }
        ]
      },
      "ErrorResponseInternalServerError": {
        "description": "Internal Server Error",
        "allOf": [
          {
            "$ref": "#/components/schemas/BasicErrorResponse"
          }
        ],
        "example": {
          "type": "string",
          "title": "Internal Server Error",
          "status": 500,
          "code": 0,
          "detail": "Internal server encountered, please contact support",
          "instance": "string",
          "details": [
            {}
          ],
          "requestId": "aad109f8-033f-4a24-8b77-5032eb3a6158"
        }
      },
      "ConsentSpecification": {
        "type": "object",
        "properties": {
          "consents": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "granted"
              ],
              "properties": {
                "granted": {
                  "type": "boolean"
                },
                "name": {
                  "type": "string",
                  "enum": [
                    "vivox.safevoice_moderation"
                  ]
                }
              },
              "example": {
                "name": "vivox.safevoice_moderation",
                "granted": true
              }
            }
          }
        },
        "required": [
          "consents"
        ]
      }
    },
    "securitySchemes": {
      "Client": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "To get started with Authentication, please visit the [Client Authentication section](https://services.docs.unity.com/docs/client-auth)."
      }
    }
  }
}
```