{
  "openapi": "3.1.1",
  "info": {
    "title": "Trackwell SLA Calculator API",
    "version": "1.0.0",
    "summary": "When is a ticket due in business hours? Working days, holidays, pauses and breaches.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://trackwellslacalculator.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "When is a ticket due in business hours? Working days, holidays, pauses and breaches.",
        "description": "Adds an SLA target (for example 4h or 2d of business time) to the moment a ticket was opened, skipping nights, weekends and holidays, and tells you the due time. With an “as of” or “stopped at” time it also shows elapsed business time, time left and whether the SLA was breached, minus paused periods such as “waiting for customer”.\n\nMethodology:\n- Business time runs only inside the working hours of working days that are not holidays. The local times you enter are converted with the fixed UTC offset; daylight saving changes are not applied.\n- Due time = the moment when the target’s business minutes have passed since the ticket was opened. A target in days uses the length of one working day (e.g. 1d = 8h for 09:00–17:00).\n- Elapsed time = business minutes from opening to the check time (or the stop time) minus the business minutes inside paused periods. Remaining = target − elapsed; negative means breached.\n- With a stop time the clock is final: met when elapsed ≤ target. Without one, the state is running, paused (inside a pause) or breached.\n- This is the same calculation Trackwell runs for incident and request SLAs (response and resolution) in its issue view and dashboard.\n\nCheck your contract for how it counts business hours, holidays and pauses; this tool follows the rules above.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "trackwell_sla_calculator",
        "x-owner-app": "trackwell",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TrackwellSlaCalculatorInput"
              },
              "examples": {
                "example1": {
                  "summary": "Incident opened Friday 16:30, 4 business hours, Mon–Fri 9–17",
                  "value": {
                    "start": "2026-11-20T16:30",
                    "target": "4h",
                    "asOf": "2026-11-23T10:00"
                  }
                },
                "example2": {
                  "summary": "Request with 2 business days, a holiday and a pause, resolved in time",
                  "value": {
                    "start": "2026-12-23T11:00",
                    "target": "2d",
                    "dayStart": "08:00",
                    "dayEnd": "18:00",
                    "utcOffset": "+01:00",
                    "holidays": [
                      "2026-12-24",
                      "2026-12-25",
                      "2026-12-26"
                    ],
                    "pauses": [
                      {
                        "from": "2026-12-28T09:00",
                        "to": "2026-12-28T14:00"
                      }
                    ],
                    "stop": "2026-12-29T15:00"
                  }
                },
                "example3": {
                  "summary": "Response target of 30 minutes, answered late",
                  "value": {
                    "start": "2026-11-24T08:50",
                    "target": "30m",
                    "stop": "2026-11-24T09:45"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TrackwellSlaCalculatorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "TrackwellSlaCalculatorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "start": {
            "title": "Ticket opened at (local time)",
            "type": "string",
            "description": "Local date-time YYYY-MM-DDTHH:mm",
            "default": "2026-11-20T16:30"
          },
          "target": {
            "title": "SLA target (business time)",
            "description": "For example 30m, 4h, 1d 4h or 2d. One day = the length of one working day.",
            "type": "string",
            "maxLength": 40,
            "default": "4h"
          },
          "days": {
            "title": "Working days",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sun",
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
                "sat"
              ]
            },
            "default": [
              "mon",
              "tue",
              "wed",
              "thu",
              "fri"
            ]
          },
          "dayStart": {
            "title": "Working day starts",
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "default": "09:00"
          },
          "dayEnd": {
            "title": "Working day ends",
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "default": "17:00"
          },
          "utcOffset": {
            "title": "UTC offset of these times",
            "description": "For example +01:00 for CET in winter. Fixed offset: daylight saving changes are not applied.",
            "type": "string",
            "maxLength": 10,
            "default": "+00:00"
          },
          "holidays": {
            "title": "Holidays (one date per line)",
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 200,
            "default": []
          },
          "asOf": {
            "title": "Check at (local time, optional)",
            "description": "Shows elapsed and remaining business time at this moment. Local date-time YYYY-MM-DDTHH:mm",
            "type": "string"
          },
          "stop": {
            "title": "Responded or resolved at (optional)",
            "description": "Stops the clock: the SLA was met or breached. Local date-time YYYY-MM-DDTHH:mm",
            "type": "string"
          },
          "pauses": {
            "title": "Paused periods (waiting for customer)",
            "description": "Local times as YYYY-MM-DDTHH:MM.",
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "from": {
                  "title": "From",
                  "type": "string",
                  "default": ""
                },
                "to": {
                  "title": "To (empty = still paused)",
                  "type": "string",
                  "default": ""
                }
              },
              "required": []
            },
            "default": []
          }
        },
        "required": [
          "start"
        ]
      },
      "TrackwellSlaCalculatorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "required": [
              "due",
              "targetMinutes"
            ],
            "properties": {
              "start": {
                "type": "string"
              },
              "due": {
                "type": "string"
              },
              "dueLocal": {
                "type": "string"
              },
              "dueUtc": {
                "type": "string"
              },
              "targetMinutes": {
                "type": "number"
              },
              "calendar": {
                "type": "object"
              },
              "clock": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "businessHoursPerWeek": {
                "type": "number"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}