diff --git a/go.mod b/go.mod index 5ec2da5..36d9ded 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,19 @@ module github.com/Gaardsholt/go-gitguardian go 1.22 require ( + github.com/getkin/kin-openapi v0.114.0 github.com/google/go-querystring v1.1.0 github.com/peterhellberg/link v1.2.0 ) + +require ( + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/swag v0.19.5 // indirect + github.com/invopop/yaml v0.1.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/perimeterx/marshmallow v1.1.4 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index 36c600f..59c9e1e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,60 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/getkin/kin-openapi v0.114.0 h1:ar7QiJpDdlR+zSyPjrLf8mNnpoFP/lI90XcywMCFNe8= +github.com/getkin/kin-openapi v0.114.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= +github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc= +github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= +github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= +github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/peterhellberg/link v1.2.0 h1:UA5pg3Gp/E0F2WdX7GERiNrPQrM1K6CVJUUWfHa4t6c= github.com/peterhellberg/link v1.2.0/go.mod h1:gYfAh+oJgQu2SrZHg5hROVRQe1ICoK0/HHJTcE0edxc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..7c06d38 --- /dev/null +++ b/main_test.go @@ -0,0 +1,45 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/Gaardsholt/go-gitguardian/types" + "github.com/getkin/kin-openapi/openapi2" +) + +func Test_main(t *testing.T) { + input, err := os.ReadFile("swagger.json") + if err != nil { + panic(err) + } + + var doc openapi2.T + if err = json.Unmarshal(input, &doc); err != nil { + panic(err) + } + + for k, v := range doc.Paths { + operations := v.Operations() + + for o := range operations { + t.Run(fmt.Sprintf("%s - %s", o, k), func(t *testing.T) { + if !checkIfPathIsThere(k, o) { + t.Fatalf("Path '%s' with operation '%s' is not there", k, o) + } + }) + } + } + +} + +func checkIfPathIsThere(path string, operation string) bool { + for _, v := range types.Endpoints { + if v.GetApiPath() == path && v.Operation == operation { + return true + } + } + return false +} diff --git a/swagger.json b/swagger.json new file mode 100644 index 0000000..87e8118 --- /dev/null +++ b/swagger.json @@ -0,0 +1,6646 @@ +{ + "openapi": "3.0.3", + "servers": [ + { + "url": "https://api.gitguardian.com" + } + ], + "info": { + "title": "GitGuardian API", + "version": "1.1.0", + "termsOfService": "https://www.gitguardian.com/legal-terms", + "license": { + "name": "GitGuardian", + "url": "https://www.gitguardian.com/legal-terms" + }, + "x-logo": { + "url": "https://static.gitguardian.com/Logo-blue.png", + "altText": "GitGuardian" + }, + "contact": { + "name": "GitGuardian", + "email": "support@gitguardian.com", + "url": "https://www.gitguardian.com" + }, + "description": "\n# Introduction\n\nWhether you want to build a complete integration with your software development\nworkflow or simply want to test GitGuardian's policy break detection on any text content,\nyou can use our API.\n\n- The base url for the latest version is `api.gitguardian.com/v1` over `HTTPS`.\n- All data is sent and received as JSON by default.\n- All timestamps returned are ISO-8601 compliant, example:\n```python\n2020-03-16T04:46:00+00:00 # for date-time\n```\n\nGitGuardian supported wrappers:\n- Python: [**py-gitguardian**](https://github.com/GitGuardian/py-gitguardian)\n\nGitGuardian provides you with [**GitGuardian Shield**](https://github.com/GitGuardian/gg-shield),\na CLI application that uses the GitGuardian API through py-gitguardian\nto scan your files and detect potential secrets or issues in your code.\n\nThis CLI application can be used in many CIs (such as GitHub Actions, GitLab Pipelines, CircleCI,...)\nor as a pre-commit or pre-receive hook.\n\n# Authentication\n\nThe GitGuardian API uses API keys to authenticate requests.\n\nYou need to [create an account](https://dashboard.gitguardian.com/auth/signup) before getting started\nin order to get an API key.\n\nYour API key can be created and revoked from the\n[API section of your dashboard](https://dashboard.gitguardian.com/api).\n\nYour API key must kept private and should neither be embedded directly in the code nor versioned in Git.\n(Please do not push GitGuardian's API keys to public GitHub repositories ^^).\n\nBeware your API keys can expire and can be revoked.\n\nUse [/v1/health](#operation/health_check) to check the\nvalidity of your token if needed.\n\n```bash\ncurl -H \"Authorization: Token ${TOKEN}\" \\\n https://api.gitguardian.com/v1/health\n```\n\n\n\n" + }, + "tags": [ + { + "name": "Secret Incidents", + "description": "Manage incidents found by post-receive hooks on your GitGuardian Dashboard.\n" + }, + { + "name": "Secret Occurrences", + "description": "Manage occurrences found by post-receive hooks on your GitGuardian Dashboard.\n" + }, + { + "name": "Secret Incident Notes", + "description": "Manage notes on incidents found by post-receive hooks on your GitGuardian Dashboard.\n" + }, + { + "name": "Invitations", + "description": "Manage workspace invitations.\n" + }, + { + "name": "Sources", + "description": "Retrieve details on sources monitored by GitGuardian.\n" + }, + { + "name": "Members", + "description": "Retrieve details about workspace members.\n" + }, + { + "name": "Scan Methods", + "description": "Use GitGuardian's brain at your leisure.\n\nScanning API allows you to scan any content you want using GitGuardian's secrets detection algorithms.\n" + }, + { + "name": "Quota", + "description": "Retrieve details about quota usage.\n" + }, + { + "name": "Audit logs", + "description": "List of audit logs of the workspace.\n" + }, + { + "name": "Status", + "description": "Check the status of the API and the overall system health.\n" + }, + { + "name": "Teams", + "description": "Manage teams.\n" + }, + { + "name": "Team Invitations", + "description": "Manage team invitations.\n" + }, + { + "name": "Team Memberships", + "description": "Add or remove members from teams, or update their permissions.\n" + } + ], + "x-tagGroups": [ + { + "name": "Incidents Management", + "tags": [ + "Secret Incidents", + "Secret Occurrences", + "Secret Incident Notes" + ] + }, + { + "name": "Perimeter Management", + "tags": [ + "Sources" + ] + }, + { + "name": "User Management", + "tags": [ + "Members", + "Invitations" + ] + }, + { + "name": "Secrets Scanning", + "tags": [ + "Scan Methods", + "Quota" + ] + }, + { + "name": "Team Management", + "tags": [ + "Teams", + "Team Invitations", + "Team Memberships", + "Team Requests", + "Team Sources" + ] + }, + { + "name": "Audit Logs", + "tags": [ + "Audit Logs" + ] + }, + { + "name": "Other", + "tags": [ + "Status" + ] + } + ], + "paths": { + "/v1/incidents/secrets": { + "get": { + "tags": [ + "Secret Incidents" + ], + "operationId": "list-incidents", + "summary": "List secret incidents", + "description": "List secret incidents detected by the GitGuardian dashboard.\nOccurrences are not returned in this route.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/date_before" + }, + { + "$ref": "#/components/parameters/date_after" + }, + { + "name": "assignee_email", + "in": "query", + "schema": { + "type": "string", + "description": "Incidents assigned to this email.", + "example": "eric@gitguardian.com" + } + }, + { + "name": "status", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/StatusEnum" + } + ], + "description": "Incidents with the following status." + } + }, + { + "name": "severity", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SeverityEnum" + } + ], + "description": "Filter incidents by severity." + } + }, + { + "name": "validity", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ValidityEnum" + } + ], + "description": "Secrets with the following validity." + } + }, + { + "name": "tags", + "in": "query", + "schema": { + "type": "string", + "description": "Incidents with one of the following tags. Use `NONE` if you want to filter incidents with no tags.", + "example": "FROM_HISTORICAL_SCAN,SENSITIVE_FILE", + "allOf": [ + { + "$ref": "#/components/schemas/TagFilterEnum" + } + ] + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "date", + "-date", + "resolved_at", + "-resolved_at", + "ignored_at", + "-ignored_at" + ] + } + }, + { + "name": "detector_group_name", + "in": "query", + "schema": { + "type": "string", + "description": "Incidents belonging to the specified detector group.", + "example": "slackbot_token" + } + } + ], + "responses": { + "200": { + "description": "Secret Incident List", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}": { + "get": { + "tags": [ + "Secret Incidents" + ], + "operationId": "retrieve-incidents", + "summary": "Retrieve a secret incident", + "description": "Retrieve secret incident detected by the GitGuardian dashboard with\nits occurrences.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "name": "with_occurrences", + "in": "query", + "description": "Retrieve a number of occurrences of this incident.", + "schema": { + "type": "integer", + "default": 20, + "minimum": 0, + "maximum": 100 + } + } + ], + "responses": { + "200": { + "description": "Secret Incident Details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incident" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + }, + "patch": { + "tags": [ + "Secret Incidents" + ], + "operationId": "update-secret-incident", + "summary": "Update a secret incident", + "description": "Update a secret incident\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Update Request", + "properties": { + "severity": { + "allOf": [ + { + "$ref": "#/components/schemas/SeverityEnum" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/assign": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "assign-incident", + "summary": "Assign a secret incident", + "description": "Assign secret incident detected by the GitGuardian dashboard to a workspace member\nby email.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Assignee Request", + "properties": { + "email": { + "type": "string", + "example": "eric@gitguardian.com", + "description": "email of the member to assign. This parameter is mutually exclusive with `member_id`.\n" + }, + "member_id": { + "type": "number", + "example": 4295, + "description": "id of the member to assign. This parameter is mutually exclusive with `email`.\n" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/unassign": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "unassign-incident", + "summary": "Unassign a secret incident", + "description": "Unassign secret incident from a workspace member by email.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/resolve": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "resolve-incident", + "summary": "Resolve a secret incident", + "description": "Resolve a secret incident detected by the GitGuardian dashboard.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Resolve Request", + "required": [ + "secret_revoked" + ], + "properties": { + "secret_revoked": { + "type": "boolean", + "example": true + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/ignore": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "ignore-incident", + "summary": "Ignore a secret incident", + "description": "Ignore a secret incident detected by the GitGuardian dashboard.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Ignore Request", + "required": [ + "ignore_reason" + ], + "properties": { + "ignore_reason": { + "allOf": [ + { + "$ref": "#/components/schemas/SecretStatusEnum" + } + ], + "example": "low_risk" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/reopen": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "reopen-incident", + "summary": "Reopen a secret incident", + "description": "Unresolve or unignore a secret incident detected by the GitGuardian dashboard.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "responses": { + "200": { + "description": "Secret Incident Details without occurrences.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentWithoutOccurrences" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/share": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "share-incident", + "summary": "Share a secret incident", + "description": "Share a secret incident by creating a public link.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Incident Share Request", + "properties": { + "auto_healing": { + "type": "boolean", + "example": true, + "default": false, + "description": "Allow the developer to resolve or ignore through the share link" + }, + "feedback_collection": { + "type": "boolean", + "example": true, + "default": true, + "description": "Allow the developer to submit their feedback through the share link" + }, + "lifespan": { + "type": "integer", + "example": 720, + "default": 0, + "description": "Lifespan, in hours, of the share link. If 0 or unset, a default value will be applied based on the workspace settings." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Incident Sharing Details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentToken" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:share" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/unshare": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "unshare-incident", + "summary": "Unshare a secret incident", + "description": "Unshare a secret incident by revoking its public link.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "responses": { + "204": { + "description": "The public link was revoked successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:share" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/grant_access": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "grant-access-incident", + "summary": "Grant access to a secret incident", + "description": "Grant a user, an existing invitee or a team access to a secret incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Grant Access Request", + "properties": { + "email": { + "type": "string", + "description": "Email address of a user or invitee. This parameter is mutually exclusive\nwith `member_id`, `invitation_id` and `team_id`.\n" + }, + "member_id": { + "type": "number", + "description": "Id of a member. This parameter is mutually exclusive with `email`,\n`invitation_id` and `team_id`.\n" + }, + "invitation_id": { + "type": "number", + "description": "Id of an invitation. This parameter is mutually exclusive with `email`,\n`member_id` and `team_id`.\n" + }, + "team_id": { + "type": "number", + "description": "Id of a team, except for the global team. This parameter is mutually\nexclusive with `email`, `member_id` and `invitation_id`.\n" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ] + } + }, + "example": { + "member_id": 1492, + "incident_permission": "can_edit" + } + } + } + } + }, + "responses": { + "204": { + "description": "The access was granted successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:share" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/revoke_access": { + "post": { + "tags": [ + "Secret Incidents" + ], + "operationId": "revoke-access-incident", + "summary": "Revoke access to a secret incident", + "description": "Revoke access of a user, an existing invitee or a team to a secret incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Grant Access Request", + "properties": { + "email": { + "type": "string", + "description": "Email address of a user or invitee. This parameter is mutually exclusive\nwith `member_id`, `invitation_id` and `team_id`.\n" + }, + "member_id": { + "type": "number", + "description": "Id of a member. This parameter is mutually exclusive with `email`,\n`invitation_id` and `team_id`.\n" + }, + "invitation_id": { + "type": "number", + "description": "Id of an invitation. This parameter is mutually exclusive with `email`,\n`member_id` and `team_id`.\n" + }, + "team_id": { + "type": "number", + "description": "Id of a team, except for the global team. This parameter is mutually\nexclusive with `email`, `member_id` and `invitation_id`.\n" + } + }, + "example": { + "member_id": 1492 + } + } + } + } + }, + "responses": { + "204": { + "description": "The access was revoked successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:share" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/notes": { + "get": { + "tags": [ + "Secret Incident Notes" + ], + "operationId": "list-incident-notes", + "summary": "List notes on a secret incident", + "description": "List notes left on a secret incident in chronological order.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "created_at", + "-created_at", + "updated_at", + "-updated_at" + ] + } + }, + { + "name": "member_id", + "in": "query", + "description": "Filter by member id.", + "schema": { + "type": "integer", + "example": 1 + } + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search notes based on the comment field content.", + "example": "I revoked this" + } + } + ], + "responses": { + "200": { + "description": "Incident Note List", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/incidentNote" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "404": { + "description": "Secret Incident not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + }, + "post": { + "tags": [ + "Secret Incident Notes" + ], + "operationId": "create-incident-note", + "summary": "Create a secret incident note", + "description": "Add a note on a secret incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Incident Note Request", + "properties": { + "comment": { + "type": "string", + "example": "I revoked this secret", + "description": "Content of the incident note" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "The note was created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentNote" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "404": { + "description": "Secret Incident not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/notes/{note_id}": { + "patch": { + "tags": [ + "Secret Incident Notes" + ], + "operationId": "update-incident-note", + "summary": "Update a secret incident note", + "description": "Update an existing comment on a secret incident. Only incident notes\ncreated by the current API key can be updated.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "name": "note_id", + "in": "path", + "required": true, + "description": "The id of the incident note to update", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Incident Note Request", + "properties": { + "comment": { + "type": "string", + "example": "I revoked this secret", + "description": "Content of the incident note" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "The note was updated successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/incidentNote" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "You cannot update an Incident Note you that was not created by\nthe current API key.\n", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Secret Incident or Incident Note not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + }, + "delete": { + "tags": [ + "Secret Incident Notes" + ], + "operationId": "delete-incident-note", + "summary": "Delete a secret incident note", + "description": "Delete an existing comment on a secret incident. Only incident notes\ncreated by the current API key can be deleted.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "name": "note_id", + "in": "path", + "required": true, + "description": "The id of the incident note to delete", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "The note was deleted successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "You cannot delete an Incident Note you that was not created by\nthe current API key.\n", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Secret Incident or Incident Note not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:write" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/members": { + "get": { + "tags": [ + "Secret Incidents" + ], + "operationId": "list-incident-members", + "summary": "List members having access to a secret incident", + "description": "List all the members having access to a secret incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "member_id", + "in": "query", + "schema": { + "type": "number", + "description": "filter on a specific member id.", + "example": 1234 + } + }, + { + "name": "incident_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + }, + { + "name": "role", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/MemberRoleEnum" + } + ], + "description": "Filter members based on their role.", + "deprecated": true + } + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search members based on their name or email.", + "deprecated": true + } + } + ], + "responses": { + "200": { + "description": "List of members", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/incidentMember" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "404": { + "description": "Secret Incident not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read", + "members:read" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/teams": { + "get": { + "tags": [ + "Secret Incidents" + ], + "operationId": "list-incident-teams", + "summary": "List teams having access to a secret incident", + "description": "List all the teams having access to a secret incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "$ref": "#/components/parameters/cursor" + }, + { + "name": "team_id", + "in": "query", + "schema": { + "type": "number", + "description": "filter on a specific team id.", + "example": 1234 + } + }, + { + "name": "incident_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + ], + "responses": { + "200": { + "description": "List of team accesses", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/incidentTeam" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Secret Incident not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read", + "teams:read" + ] + } + ] + } + }, + "/v1/incidents/secrets/{incident_id}/invitations": { + "get": { + "tags": [ + "Secret Incidents" + ], + "operationId": "list-incident-invitations", + "summary": "List invitations having access to a Secret Incident", + "description": "List all the invitations having access to a Secret Incident.\n", + "parameters": [ + { + "$ref": "#/components/parameters/incident_id" + }, + { + "$ref": "#/components/parameters/cursor" + }, + { + "name": "invitation_id", + "in": "query", + "schema": { + "type": "number", + "description": "filter on a specific invitation id.", + "example": 1234 + } + }, + { + "name": "incident_permission", + "in": "query", + "description": "filter accesses with a specific permission.", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + ], + "responses": { + "200": { + "description": "List of invitation accesses", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/incidentInvitation" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Secret Incident not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read", + "members:read" + ] + } + ] + } + }, + "/v1/occurrences/secrets": { + "get": { + "tags": [ + "Secret Occurrences" + ], + "operationId": "list-occs", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/date_before" + }, + { + "$ref": "#/components/parameters/date_after" + }, + { + "name": "source_id", + "in": "query", + "description": "Filter on the source ID.", + "schema": { + "type": "integer", + "example": 5523 + } + }, + { + "name": "source_name", + "in": "query", + "schema": { + "type": "string", + "description": "Entries matching this source name search.", + "example": "gitguardian/test-repository" + } + }, + { + "name": "incident_id", + "in": "query", + "description": "Filter by incident ID.", + "schema": { + "type": "integer" + } + }, + { + "name": "presence", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/PresenceEnum" + } + ], + "description": "Entries that have the following presence status." + } + }, + { + "name": "author_name", + "in": "query", + "schema": { + "type": "string", + "description": "Entries matching this author name search.", + "minLength": 3, + "example": "John Doe" + } + }, + { + "name": "author_info", + "in": "query", + "schema": { + "type": "string", + "description": "Entries matching this author email search.", + "minLength": 3, + "example": "john.doe@gitguardian.com" + } + }, + { + "name": "sha", + "in": "query", + "schema": { + "type": "string", + "description": "Entries starting with the commit sha search string.", + "minLength": 3, + "example": "fccebf0562698ab99dc10dcb2e864fc563b25ac4" + } + }, + { + "name": "filepath", + "in": "query", + "schema": { + "type": "string", + "description": "Entries matching this filepath search.", + "minLength": 3, + "example": "myfile.txt" + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "date", + "-date" + ] + } + } + ], + "summary": "List secret occurrences", + "description": "List occurrences of secrets in the monitored perimeter.\n", + "responses": { + "200": { + "description": "List occurrences", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/occurrence" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + } + }, + "/v1/invitations": { + "get": { + "tags": [ + "Invitations" + ], + "operationId": "list-invitations", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search invitations based on the email field." + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "date", + "-date" + ] + } + } + ], + "summary": "List invitations", + "description": "This endpoint allows you to list all pending invitations.\n\nThe response contains the list of invitations and a pagination cursor to retrieve the next page.\n\nThe invitations are sorted by id.\n\nIf you are using a personal access token, you need to have a role superior or equal to `member`.\n", + "responses": { + "200": { + "description": "List invitations", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/invitation" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read" + ] + } + ] + }, + "post": { + "tags": [ + "Invitations" + ], + "operationId": "create-invitations", + "summary": "Create an invitation", + "description": "This endpoint allows you to send an invitation to a user.\n\nIf you are using a personal access token, you need to have a role superior or equal to `member`.\n", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Invitation Request", + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string", + "example": "eric@gitguardian.com", + "description": "email of the user to invite.\n" + }, + "role": { + "allOf": [ + { + "$ref": "#/components/schemas/NonOwnerMemberRoleEnum" + } + ], + "example": "manager", + "default": "member" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "User already in the workspace", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "details": { + "type": "string" + } + } + } + } + } + } + }, + "201": { + "description": "Invitation sent", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/invitation" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:write" + ] + } + ] + } + }, + "/v1/invitations/{invitation_id}": { + "delete": { + "tags": [ + "Invitations" + ], + "operationId": "delete-invitation", + "summary": "Delete an invitation", + "description": "Delete an existing invitation.\n\nIf you are using a personal access token, you need to have a role superior or equal to `manager`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/invitation_id" + } + ], + "responses": { + "204": { + "description": "The invitation was deleted successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Invitation not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:write" + ] + } + ] + } + }, + "/v1/invitations/{invitation_id}/resend": { + "post": { + "tags": [ + "Invitations" + ], + "operationId": "resend-invitation", + "summary": "Resend an invitation", + "description": "Resend an existing invitation.\n\nIf you are using a personal access token, you need to have a role superior or equal to `manager`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/invitation_id" + } + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "responses": { + "200": { + "description": "Invitation sent", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "detail": { + "type": "string", + "description": "string", + "example": "Email sent" + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Invitation not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "429": { + "description": "Too many requests", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:write" + ] + } + ] + } + }, + "/v1/members": { + "get": { + "tags": [ + "Members" + ], + "operationId": "list-members", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "role", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/MemberRoleEnum" + } + ], + "description": "Filter members based on their role." + } + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search members based on their name or email." + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "created_at", + "-created_at", + "last_login", + "-last_login" + ] + } + } + ], + "summary": "List members", + "description": "List members of the workspace.\n", + "responses": { + "200": { + "description": "List members", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/member" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read" + ] + } + ] + } + }, + "/v1/members/{member_id}": { + "get": { + "tags": [ + "Members" + ], + "operationId": "retrieve-member", + "summary": "Retrieve a member", + "description": "Retrieve an existing workspace member.\n\nIf you are using a personal access token, you need to have a role greater or equal to `member`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/member_id" + } + ], + "responses": { + "200": { + "description": "Workspace member details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/member" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Member not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read" + ] + } + ] + }, + "delete": { + "tags": [ + "Members" + ], + "operationId": "delete-member", + "summary": "Delete a member", + "description": "Delete an existing workspace member.\n\nIf you are using a personal access token, you need to have a role greater or equal to `manager`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/member_id" + } + ], + "responses": { + "204": { + "description": "The member was deleted successfully" + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Member not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:write" + ] + } + ] + }, + "patch": { + "tags": [ + "Members" + ], + "operationId": "update-member", + "summary": "Update a member", + "description": "Update an existing workspace member.\n\nIf you are using a personal access token, you need to have a role greater or equal to `manager`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/member_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "name", + "properties": { + "role": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/NonOwnerMemberRoleEnum" + } + ] + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Workspace member details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/member" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Member not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:write" + ] + } + ] + } + }, + "/v1/scan": { + "post": { + "tags": [ + "Scan Methods" + ], + "operationId": "content_scan", + "summary": "Content scan", + "description": "Scan provided document content for policy breaks.\n\nRequest body shouldn't exceed 1MB.\n\nThis endpoint is stateless and as such will not store in our servers neither the documents nor the secrets found.\n", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/document" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Scan", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/scanResult" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/OverQuotaError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "x-codeSamples": [ + { + "lang": "Shell", + "label": "cURL", + "source": "curl --request POST \\\n --url https://api.gitguardian.com/v1/scan \\\n --header 'authorization: Token ' \\\n --header 'content-type: application/json' \\\n --data '{\n\"document\": \"import urllib.request\\nurl = '\\''http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\\''\\nresponse = urllib.request.urlopen(url)\\nconsume(response.read())\",\n\"filename\": \".env\"\n} '\n" + }, + { + "lang": "Python", + "source": "import os\nfrom pygitguardian import GGClient\ndoc_content = \"import urllib.request\\n\nurl = 'http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\\n\nresponse = urllib.request.urlopen(url)\\n\nconsume(response.read())\"\nclient = GGClient(api_key=API_KEY)\nscan_result = client.content_scan(filename=\".env\", document=doc_content)\nprint(\"Scan results:\", scan_result.has_secrets, \":\", scan_result.policy_break_count)\n" + } + ], + "security": [ + { + "API Key": [ + "scan" + ] + } + ] + } + }, + "/v1/multiscan": { + "post": { + "tags": [ + "Scan Methods" + ], + "operationId": "multiple_scan", + "summary": "Multiple content scan", + "description": "Scan provided document contents for policy breaks.\nMultiple documents are returned by the same index order.\n\nThere should not be more than 20 documents in the payload. Individual documents should not exceed 1MB.\n\nQuota usage is based on requests and not on the content size. One request to this endpoint will consume 1 API call.\nAlso note that the quota is set on a rolling month and not on a calendar month. \nSee [this documentation](https://docs.gitguardian.com/api-docs/usage-and-quotas) for more details.\n\nThis endpoint is stateless and as such will not store in our servers neither the documents nor the secrets found.\n", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "description": "List of documents to scan.", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/document" + }, + "example": [ + { + "filename": ".env", + "document": "import urllib.request\nurl = 'http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\nresponse = urllib.request.urlopen(url)\nconsume(response.read())\n" + }, + { + "filename": "tasks.py", + "document": "__version__=\"1.0.0\"" + } + ] + } + } + } + }, + "responses": { + "200": { + "description": "Successful Scan", + "content": { + "application/json": { + "schema": { + "type": "array", + "description": "List of scan results. Corresponding index to document array.", + "minItems": 1, + "items": { + "$ref": "#/components/schemas/scanResult" + }, + "example": [ + { + "policy_break_count": 2, + "policies": [ + "Filename", + "File extensions", + "Secrets detection" + ], + "policy_breaks": [ + { + "type": ".env", + "policy": "Filenames", + "matches": [ + { + "type": "filename", + "match": ".env" + } + ] + }, + { + "type": "Basic Auth String", + "policy": "Secrets detection", + "validity": "cannot_check", + "matches": [ + { + "type": "username", + "match": "jen_barber", + "index_start": 52, + "index_end": 61, + "line_start": 2, + "line_end": 2 + }, + { + "type": "password", + "match": "correcthorsebatterystaple", + "index_start": 63, + "index_end": 87, + "line_start": 2, + "line_end": 2 + }, + { + "type": "host", + "match": "cake.gitguardian.com", + "index_start": 89, + "index_end": 108, + "line_start": 2, + "line_end": 2 + } + ] + } + ] + }, + { + "policy_break_count": 0, + "policies": [ + "Filename", + "File extensions", + "Secrets detection" + ], + "policy_breaks": [] + } + ] + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/OverQuotaError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "x-codeSamples": [ + { + "lang": "Shell", + "label": "cURL", + "source": "curl --request POST \\\n --url https://api.gitguardian.com/v1/multiscan \\\n --header 'authorization: Token ' \\\n --header 'content-type: application/json' \\\n --data '[\n{\n\"document\": \"import urllib.request\\nurl = '\\''http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\\''\\nresponse = urllib.request.urlopen(url)\\nconsume(response.read())\",\n\"filename\": \".env\"\n},\n{\n \"document\": \"__version__=\\\"1.0.0\\\"\",\n \"filename\": \"__init__.py\"\n}\n]'\n" + }, + { + "lang": "Python", + "source": "import os\nfrom pygitguardian import GGClient\ndoc_content = \"import urllib.request\\n\nurl = 'http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\\n\nresponse = urllib.request.urlopen(url)\\n\nconsume(response.read())\"\nclient = GGClient(api_key=API_KEY)\nto_scan = [{\"filename\": \".env\", \"document\": doc_content},\n {\"filename\": \"__init__.py\", \"document\": \"__version__=\"1.0.0\"}]\nscan_results = client.multi_content_scan(to_scan)\nprint(scan_results)\n" + } + ], + "security": [ + { + "API Key": [ + "scan" + ] + } + ] + } + }, + "/v1/quotas": { + "get": { + "tags": [ + "Quota" + ], + "operationId": "quotas", + "summary": "Quota overview", + "description": "Check available scanning calls for this token. Quota is shared between all tokens of a workspace\n", + "parameters": [], + "responses": { + "200": { + "description": "Quota Overview", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/quota" + } + } + } + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + } + } + }, + "/v1/sources": { + "get": { + "tags": [ + "Sources" + ], + "operationId": "list-sources", + "summary": "List sources", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/page" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/sourceSearch" + }, + { + "$ref": "#/components/parameters/sourceType" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Sources matching this search.", + "example": "test-repository" + } + }, + { + "name": "last_scan_status", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ScanStatusEnum" + } + ], + "description": "Filter sources based on the status of their latest historical scan." + } + }, + { + "name": "health", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SourceHealthEnum" + } + ], + "description": "Filter sources based on their health status." + } + }, + { + "name": "type", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by integration type.", + "example": "github", + "enum": [ + "bitbucket", + "github", + "gitlab", + "azure_devops" + ] + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "last_scan_date", + "-last_scan_date" + ] + } + }, + { + "name": "visibility", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by visibility status.", + "example": "public", + "enum": [ + "public", + "private", + "internal" + ] + } + }, + { + "name": "external_id", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by specific external id.", + "example": "1" + } + } + ], + "description": "List sources monitored by GitGuardian.\n", + "responses": { + "200": { + "description": "Source List", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + }, + "X-Next-Page": { + "$ref": "#/components/headers/xNextPage" + }, + "X-Page": { + "$ref": "#/components/headers/xPage" + }, + "X-Prev-Page": { + "$ref": "#/components/headers/xPrevPage" + }, + "X-Total": { + "$ref": "#/components/headers/xTotal" + }, + "X-Total-Pages": { + "$ref": "#/components/headers/xTotalPages" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/source" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + } + }, + "/v1/sources/{source_id}": { + "get": { + "tags": [ + "Sources" + ], + "operationId": "retrieve-source", + "summary": "Retrieve a source", + "description": "Retrieve a source monitored by GitGuardian.\n", + "parameters": [ + { + "name": "source_id", + "in": "path", + "required": true, + "description": "The id of the source to retrieve.", + "schema": { + "type": "integer", + "example": 5523 + } + } + ], + "responses": { + "200": { + "description": "Source List", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/source" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "incidents:read" + ] + } + ] + } + }, + "/v1/audit_logs": { + "get": { + "tags": [ + "Audit Logs" + ], + "operationId": "list-audit-logs", + "summary": "List audit Logs", + "description": "List audit logs.", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/date_before" + }, + { + "$ref": "#/components/parameters/date_after" + }, + { + "name": "event_name", + "in": "query", + "description": "Entries matching this event name.", + "schema": { + "type": "string", + "example": "user.logged_in" + } + }, + { + "name": "member_id", + "in": "query", + "description": "The id of the member to retrieve.", + "schema": { + "type": "integer", + "example": 3252 + } + }, + { + "name": "member_name", + "in": "query", + "description": "Entries matching this member name.", + "schema": { + "type": "string", + "example": "John Smith" + } + }, + { + "name": "member_email", + "in": "query", + "description": "Entries matching this member email.", + "schema": { + "type": "string", + "example": "john.smith@example.org" + } + }, + { + "name": "api_token_id", + "in": "query", + "description": "Entries matching this API token id.", + "schema": { + "type": "string", + "format": "uuid", + "example": "fdf075f9-1662-4cf1-9171-af50568158a8" + } + }, + { + "name": "ip_address", + "in": "query", + "description": "Entries matching this IP address.", + "schema": { + "type": "string", + "example": "8.8.8.8" + } + } + ], + "responses": { + "200": { + "description": "Audit logs List", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/auditLog" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "audit_logs:read" + ] + } + ] + } + }, + "/v1/health": { + "get": { + "tags": [ + "Status" + ], + "operationId": "health_check", + "summary": "Health check", + "description": "Check the status of the API and your token without spending your quota.", + "parameters": [], + "responses": { + "200": { + "description": "API on and key valid response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Health Status", + "description": "Health check response.", + "required": [ + "detail" + ], + "properties": { + "detail": { + "type": "string", + "description": "API key status." + } + } + }, + "examples": { + "healthy": { + "summary": "Valid API Key.", + "value": { + "detail": "Valid API key." + } + } + } + } + } + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "x-codeSamples": [ + { + "lang": "Shell", + "label": "cURL", + "source": "curl --request GET \\\n --url https://api.gitguardian.com/v1/health \\\n --header 'authorization: Token '\n" + }, + { + "lang": "Python", + "source": "import os\nfrom pygitguardian import GGClient\n# store your API key in an environment variable\nclient = GGClient(api_key=os.getenv(\"GG_API_KEY\"))\nhealth_obj = client.health_check()\nif bool(health_obj):\n print(\"Healthy API server\")\n" + } + ] + } + }, + "/v1/teams": { + "get": { + "tags": [ + "Teams" + ], + "operationId": "list-teams", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "is_global", + "in": "query", + "schema": { + "type": "boolean", + "description": "Filter on/exclude the \"All-incidents\" team." + } + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search teams based on their name and/or description." + } + } + ], + "summary": "List teams", + "description": "This endpoint allows you to list all the teams of your workspace.\n\nThe response contains the list of teams and a pagination cursor to retrieve the next page.\n\nThe teams are sorted by id.\n\nIf you are using a personal access token, you need to have a role superior or equal to `member`.\n", + "responses": { + "200": { + "description": "List teams", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/team" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "post": { + "tags": [ + "Teams" + ], + "operationId": "create-teams", + "summary": "Create a team", + "description": "This endpoint allows you to create a team.\n\nIf you are using a personal access token, you need to have a role superior or equal to `manager`.\n\nIf a personal access token is being used, the member is automatically added to the created team with permissions `can_manage` and `full_access`\n", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Team", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "feature team B", + "description": "team name.\n" + }, + "description": { + "type": "string", + "example": "Description of my team", + "description": "team description.\n" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Team created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/team" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{teams_id}": { + "get": { + "tags": [ + "Teams" + ], + "operationId": "retrieve-team", + "summary": "Retrieve a team", + "description": "Retrieve an existing team.\n\nIf you are using a personal access token, you need to have a role greater or equal to `member`.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "responses": { + "200": { + "description": "Team details", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/team" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Team not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "delete": { + "tags": [ + "Teams" + ], + "operationId": "delete-team", + "summary": "Delete a team", + "description": "Delete an existing team.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n\nThe \"All-incidents\" team (is_global=true) cannot be deleted.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "responses": { + "204": { + "description": "The team was deleted successfully." + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Team not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + }, + "patch": { + "tags": [ + "Teams" + ], + "operationId": "update-team", + "summary": "Update a team", + "description": "Update a team's name and/or its description.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n\nThe \"All-incidents\" team (is_global=true) cannot be updated.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "name and description", + "properties": { + "name": { + "type": "string", + "example": "feature team B", + "description": "A new team name" + }, + "description": { + "type": "string", + "example": "Description of my team", + "description": "A new team description" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "The team was updated successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/team" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/members/{member_id}/teams": { + "get": { + "tags": [ + "Members" + ], + "operationId": "list-member-teams", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Search teams based on their name and/or description." + } + }, + { + "name": "is_global", + "in": "query", + "schema": { + "type": "boolean", + "description": "Filter on/exclude the \"All-incidents\" team." + } + }, + { + "$ref": "#/components/parameters/member_id" + } + ], + "summary": "List teams of a member", + "description": "List teams of a workspace member.\nThe response contains the list of teams and a pagination cursor to retrieve the next page.\n\nThe teams are sorted by id.\n\nIf you are using a personal access token, you need to have a role superior or equal to `manager` except if the requested member is yourself.\n", + "responses": { + "200": { + "description": "List teams", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/team" + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "description": "Forbidden Call", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read", + "teams:read" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_invitations": { + "get": { + "tags": [ + "Team Invitations" + ], + "operationId": "list-team-invitation", + "summary": "List team invitations", + "description": "List all existing team invitations.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "invitation_id", + "in": "query", + "description": "The id of an invitation to filter on", + "schema": { + "type": "integer" + } + }, + { + "name": "team_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "description": "Filter team memberships with a specific team permission", + "example": "can_manage" + } + }, + { + "name": "incident_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "description": "Filter team memberships with a specific incident permission", + "example": "can_edit" + } + } + ], + "responses": { + "200": { + "description": "Team invitation list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/teamInvitation" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "post": { + "tags": [ + "Team Invitations" + ], + "operationId": "create-team-invitations", + "summary": "Create a team invitation", + "description": "This endpoint allows you to create a team invitation from an existing team and invitation.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "TeamInvitation", + "required": [ + "invitation_id" + ], + "properties": { + "invitation_id": { + "type": "integer", + "example": 4851, + "description": "Id of an existing invitation.\n" + }, + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Team invitation created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamInvitation" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_invitations/{team_invitation_id}": { + "patch": { + "tags": [ + "Team Invitations" + ], + "operationId": "update-team-invitation", + "summary": "Update a team invitation", + "description": "Update permissions of a team invitation.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_invitation_id", + "in": "path", + "required": true, + "description": "The id of the team invitation", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "TeamInvitation", + "properties": { + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team invitation was updated successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamInvitation" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + }, + "delete": { + "tags": [ + "Team Invitations" + ], + "operationId": "delete-team-invitation", + "summary": "Delete a team invitation", + "description": "Delete an existing team invitation.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_invitation_id", + "in": "path", + "required": true, + "description": "The id of the team invitation", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Team invitation was deleted successfully." + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_memberships": { + "get": { + "tags": [ + "Team Memberships" + ], + "operationId": "list-team-memberships", + "summary": "List team memberships", + "description": "List all the memberships of a team.\n\nIf you are using a personal access token, you need to be a workspace manager or be part of the team.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "description": "Filter team memberships with a specific team permission", + "example": "can_manage" + } + }, + { + "name": "incident_permission", + "in": "query", + "schema": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "description": "Filter team memberships with a specific incident permission", + "example": "can_edit" + } + }, + { + "name": "member_id", + "in": "query", + "schema": { + "type": "number", + "description": "Filter team memberships on a specific member", + "example": 1234 + } + } + ], + "responses": { + "200": { + "description": "Team membership list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/teamMembership" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "post": { + "tags": [ + "Team Memberships" + ], + "operationId": "create-team-membership", + "summary": "Add a member to a team", + "description": "Add a member to a team.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "TeamMembership", + "required": [ + "member_id" + ], + "properties": { + "member_id": { + "type": "integer", + "example": 4851, + "description": "Id of a workspace member.\n" + }, + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Team membership created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamMembership" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_memberships/{team_membership_id}": { + "patch": { + "tags": [ + "Team Memberships" + ], + "operationId": "update-team-membership", + "summary": "Update a team membership", + "description": "Update permissions of a team membership.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_membership_id", + "in": "path", + "required": true, + "description": "The id of the team membership", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "TeamMembership", + "properties": { + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team membership was updated successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamMembership" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + }, + "delete": { + "tags": [ + "Team Memberships" + ], + "operationId": "delete-team-membership", + "summary": "Remove a member from a team", + "description": "Remove a member from a team.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager,\nor be the member being removed.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_membership_id", + "in": "path", + "required": true, + "description": "The id of the team membership", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Team membership was deleted successfully." + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/members/{member_id}/team_memberships": { + "get": { + "tags": [ + "Members" + ], + "operationId": "list-member-team-memberships", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/member_id" + }, + { + "name": "team_id", + "in": "query", + "description": "The id of a team to filter on", + "schema": { + "type": "integer" + } + } + ], + "summary": "List team memberships of a member", + "description": "List team memberships of a workspace member.\nThe response contains the list of team memberships and a pagination cursor to retrieve the next page.\n\nThe team memberships are sorted by id.\n\nIf you are using a personal access token, you need to have a role superior or equal to `manager` except if the requested member is yourself.\n", + "responses": { + "200": { + "description": "Team membership list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/teamMembership" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_requests": { + "get": { + "tags": [ + "Team Requests" + ], + "operationId": "list-team-requests", + "summary": "List team requests of a team", + "description": "List pending requests of a team.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "member_id", + "in": "query", + "schema": { + "type": "number", + "description": "Filter requests coming from a specific member", + "example": 1234 + } + } + ], + "responses": { + "200": { + "description": "Team request list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/teamRequest" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "post": { + "tags": [ + "Team Requests" + ], + "operationId": "create-team-request", + "summary": "Request access to a team", + "description": "Create an access request to a team.\n\nYou must be authenticated via a Personal Access Token. You must not already have a pending\nrequest on the team, be a member of the team, be a workspace manager or have the\nrestricted role.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "responses": { + "201": { + "description": "Team request created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamRequest" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "409": { + "$ref": "#/components/responses/ConflictError" + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_requests/{team_request_id}": { + "delete": { + "tags": [ + "Team Requests" + ], + "operationId": "delete-team-request", + "summary": "Cancel or decline a team request", + "description": "Cancel or decline a team request.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager, or\nbe the member who created the request being cancelled.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_request_id", + "in": "path", + "required": true, + "description": "The id of the team request", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "204": { + "description": "Team request deleted" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/teams/{team_id}/team_requests/{team_request_id}/accept": { + "post": { + "tags": [ + "Team Requests" + ], + "operationId": "accept-team-request", + "summary": "Accept a team request", + "description": "Accept a team request by adding the member to the team.\n\nIf you are using a personal access token, you must have \"can manage\" permission on the team or be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "team_request_id", + "in": "path", + "required": true, + "description": "The id of the team request", + "schema": { + "type": "integer" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "TeamMembership", + "properties": { + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_view" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Team request accepted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/teamMembership" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + }, + "/v1/members/{member_id}/team_requests": { + "get": { + "tags": [ + "Team Requests" + ], + "operationId": "list-member-team-requests", + "summary": "List team requests of a member", + "description": "List pending team requests of a member.\n\nIf you are using a personal access token, you need to be either a workspace manager or the member being queried.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/member_id" + }, + { + "name": "team_id", + "in": "query", + "schema": { + "type": "number", + "description": "Filter requests to a specific team", + "example": 1234 + } + } + ], + "responses": { + "200": { + "description": "Team request list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/teamRequest" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "members:read", + "teams:read" + ] + } + ] + } + }, + "/v1/teams/{team_id}/sources": { + "get": { + "tags": [ + "Team Sources" + ], + "operationId": "list-team-sources", + "summary": "List team sources", + "description": "List sources belonging to a team's perimeter.\n", + "parameters": [ + { + "$ref": "#/components/parameters/cursor" + }, + { + "$ref": "#/components/parameters/per_page" + }, + { + "$ref": "#/components/parameters/team_id" + }, + { + "name": "search", + "in": "query", + "schema": { + "type": "string", + "description": "Sources matching this search.", + "example": "test-repository" + } + }, + { + "name": "last_scan_status", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/ScanStatusEnum" + } + ], + "description": "Filter sources based on the status of their latest historical scan." + } + }, + { + "name": "health", + "in": "query", + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SourceHealthEnum" + } + ], + "description": "Filter sources based on their health status." + } + }, + { + "name": "type", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by integration type.", + "example": "github", + "enum": [ + "bitbucket", + "github", + "gitlab", + "azure_devops" + ] + } + }, + { + "name": "ordering", + "in": "query", + "description": "Sort the results by their field value. The default sort is ASC, DESC if the\nfield is preceded by a '-'.\n", + "schema": { + "type": "string", + "enum": [ + "last_scan_date", + "-last_scan_date" + ] + } + }, + { + "name": "visibility", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by visibility status.", + "example": "public", + "enum": [ + "public", + "private", + "internal" + ] + } + }, + { + "name": "external_id", + "in": "query", + "schema": { + "type": "string", + "description": "Filter by specific external id.", + "example": "1" + } + } + ], + "responses": { + "200": { + "description": "Source list", + "headers": { + "Link": { + "schema": { + "type": "string", + "description": "Links toward the previous and next pages if they exist", + "example": "; rel=\"next\",; rel=\"prev\"" + } + }, + "X-Per-Page": { + "$ref": "#/components/headers/xPerPage" + } + }, + "content": { + "application/json": { + "schema": { + "type": "array", + "$ref": "#/components/schemas/source" + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:read" + ] + } + ] + }, + "post": { + "tags": [ + "Team Sources" + ], + "operationId": "update-team-sources", + "summary": "Update a team perimeter", + "description": "This endpoint allows you to add and remove sources from the perimeter of a team.\n\nIf you are using a personal access token, you need to be a workspace manager.\n", + "parameters": [ + { + "$ref": "#/components/parameters/team_id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "sources_to_add": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Ids of sources to add to the perimeter." + }, + "sources_to_remove": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Ids of sources to remove from the perimeter." + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Team perimeter updated" + }, + "400": { + "$ref": "#/components/responses/BadRequestError" + }, + "401": { + "$ref": "#/components/responses/UnauthorizedError" + }, + "403": { + "$ref": "#/components/responses/PermissionDeniedError" + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + } + } + } + }, + "503": { + "$ref": "#/components/responses/MaintenanceResponse" + } + }, + "security": [ + { + "API Key": [ + "teams:write" + ] + } + ] + } + } + }, + "components": { + "schemas": { + "document": { + "type": "object", + "title": "Document", + "required": [ + "document" + ], + "properties": { + "filename": { + "type": "string", + "example": ".env", + "maxLength": 256 + }, + "document": { + "type": "string", + "example": "\nimport urllib.request\nurl = 'http://jen_barber:correcthorsebatterystaple@cake.gitguardian.com/isreal.json'\nresponse = urllib.request.urlopen(url)\nconsume(response.read())\n" + } + } + }, + "error": { + "type": "object", + "title": "Error", + "description": "Error obtained in an API response", + "required": [ + "detail" + ], + "properties": { + "detail": { + "type": "string", + "description": "Details on response." + } + } + }, + "quota": { + "type": "object", + "title": "Quota Overview", + "required": [ + "content" + ], + "properties": { + "content": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "limit": { + "type": "integer" + }, + "remaining": { + "type": "integer" + }, + "since": { + "type": "string", + "format": "date" + } + } + } + }, + "example": { + "content": { + "count": 2, + "limit": 5000, + "remaining": 4998, + "since": "2021-04-18" + } + } + }, + "scanResult": { + "type": "object", + "title": "Scan Result", + "description": "Result of a content scan.", + "required": [ + "policy_break_count", + "policies", + "policy_breaks" + ], + "properties": { + "policy_break_count": { + "type": "integer", + "description": "Number of policy breaks on this document.", + "minimum": 0, + "example": 2 + }, + "policies": { + "type": "array", + "description": "Policies checked on this document.", + "minItems": 0, + "items": { + "type": "string" + }, + "example": [ + "Filename", + "File extensions", + "Secrets detection" + ] + }, + "policy_breaks": { + "type": "array", + "description": "List of policy breaks.", + "minItems": 0, + "items": { + "$ref": "#/components/schemas/policyBreak" + }, + "example": [ + { + "type": ".env", + "policy": "Filenames", + "matches": [ + { + "type": "filename", + "match": ".env" + } + ] + }, + { + "type": "Basic Auth String", + "policy": "Secrets detection", + "validity": "cannot_check", + "matches": [ + { + "type": "username", + "match": "jen_barber", + "index_start": 52, + "index_end": 61, + "line_start": 2, + "line_end": 2 + }, + { + "type": "password", + "match": "correcthorsebatterystaple", + "index_start": 63, + "index_end": 87, + "line_start": 2, + "line_end": 2 + }, + { + "type": "host", + "match": "cake.gitguardian.com", + "index_start": 89, + "index_end": 108, + "line_start": 2, + "line_end": 2 + } + ] + } + ] + } + } + }, + "policyBreak": { + "type": "object", + "title": "Policy Break", + "description": "Issue found in your Document", + "required": [ + "type", + "policy", + "matches" + ], + "properties": { + "type": { + "type": "string", + "description": "Type of detected policy." + }, + "policy": { + "type": "string", + "description": "Name of failing policy." + }, + "validity": { + "type": "string", + "nullable": true, + "enum": [ + "no_checker", + "valid", + "invalid", + "failed_to_check", + "unknown" + ], + "description": "Validity of the found secret." + }, + "matches": { + "type": "array", + "description": "List of secret matches.", + "minItems": 1, + "items": { + "type": "object", + "required": [ + "type", + "match" + ], + "properties": { + "type": { + "type": "string", + "description": "Type of match" + }, + "match": { + "type": "string", + "description": "Matched string of failure" + }, + "line_start": { + "type": "integer", + "description": "start line number of match (index origin = 1)" + }, + "line_end": { + "type": "integer", + "description": "end line number of match (index origin = 1)" + }, + "index_start": { + "type": "integer", + "description": "start index of match in file as an array (index origin = 0)" + }, + "index_end": { + "type": "integer", + "description": "end index of match in file as an array (index origin = 0)" + } + } + } + } + } + }, + "match": { + "type": "object", + "properties": { + "name": { + "type": "string", + "readOnly": true, + "title": "Match name", + "example": "apikey" + }, + "indice_start": { + "type": "integer", + "readOnly": true, + "title": "Match start index", + "example": 32 + }, + "indice_end": { + "type": "integer", + "readOnly": true, + "title": "Match end index", + "example": 79 + }, + "pre_line_start": { + "type": "integer", + "nullable": true, + "readOnly": true, + "title": "Match start line before Git patch", + "example": null + }, + "pre_line_end": { + "type": "integer", + "nullable": true, + "readOnly": true, + "title": "Match end line before Git patch", + "example": null + }, + "post_line_start": { + "type": "integer", + "readOnly": true, + "title": "Match start line after Git patch", + "example": 1 + }, + "post_line_end": { + "type": "integer", + "readOnly": true, + "title": "Match end line after Git patch", + "example": 1 + } + }, + "required": [ + "indice_end", + "indice_start", + "name", + "post_line_end", + "post_line_start", + "pre_line_end", + "pre_line_start" + ] + }, + "scan": { + "type": "object", + "properties": { + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "description": "Creation date of this historical scan", + "example": "2021-05-20T12:40:55.662949Z" + }, + "status": { + "allOf": [ + { + "$ref": "#/components/schemas/ScanStatusEnum" + } + ], + "example": "finished" + } + } + }, + "incidentWithoutOccurrences": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3759 + }, + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "title": "Last trigger date", + "example": "2019-08-22T14:15:22Z" + }, + "detector": { + "$ref": "#/components/schemas/detector" + }, + "secret_hash": { + "type": "string", + "readOnly": true, + "title": "Unique hash", + "example": "Ri9FjVgdOlPnBmujoxP4XPJcbe82BhJXB/SAngijw/juCISuOMgPzYhV28m6OG24" + }, + "gitguardian_url": { + "type": "string", + "readOnly": true, + "title": "URL on the dashboard", + "example": "https://dashboard.gitguardian.com/workspace/1/incidents/3899" + }, + "regression": { + "type": "boolean", + "readOnly": true, + "example": false + }, + "status": { + "allOf": [ + { + "$ref": "#/components/schemas/StatusEnum" + } + ], + "readOnly": true + }, + "assignee_email": { + "type": "string", + "nullable": true, + "example": "eric@gitguardian.com" + }, + "occurrences_count": { + "type": "integer", + "example": 4 + }, + "occurrences": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/occurrence" + }, + "example": null + }, + "ignore_reason": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/SecretStatusEnum" + } + ], + "nullable": true, + "example": "test_credential" + }, + "ignored_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": "2019-08-24T14:15:22Z" + }, + "secret_revoked": { + "type": "boolean", + "example": false + }, + "severity": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/SeverityEnum" + } + ], + "example": "high" + }, + "validity": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/ValidityEnum" + } + ], + "example": "valid" + }, + "resolved_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "share_url": { + "type": "string", + "readOnly": true, + "example": "https://dashboard.gitguardian.com/share/incidents/11111111-1111-1111-1111-111111111111" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TagEnum" + }, + "example": [ + "FROM_HISTORICAL_SCAN", + "SENSITIVE_FILE" + ] + } + }, + "required": [ + "assignments", + "date", + "detector", + "hash", + "id", + "ignored", + "regression", + "resolved", + "status" + ] + }, + "incident": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3759 + }, + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "title": "Last trigger date", + "example": "2019-08-22T14:15:22Z" + }, + "detector": { + "$ref": "#/components/schemas/detector" + }, + "secret_hash": { + "type": "string", + "readOnly": true, + "title": "Unique hash", + "example": "Ri9FjVgdOlPnBmujoxP4XPJcbe82BhJXB/SAngijw/juCISuOMgPzYhV28m6OG24" + }, + "gitguardian_url": { + "type": "string", + "readOnly": true, + "title": "URL on the dashboard", + "example": "https://dashboard.gitguardian.com/workspace/1/incidents/3899" + }, + "regression": { + "type": "boolean", + "readOnly": true, + "example": false + }, + "status": { + "allOf": [ + { + "$ref": "#/components/schemas/StatusEnum" + } + ], + "readOnly": true + }, + "assignee_email": { + "type": "string", + "nullable": true, + "example": "eric@gitguardian.com" + }, + "occurrences_count": { + "type": "integer", + "example": 4 + }, + "occurrences": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/occurrence" + } + }, + "ignore_reason": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/SecretStatusEnum" + } + ], + "nullable": true, + "example": "test_credential" + }, + "severity": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/SeverityEnum" + } + ], + "example": "high" + }, + "validity": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/ValidityEnum" + } + ], + "example": "valid" + }, + "ignored_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": "2019-08-24T14:15:22Z" + }, + "secret_revoked": { + "type": "boolean", + "example": false + }, + "resolved_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + }, + "share_url": { + "type": "string", + "readOnly": true, + "example": "https://dashboard.gitguardian.com/share/incidents/11111111-1111-1111-1111-111111111111" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TagEnum" + }, + "example": [ + "FROM_HISTORICAL_SCAN", + "SENSITIVE_FILE" + ] + } + }, + "required": [ + "assignments", + "date", + "detector", + "hash", + "id", + "ignored", + "regression", + "resolved", + "status" + ] + }, + "incidentNote": { + "type": "object", + "title": "Incident Note", + "properties": { + "id": { + "type": "number", + "readOnly": true, + "example": 17 + }, + "incident_id": { + "type": "number", + "readOnly": true, + "example": 42, + "description": "Id of the related Incident" + }, + "member_id": { + "type": "number", + "nullable": true, + "readOnly": true, + "example": 38, + "description": "Id of the member who created this note. Can be null if the note was\nnot created by a member or if the member was deleted.\n" + }, + "api_token": { + "type": "string", + "deprecated": true, + "nullable": true, + "readOnly": true, + "example": null, + "description": "Name of the API key which created this note. Can be null if the note\nwas not created via the API. Use `api_token_id` instead.\n" + }, + "api_token_id": { + "type": "string", + "format": "uuid", + "nullable": true, + "readOnly": true, + "example": null, + "description": "ID of the API key which created this note. Can be null if the note\nwas not created via the API.\n" + }, + "created_at": { + "type": "string", + "format": "date-time", + "readOnly": true, + "description": "Creation date of the note", + "example": "2019-08-22T14:15:22Z" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "readOnly": true, + "example": null, + "description": "Last time the content of the note was updated. Null if the\ncomment was never modified.\n" + }, + "comment": { + "type": "string", + "example": "I revoked this secret" + }, + "issue_id": { + "type": "number", + "readOnly": true, + "example": 42, + "description": "Id of the related Incident. Use `incident_id` instead.", + "deprecated": true + }, + "user_id": { + "type": "number", + "nullable": true, + "readOnly": true, + "example": 38, + "description": "Id of the user who created this note. Can be null if the note was\nnot created by a user or if the user was deleted. Use `member_id` instead.\n", + "deprecated": true + } + } + }, + "incidentToken": { + "type": "object", + "title": "Incident Sharing Information", + "properties": { + "share_url": { + "type": "string", + "readOnly": true, + "example": "https://dashboard.gitguardian.com/share/incidents/11111111-1111-1111-1111-111111111111" + }, + "incident_id": { + "type": "integer", + "readOnly": true, + "example": 3759 + }, + "feedback_collection": { + "type": "boolean", + "example": true, + "description": "Allow the developer to submit their feedback through the share link" + }, + "auto_healing": { + "type": "boolean", + "example": false, + "description": "Allow the developer to resolve or ignore through the share link" + }, + "token": { + "type": "string", + "example": "12345678-1234-1234-1234-123456789012" + }, + "expire_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": "2019-08-24T14:15:22Z" + }, + "revoked_at": { + "type": "string", + "format": "date-time", + "nullable": true, + "example": null + } + } + }, + "occurrence": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 4421 + }, + "incident_id": { + "type": "integer", + "readOnly": true, + "example": 3759 + }, + "kind": { + "allOf": [ + { + "$ref": "#/components/schemas/OccurrenceKindEnum" + } + ], + "readOnly": true, + "title": "Kind when created" + }, + "sha": { + "type": "string", + "readOnly": true, + "title": "Commit SHA", + "example": "d670460b4b4aece5915caf5c68d12f560a9fe3e4" + }, + "source": { + "$ref": "#/components/schemas/source" + }, + "author_name": { + "type": "string", + "readOnly": true, + "example": "Eric" + }, + "author_info": { + "type": "string", + "readOnly": true, + "example": "eric@gitguardian.com" + }, + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "title": "Publish date", + "example": "2021-05-20T12:40:55.662949Z" + }, + "presence": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/PresenceEnum" + } + ], + "example": "present" + }, + "url": { + "type": "string", + "readOnly": true, + "example": "https://github.com/prm-dev-team/QATest_staging/commit/76dd18a2a8d27eaf00a45851cc7731c53b59ed19#diff-0f372f3171c8f13a15a22a1081487ed54fa70ad088e17c6c6386196a179a04ffR1" + }, + "matches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/match" + } + }, + "filepath": { + "type": "string", + "readOnly": true, + "description": "This is filename for old models with incomplete data", + "example": "test_data/12123testfile.txt" + } + }, + "required": [ + "account", + "author_info", + "author_name", + "date", + "sha", + "filepath", + "kind", + "matches", + "source", + "url" + ] + }, + "detector": { + "type": "object", + "properties": { + "name": { + "type": "string", + "readOnly": true, + "example": "slack_bot_token" + }, + "display_name": { + "type": "string", + "readOnly": true, + "example": "Slack Bot Token" + }, + "nature": { + "type": "string", + "readOnly": true, + "example": "specific" + }, + "family": { + "type": "string", + "readOnly": true, + "example": "apikey" + }, + "detector_group_name": { + "type": "string", + "readOnly": true, + "example": "slackbot_token" + }, + "detector_group_display_name": { + "type": "string", + "readOnly": true, + "example": "Slack Bot Token" + } + }, + "required": [ + "name", + "display_name", + "nature" + ] + }, + "invitation": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3252 + }, + "email": { + "type": "string", + "format": "email", + "readOnly": true, + "example": "john.smith@example.org" + }, + "role": { + "readOnly": true, + "allOf": [ + { + "$ref": "#/components/schemas/NonOwnerMemberRoleEnum" + } + ] + }, + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "description": "Creation date of the invitation", + "example": "2019-08-22T14:15:22Z" + } + } + }, + "incidentInvitation": { + "type": "object", + "properties": { + "invitation_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the invitation object\n" + }, + "incident_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the incident object\n" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_edit" + } + } + }, + "member": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3252 + }, + "name": { + "type": "string", + "readOnly": true, + "example": "John Smith" + }, + "email": { + "type": "string", + "format": "email", + "readOnly": true, + "example": "john.smith@example.org" + }, + "role": { + "readOnly": true, + "allOf": [ + { + "$ref": "#/components/schemas/MemberRoleEnum" + } + ] + } + } + }, + "incidentMember": { + "type": "object", + "properties": { + "member_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the Member object (replaces the id field)\n" + }, + "incident_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the Incident object\n" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_edit" + }, + "id": { + "type": "integer", + "readOnly": true, + "example": 1234, + "deprecated": true + }, + "name": { + "type": "string", + "readOnly": true, + "example": "John Smith", + "deprecated": true + }, + "email": { + "type": "string", + "format": "email", + "readOnly": true, + "example": "john.smith@example.org", + "deprecated": true + }, + "role": { + "readOnly": true, + "allOf": [ + { + "$ref": "#/components/schemas/MemberRoleEnum" + } + ], + "deprecated": true + } + } + }, + "source": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "example": 6531 + }, + "url": { + "type": "string", + "format": "uri", + "example": "https://github.com/GitGuardian/gg-shield" + }, + "type": { + "type": "string", + "example": "github" + }, + "full_name": { + "type": "string", + "example": "gitguardian/gg-shield" + }, + "health": { + "allOf": [ + { + "$ref": "#/components/schemas/SourceHealthEnum" + } + ], + "example": "at_risk" + }, + "open_incidents_count": { + "type": "number", + "description": "Number of open secret incidents with at least one occurrence on this source.\n", + "example": 3 + }, + "closed_incidents_count": { + "type": "number", + "description": "Number of closed secret incidents with at least one occurrence on this source.\n", + "example": 2 + }, + "visibility": { + "type": "string", + "example": "public" + }, + "external_id": { + "type": "string", + "description": "VCS identifier of the source (e.g.: the GitHub id for a GitHub repository). Warning: external_id is a string because some VCS ids can be UUIDs.\n", + "example": "125" + }, + "last_scan": { + "$ref": "#/components/schemas/scan" + } + }, + "required": [ + "display_name", + "id", + "type", + "url", + "visibility" + ] + }, + "auditLog": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3759 + }, + "date": { + "type": "string", + "format": "date-time", + "readOnly": true, + "title": "Date the event occurred", + "example": "2019-08-22T14:15:22Z" + }, + "member_email": { + "type": "string", + "readOnly": true, + "example": "eric@gitguardian.com" + }, + "member_name": { + "type": "string", + "readOnly": true, + "example": "Eric", + "description": "Name of the member at the time he/she did the event. It may differ from the current name\nof the member if it has been updated since.\n" + }, + "member_id": { + "type": "integer", + "nullable": true, + "readOnly": true, + "example": 1243, + "description": "ID of the member that did the event. Can be null if the member has been deleted since then:\nin that case use `member_name` and `member_email` to identify the author of the action.\n" + }, + "api_token_id": { + "type": "integer", + "nullable": true, + "readOnly": true, + "example": 1243, + "description": "ID of the API token associated to the event if it was done through the API" + }, + "ip_address": { + "type": "string", + "readOnly": true, + "nullable": true + }, + "target_ids": { + "type": "array", + "readOnly": true, + "items": { + "type": "integer" + }, + "example": [ + 1243, + 3423 + ] + }, + "action_type": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/AuditLogActionTypeEnum" + } + ], + "example": "READ", + "readOnly": true + }, + "event_name": { + "type": "string", + "readOnly": true, + "example": "user.logged_in" + }, + "data": { + "type": "object", + "readOnly": true, + "nullable": true, + "description": "Additional data associated to the event.", + "example": "{type: github_sso}" + } + } + }, + "team": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3252 + }, + "name": { + "type": "string", + "example": "feature team A" + }, + "description": { + "type": "string", + "example": "Description of my team" + }, + "is_global": { + "type": "boolean", + "example": false, + "readOnly": true + }, + "gitguardian_url": { + "type": "string", + "readOnly": true, + "title": "URL on the dashboard", + "example": "https://dashboard.gitguardian.com/workspace/1/settings/workspace/teams/1" + } + } + }, + "teamInvitation": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 3252 + }, + "invitation_id": { + "type": "integer", + "example": 4851 + }, + "team_id": { + "type": "integer", + "readOnly": true, + "example": 991 + }, + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_edit" + } + } + }, + "teamMembership": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 1234 + }, + "member_id": { + "type": "integer", + "readOnly": true, + "example": 2489 + }, + "team_id": { + "type": "integer", + "readOnly": true, + "example": 4285 + }, + "team_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/TeamPermissionEnum" + } + ], + "example": "cannot_manage" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_edit" + } + } + }, + "teamRequest": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "readOnly": true, + "example": 1234 + }, + "member_id": { + "type": "integer", + "readOnly": true, + "example": 2489 + }, + "team_id": { + "type": "integer", + "readOnly": true, + "example": 4285 + } + } + }, + "incidentTeam": { + "type": "object", + "properties": { + "team_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the Team object\n" + }, + "incident_id": { + "type": "integer", + "readOnly": true, + "example": 3252, + "description": "The id of the Incident object\n" + }, + "incident_permission": { + "type": "string", + "allOf": [ + { + "$ref": "#/components/schemas/IncidentPermissionEnum" + } + ], + "example": "can_edit" + } + } + }, + "MemberRoleEnum": { + "enum": [ + "owner", + "manager", + "member", + "viewer", + "restricted" + ], + "type": "string" + }, + "NonOwnerMemberRoleEnum": { + "enum": [ + "manager", + "member", + "viewer", + "restricted" + ], + "type": "string" + }, + "OccurrenceKindEnum": { + "enum": [ + "Realtime", + "Historical" + ], + "type": "string" + }, + "PresenceEnum": { + "enum": [ + "present", + "removed" + ], + "type": "string" + }, + "ScanStatusEnum": { + "enum": [ + "pending", + "running", + "canceled", + "failed", + "too_large", + "timeout", + "finished" + ], + "type": "string" + }, + "SecretStatusEnum": { + "enum": [ + "test_credential", + "false_positive", + "low_risk" + ], + "type": "string" + }, + "SeverityEnum": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info", + "unknown" + ], + "type": "string" + }, + "SourceHealthEnum": { + "enum": [ + "safe", + "unknown", + "at_risk" + ], + "type": "string" + }, + "StatusEnum": { + "enum": [ + "IGNORED", + "TRIGGERED", + "ASSIGNED", + "RESOLVED" + ], + "type": "string" + }, + "ValidityEnum": { + "enum": [ + "valid", + "invalid", + "failed_to_check", + "no_checker", + "unknown" + ], + "type": "string" + }, + "TagEnum": { + "enum": [ + "FROM_HISTORICAL_SCAN", + "IGNORED_IN_CHECK_RUN", + "PUBLIC", + "REGRESSION", + "SENSITIVE_FILE", + "TEST_FILE" + ], + "type": "string" + }, + "TagFilterEnum": { + "enum": [ + "FROM_HISTORICAL_SCAN", + "IGNORED_IN_CHECK_RUN", + "PUBLIC", + "REGRESSION", + "SENSITIVE_FILE", + "TEST_FILE", + "NONE" + ] + }, + "AuditLogActionTypeEnum": { + "enum": [ + "READ", + "CREATE", + "UPDATE", + "DELETE", + "OTHER" + ], + "type": "string" + }, + "TeamPermissionEnum": { + "enum": [ + "can_manage", + "cannot_manage" + ], + "type": "string" + }, + "IncidentPermissionEnum": { + "enum": [ + "can_view", + "can_edit", + "full_access" + ], + "type": "string" + } + }, + "responses": { + "MaintenanceResponse": { + "description": "API under maintenance", + "headers": { + "X-Maintenance": { + "required": true, + "schema": { + "type": "boolean" + }, + "example": true + } + }, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "API maintenance", + "value": { + "detail": "API under scheduled maintenance." + } + } + } + } + } + }, + "ConflictError": { + "description": "Data conflict", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "Data conflict", + "value": { + "detail": "Request conflicts with existing data." + } + } + } + } + } + }, + "BadRequestError": { + "description": "Invalid data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "Invalid data", + "value": { + "detail": "Invalid data." + } + } + } + } + } + }, + "UnauthorizedError": { + "description": "Invalid API key", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "Invalid APIKey", + "value": { + "detail": "Invalid API key." + } + } + } + } + } + }, + "PermissionDeniedError": { + "description": "Permission denied", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "Permission denied", + "value": { + "detail": "Permission denied." + } + } + } + } + } + }, + "OverQuotaError": { + "description": "Quota limit reached", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/error" + }, + "examples": { + "error": { + "summary": "Quota limit reached.", + "value": { + "detail": "Quota limit reached." + } + } + } + } + } + } + }, + "parameters": { + "incident_id": { + "name": "incident_id", + "in": "path", + "required": true, + "description": "The id of the incident to retrieve", + "schema": { + "type": "integer" + } + }, + "invitation_id": { + "name": "invitation_id", + "in": "path", + "required": true, + "description": "The id of the invitation to retrieve", + "schema": { + "type": "integer" + } + }, + "team_id": { + "name": "team_id", + "in": "path", + "required": true, + "description": "The id of the team", + "schema": { + "type": "integer" + } + }, + "member_id": { + "name": "member_id", + "in": "path", + "required": true, + "description": "The id of the workspace member", + "schema": { + "type": "integer" + } + }, + "cursor": { + "name": "cursor", + "in": "query", + "description": "Pagination cursor.", + "schema": { + "type": "string" + } + }, + "page": { + "deprecated": true, + "name": "page", + "in": "query", + "description": "Page number.", + "schema": { + "type": "integer", + "minimum": 0, + "default": 1 + } + }, + "per_page": { + "name": "per_page", + "in": "query", + "description": "Number of items to list per page.", + "schema": { + "type": "integer", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + "date_before": { + "in": "query", + "name": "date_before", + "schema": { + "type": "string", + "format": "datetime", + "description": "Entries found before this date.", + "example": "2019-08-30T14:15:22Z" + } + }, + "date_after": { + "in": "query", + "name": "date_after", + "schema": { + "type": "string", + "format": "datetime", + "description": "Entries found after this date.", + "example": "2019-08-22T14:15:22Z" + } + } + }, + "headers": { + "xPage": { + "deprecated": true, + "schema": { + "description": "The index of the current page.", + "minimum": 1 + } + }, + "xPerPage": { + "schema": { + "type": "integer", + "description": "The number of items per page.", + "default": 20, + "minimum": 1, + "maximum": 100 + } + }, + "xNextPage": { + "deprecated": true, + "schema": { + "type": "integer", + "description": "The index of the next page.", + "minimum": 1 + } + }, + "xPrevPage": { + "deprecated": true, + "schema": { + "type": "integer", + "description": "The index of the previous page.", + "minimum": 1 + } + }, + "xTotal": { + "deprecated": true, + "schema": { + "type": "integer", + "description": "The total number of items.", + "minimum": 1 + } + }, + "xTotalPages": { + "deprecated": true, + "schema": { + "type": "integer", + "description": "The total number of pages.", + "minimum": 1 + } + } + }, + "securitySchemes": { + "API Key": { + "description": "Usage: `Token ` in `Authorization` header.\n", + "type": "http", + "scheme": "Bearer", + "bearerFormat": "Token ", + "scopes": [ + { + "scan": "Secrets detection capability" + }, + { + "incidents:read": "Read incidents" + }, + { + "incidents:write": "Read and write incidents" + }, + { + "incidents:share": "Share, read and write incidents" + }, + { + "members:read": "Read members" + }, + { + "members:write": "Read and write members" + }, + { + "teams:read": "Read teams" + }, + { + "teams:write": "Read and write teams" + }, + { + "audit_logs:read": "Read audit logs" + } + ] + } + } + }, + "security": [ + { + "API Key": [] + } + ] +} \ No newline at end of file