{
  "openapi": "3.1.0",
  "info": {
    "title": "GuardDog API",
    "version": "1.0.0",
    "description": "Manage GuardDog branch call trees and unit driver assignments."
  },
  "servers": [
    {
      "url": "https://app.guarddog.live/api/v1",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Call trees",
      "description": "Manage branch-scoped escalation contacts."
    },
    {
      "name": "Unit drivers",
      "description": "Manage unit driver assignments."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/branches/{branchId}/call-tree": {
      "parameters": [
        {
          "$ref": "#/components/parameters/BranchId"
        }
      ],
      "get": {
        "operationId": "getBranchCallTree",
        "summary": "Get a branch call tree",
        "description": "Returns active branch-scoped contacts in priority order. Corporate contacts are not included.",
        "tags": ["Call trees"],
        "responses": {
          "200": {
            "description": "The active branch call tree.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallTreeResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "operationId": "replaceBranchCallTree",
        "summary": "Replace a branch call tree",
        "description": "Archives the current branch-scoped contacts and replaces them with the supplied contacts. Corporate contacts are not changed.",
        "tags": ["Call trees"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReplaceCallTreeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The replacement branch call tree.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallTreeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidJson"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidBody"
          }
        }
      }
    },
    "/units/{unitId}/driver": {
      "parameters": [
        {
          "$ref": "#/components/parameters/UnitId"
        }
      ],
      "get": {
        "operationId": "getUnitDriver",
        "summary": "Get a unit driver",
        "tags": ["Unit drivers"],
        "responses": {
          "200": {
            "description": "The unit's current driver, or null when unassigned.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnitDriverResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "put": {
        "operationId": "setUnitDriver",
        "summary": "Set or clear a unit driver",
        "description": "Assign a driver object, or send null to clear the assignment.",
        "tags": ["Unit drivers"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetUnitDriverRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated driver assignment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnitDriverResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidJson"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidBody"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "gd_live_ API key",
        "description": "An organization API key created in GuardDog settings."
      }
    },
    "parameters": {
      "BranchId": {
        "name": "branchId",
        "in": "path",
        "required": true,
        "description": "A branch ID in the authenticated organization.",
        "schema": {
          "type": "string"
        }
      },
      "UnitId": {
        "name": "unitId",
        "in": "path",
        "required": true,
        "description": "A unit ID in the authenticated organization.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "CallTreeContactInput": {
        "type": "object",
        "additionalProperties": false,
        "required": ["first_name", "last_name", "phone_number", "priority"],
        "properties": {
          "first_name": {
            "type": "string",
            "minLength": 1
          },
          "last_name": {
            "type": "string",
            "minLength": 1
          },
          "phone_number": {
            "type": "string",
            "minLength": 1,
            "description": "A US phone number in a common format. Stored as E.164."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "job_title": {
            "type": "string"
          },
          "priority": {
            "type": "integer",
            "minimum": 0,
            "description": "Lower values are contacted first."
          }
        }
      },
      "CallTreeContact": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CallTreeContactInput"
          },
          {
            "type": "object",
            "required": [
              "id",
              "branch_id",
              "organization_id",
              "is_corporate",
              "archived",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "branch_id": {
                "type": ["string", "null"]
              },
              "organization_id": {
                "type": "string"
              },
              "email": {
                "type": ["string", "null"],
                "format": "email"
              },
              "job_title": {
                "type": ["string", "null"]
              },
              "is_corporate": {
                "type": "boolean"
              },
              "archived": {
                "type": "boolean"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      },
      "ReplaceCallTreeRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["contacts"],
        "properties": {
          "contacts": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/CallTreeContactInput"
            }
          }
        }
      },
      "CallTreeResponse": {
        "type": "object",
        "required": ["branch_id", "contacts"],
        "properties": {
          "branch_id": {
            "type": "string"
          },
          "contacts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CallTreeContact"
            }
          }
        }
      },
      "DriverInput": {
        "type": "object",
        "additionalProperties": false,
        "required": ["first_name", "last_name", "phone_number"],
        "properties": {
          "first_name": {
            "type": "string",
            "minLength": 1
          },
          "last_name": {
            "type": "string",
            "minLength": 1
          },
          "phone_number": {
            "type": "string",
            "minLength": 1,
            "description": "A US phone number in a common format. Stored as E.164."
          }
        }
      },
      "Driver": {
        "allOf": [
          {
            "$ref": "#/components/schemas/DriverInput"
          },
          {
            "type": "object",
            "required": [
              "id",
              "branch_id",
              "organization_id",
              "archived",
              "created_at",
              "updated_at"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "branch_id": {
                "type": "string"
              },
              "organization_id": {
                "type": "string"
              },
              "archived": {
                "type": "boolean"
              },
              "created_at": {
                "type": "string",
                "format": "date-time"
              },
              "updated_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        ]
      },
      "SetUnitDriverRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["driver"],
        "properties": {
          "driver": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DriverInput"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "UnitDriverResponse": {
        "type": "object",
        "required": ["unit_id", "driver"],
        "properties": {
          "unit_id": {
            "type": "string"
          },
          "driver": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Driver"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          }
        }
      }
    },
    "responses": {
      "InvalidJson": {
        "description": "The request body is not valid JSON.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Invalid JSON body"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The API key is missing, invalid, or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Unauthorized"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource was not found in the authenticated organization.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Branch not found"
            }
          }
        }
      },
      "InvalidBody": {
        "description": "The request body failed validation.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "Invalid body",
              "details": {
                "formErrors": [],
                "fieldErrors": {}
              }
            }
          }
        }
      }
    }
  }
}
