{
  "openapi": "3.1.0",
  "info": {
    "title": "Customer Interactions",
    "description": "Technician ratings",
    "version": "1.0"
  },
  "servers": [
    {
      "url": "https://api.servicetitan.io/customer-interactions/v2",
      "description": "Production"
    },
    {
      "url": "https://api-integration.servicetitan.io/customer-interactions/v2",
      "description": "Integration"
    }
  ],
  "paths": {
    "/tenant/{tenant}/technician-rating/technician/{technicianId}/job/{jobId}": {
      "put": {
        "tags": [
          "TechnicianRating"
        ],
        "summary": "Add a rating for the specified technician, tied to the specific job.\nIf the rating already exists for that technician/ job combination, update it with the new score.",
        "operationId": "TechnicianRating_Update",
        "parameters": [
          {
            "name": "technicianId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "tenant",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInteractions.V2.CreateOrUpdateTechnicianAssessmentRequestOld"
              },
              "example": {
                "value": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request has succeeded"
          },
          "400": {
            "description": "The request cannot be processed, check validation errors or request format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          },
          "404": {
            "description": "Technician or Job not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKeyHeader": [],
            "oauth": [
              "tn.csi.technicianrating:w"
            ]
          }
        ]
      }
    },
    "/tenant/{tenant}/technician-ratings": {
      "get": {
        "tags": [
          "TechnicianRatings"
        ],
        "summary": "Gets a list of technician ratings",
        "operationId": "TechnicianRatings_GetList",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "technicianId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "jobId",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "includeTotal",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Values: [True, Any, False]",
            "schema": {
              "type": "string",
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ActiveRequestArg"
                }
              ]
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdOnOrAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "modifiedBefore",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "modifiedOnOrAfter",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedResponse_Of_CustomerInteractions.V2.TechnicianAssessmentResponse"
                },
                "example": {
                  "page": 0,
                  "pageSize": 0,
                  "hasMore": true,
                  "totalCount": 0,
                  "data": [
                    {
                      "technicianId": 0,
                      "jobId": 0,
                      "rating": 0,
                      "active": true,
                      "createdOn": "string",
                      "modifiedOn": "string"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be processed, check validation errors or request format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKeyHeader": [],
            "oauth": [
              "tn.csi.technicianrating:r"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "TechnicianRatings"
        ],
        "summary": "Add a rating for the specified technician, tied to the specific job.\nIf the rating already exists for that technician/ job combination, update it with the new score.",
        "operationId": "TechnicianRatings_Update",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerInteractions.V2.CreateOrUpdateTechnicianAssessmentRequest"
              },
              "example": {
                "technicianId": 0,
                "jobId": 0,
                "rating": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The request has succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerInteractions.V2.TechnicianAssessmentResponse"
                },
                "example": {
                  "technicianId": 0,
                  "jobId": 0,
                  "rating": 0,
                  "active": true,
                  "createdOn": "string",
                  "modifiedOn": "string"
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be processed, check validation errors or request format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          },
          "404": {
            "description": "Technician or Job not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKeyHeader": [],
            "oauth": [
              "tn.csi.technicianrating:w"
            ]
          }
        ]
      }
    },
    "/tenant/{tenant}/export/technician-ratings": {
      "get": {
        "tags": [
          "Export"
        ],
        "summary": "Provides export feed for technician ratings",
        "operationId": "Export_TechnicianRatings",
        "parameters": [
          {
            "name": "tenant",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Continuation token received from previous export request in \"continueFrom\" field.\nWhen not specified, the export process starts from the beginning.\\\nUse custom date strings, e.g. \"2020-01-01\" to start the export process from the certain point in time.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includeRecentChanges",
            "in": "query",
            "description": "Use \"true\" to start receiving the most recent changes quicker.\nNote this may cause the same results appearing multiple times on consecutive requests.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The request has succeeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportResponse_Of_CustomerInteractions.V2.ExportTechnicianAssessmentResponse"
                },
                "example": {
                  "hasMore": true,
                  "continueFrom": "string",
                  "data": [
                    {
                      "technicianId": 0,
                      "jobId": 0,
                      "rating": 0,
                      "active": true,
                      "createdOn": "string",
                      "modifiedOn": "string"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request cannot be processed, check validation errors or request format",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiErrorResponse"
                },
                "example": {
                  "type": "string",
                  "title": "string",
                  "status": 0,
                  "traceId": "string",
                  "errors": {},
                  "data": {}
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKeyHeader": [],
            "oauth": [
              "tn.csi.technicianrating:r"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "ApiErrorResponse": {
        "required": [
          "type",
          "title",
          "status",
          "traceId",
          "errors",
          "data"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "A URI reference that identifies the problem type"
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type"
          },
          "status": {
            "type": "integer",
            "description": "The HTTP status code generated by server",
            "format": "int32"
          },
          "traceId": {
            "type": "string",
            "description": "Internal trace ID for advanced diagnostics"
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Provides more details about errors occurred, which can potentially be used for visual display"
          },
          "data": {
            "type": "object",
            "additionalProperties": {},
            "description": "Provides additional data, intended for programmatical usage"
          }
        },
        "additionalProperties": false,
        "description": "Detailed error response, following RFC 7807 recommendations (https://tools.ietf.org/html/rfc7807)."
      },
      "CustomerInteractions.V2.CreateOrUpdateTechnicianAssessmentRequestOld": {
        "required": [
          "value"
        ],
        "type": "object",
        "properties": {
          "value": {
            "type": "number",
            "description": "Rating (0-10)",
            "format": "double"
          }
        },
        "additionalProperties": false,
        "deprecated": true,
        "x-deprecatedMessage": "Use CreateOrUpdateTechnicianAssessmentRequest instead"
      },
      "PaginatedResponse_Of_CustomerInteractions.V2.TechnicianAssessmentResponse": {
        "required": [
          "page",
          "pageSize",
          "hasMore",
          "data"
        ],
        "type": "object",
        "properties": {
          "page": {
            "type": "integer",
            "description": "From which page this output has started",
            "format": "int32"
          },
          "pageSize": {
            "type": "integer",
            "description": "Page size for this query (i.e. how many records were requested to return)",
            "format": "int32"
          },
          "hasMore": {
            "type": "boolean",
            "description": "True if there are more records in the query than returned in this result"
          },
          "totalCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Total count of records for this query (can optionally be populated)",
            "format": "int32"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerInteractions.V2.TechnicianAssessmentResponse"
            },
            "description": "The collection of result items, will never have more than PageSize items"
          }
        },
        "additionalProperties": false,
        "description": "Represents paginated API response."
      },
      "CustomerInteractions.V2.TechnicianAssessmentResponse": {
        "required": [
          "technicianId",
          "jobId",
          "rating",
          "active",
          "createdOn",
          "modifiedOn"
        ],
        "type": "object",
        "properties": {
          "technicianId": {
            "type": "integer",
            "format": "int64"
          },
          "jobId": {
            "type": "integer",
            "format": "int64"
          },
          "rating": {
            "type": "number",
            "description": "Rating (0-10)",
            "format": "double"
          },
          "active": {
            "type": "boolean"
          },
          "createdOn": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedOn": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "ActiveRequestArg": {
        "enum": [
          "True",
          "Any",
          "False"
        ],
        "type": "string",
        "description": "Represents possible HTTP query argument values, when applying filters based on active status.",
        "x-enumNames": [
          "True",
          "Any",
          "False"
        ]
      },
      "CustomerInteractions.V2.CreateOrUpdateTechnicianAssessmentRequest": {
        "required": [
          "technicianId",
          "jobId",
          "rating"
        ],
        "type": "object",
        "properties": {
          "technicianId": {
            "type": "integer",
            "format": "int64"
          },
          "jobId": {
            "type": "integer",
            "format": "int64"
          },
          "rating": {
            "type": "number",
            "description": "Rating (0-10)",
            "format": "double"
          }
        },
        "additionalProperties": false
      },
      "ExportResponse_Of_CustomerInteractions.V2.ExportTechnicianAssessmentResponse": {
        "required": [
          "hasMore",
          "continueFrom",
          "data"
        ],
        "type": "object",
        "properties": {
          "hasMore": {
            "type": "boolean",
            "description": "Indicates whether the export feed has reached its logical \"end\", or if there is more to export.\nTrue means the consumer can invoke another request right away using new continuation token value.\nFalse means there is now new data for the export, and the consumer should wait for some time (5-10 minutes)\nbefore making another request."
          },
          "continueFrom": {
            "type": "string",
            "description": "Continuation token used to resume the export operation. The value should be used in \"from\" query parameter of the following request."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomerInteractions.V2.ExportTechnicianAssessmentResponse"
            },
            "description": "The collection of exported items, usually sorted chronologically based on modification date"
          }
        },
        "additionalProperties": false,
        "description": "Represents export API response."
      },
      "CustomerInteractions.V2.ExportTechnicianAssessmentResponse": {
        "required": [
          "technicianId",
          "jobId",
          "rating",
          "active",
          "createdOn",
          "modifiedOn"
        ],
        "type": "object",
        "properties": {
          "technicianId": {
            "type": "integer",
            "format": "int64"
          },
          "jobId": {
            "type": "integer",
            "format": "int64"
          },
          "rating": {
            "type": "number",
            "description": "Rating (0-10)",
            "format": "double"
          },
          "active": {
            "type": "boolean"
          },
          "createdOn": {
            "type": "string",
            "format": "date-time"
          },
          "modifiedOn": {
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      }
    },
    "securitySchemes": {
      "apiKeyHeader": {
        "type": "apiKey",
        "name": "ST-App-Key",
        "in": "header",
        "description": "ServiceTitan App Key Header"
      },
      "oauth": {
        "type": "oauth2",
        "description": "OAuth 2.0 Client Credentials Flow",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.servicetitan.io/connect/token",
            "scopes": {
              "tn.csi.technicianrating:w": "Customer Interactions → Technician Rating (Write)",
              "tn.csi.technicianrating:r": "Customer Interactions → Technician Rating (Read)"
            }
          }
        }
      }
    }
  }
}