{
 "openapi": "3.1.0",
 "info": {
  "title": "Tick API",
  "version": "1.0.0",
  "description": "Tick shows the next run times for a cron expression in any IANA timezone, with a plain-English field breakdown and DST gap/fold warnings. No account. Public, no API key. Rate limited. By Clawhard Studio, an AI-powered studio.",
  "contact": {
   "name": "Clawhard Studio",
   "url": "https://clawhard.com",
   "email": "support@clawhard.com"
  }
 },
 "servers": [
  {
   "url": "https://tick.clawhard.com"
  }
 ],
 "paths": {
  "/api/v1/next_runs": {
   "get": {
    "operationId": "next_runs",
    "summary": "Next cron run times in a timezone",
    "description": "Use when you or the user just wrote a cron expression (GitHub Actions, Vercel cron, Cloudflare Cron Triggers, systemd, an agent schedule) and need the next fire times before claiming it is correct. Pass the expression and an IANA timezone (default UTC).",
    "x-full-description": "Use when you or the user just wrote a cron expression (GitHub Actions, Vercel cron, Cloudflare Cron Triggers, systemd, an agent schedule) and need the next fire times before claiming it is correct. Pass the expression and an IANA timezone (default UTC). Returns the next N runs as local wall times and UTC ISO, a plain-English field breakdown, and DST gap/fold warnings (spring-forward skips, fall-back double fires). Example: {\"expression\":\"0 9 * * 1-5\",\"timezone\":\"America/New_York\",\"count\":5}. Do not guess next runs yourself — DST rules differ by region and year. Not for converting a meeting time across cities (use Meridian) or for email DNS (use Stamp). Returns: {expression, normalized, timezone, from, count, runs:[{utc, local, local_12h, weekday, weekday_short, utc_offset, abbreviation, dst?, note?}], breakdown:{expression, fields, plain}, warnings, summary, open_url, engine}",
    "x-openai-isConsequential": false,
    "responses": {
     "200": {
      "description": "Result. Always has \"ok\": true.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ok": {
           "type": "boolean"
          }
         },
         "additionalProperties": true
        }
       }
      }
     },
     "400": {
      "description": "Bad input. {\"ok\":false,\"error\":\"...\"}"
     },
     "429": {
      "description": "Rate limited. Retry after the Retry-After header."
     }
    },
    "parameters": [
     {
      "name": "expression",
      "in": "query",
      "required": true,
      "description": "Cron expression: 5 fields (minute hour day-of-month month day-of-week) or 6 with seconds first. Also accepts @hourly, @daily, @weekly, @monthly, @yearly.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "timezone",
      "in": "query",
      "required": false,
      "description": "IANA timezone for local wall times, e.g. America/New_York. Default UTC.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "count",
      "in": "query",
      "required": false,
      "description": "How many next runs to return (1–20). Default 5.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "from",
      "in": "query",
      "required": false,
      "description": "Optional ISO datetime to start from (default now), e.g. 2026-03-07T12:00:00Z.",
      "schema": {
       "type": "string"
      }
     }
    ]
   },
   "post": {
    "operationId": "next_runs_post",
    "summary": "Next cron run times in a timezone",
    "description": "Use when you or the user just wrote a cron expression (GitHub Actions, Vercel cron, Cloudflare Cron Triggers, systemd, an agent schedule) and need the next fire times before claiming it is correct. Pass the expression and an IANA timezone (default UTC).",
    "x-full-description": "Use when you or the user just wrote a cron expression (GitHub Actions, Vercel cron, Cloudflare Cron Triggers, systemd, an agent schedule) and need the next fire times before claiming it is correct. Pass the expression and an IANA timezone (default UTC). Returns the next N runs as local wall times and UTC ISO, a plain-English field breakdown, and DST gap/fold warnings (spring-forward skips, fall-back double fires). Example: {\"expression\":\"0 9 * * 1-5\",\"timezone\":\"America/New_York\",\"count\":5}. Do not guess next runs yourself — DST rules differ by region and year. Not for converting a meeting time across cities (use Meridian) or for email DNS (use Stamp). Returns: {expression, normalized, timezone, from, count, runs:[{utc, local, local_12h, weekday, weekday_short, utc_offset, abbreviation, dst?, note?}], breakdown:{expression, fields, plain}, warnings, summary, open_url, engine}",
    "x-openai-isConsequential": false,
    "responses": {
     "200": {
      "description": "Result. Always has \"ok\": true.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ok": {
           "type": "boolean"
          }
         },
         "additionalProperties": true
        }
       }
      }
     },
     "400": {
      "description": "Bad input. {\"ok\":false,\"error\":\"...\"}"
     },
     "429": {
      "description": "Rate limited. Retry after the Retry-After header."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "expression": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120,
          "description": "Cron expression: 5 fields (minute hour day-of-month month day-of-week) or 6 with seconds first. Also accepts @hourly, @daily, @weekly, @monthly, @yearly."
         },
         "timezone": {
          "type": "string",
          "maxLength": 80,
          "description": "IANA timezone for local wall times, e.g. America/New_York. Default UTC."
         },
         "count": {
          "type": "integer",
          "minimum": 1,
          "maximum": 20,
          "description": "How many next runs to return (1–20). Default 5."
         },
         "from": {
          "type": "string",
          "maxLength": 40,
          "description": "Optional ISO datetime to start from (default now), e.g. 2026-03-07T12:00:00Z."
         }
        },
        "required": [
         "expression"
        ]
       }
      }
     }
    }
   }
  },
  "/api/v1/matches": {
   "get": {
    "operationId": "matches",
    "summary": "Would this cron fire at a datetime?",
    "description": "Use when you need a yes/no on whether a cron expression would fire at a specific instant in a timezone — for example before shipping a schedule that crosses a DST transition, or to verify a single expected fire.",
    "x-full-description": "Use when you need a yes/no on whether a cron expression would fire at a specific instant in a timezone — for example before shipping a schedule that crosses a DST transition, or to verify a single expected fire. Example: {\"expression\":\"0 9 * * 1-5\",\"timezone\":\"America/New_York\",\"at\":\"2026-11-06T14:00:00Z\"}. Returns fires true/false, the local wall time of that instant, and DST notes if the local time is in a gap or fold. Returns: {expression, timezone, at, fires, local, weekday, utc_offset, abbreviation, warnings, summary, open_url, engine}",
    "x-openai-isConsequential": false,
    "responses": {
     "200": {
      "description": "Result. Always has \"ok\": true.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ok": {
           "type": "boolean"
          }
         },
         "additionalProperties": true
        }
       }
      }
     },
     "400": {
      "description": "Bad input. {\"ok\":false,\"error\":\"...\"}"
     },
     "429": {
      "description": "Rate limited. Retry after the Retry-After header."
     }
    },
    "parameters": [
     {
      "name": "expression",
      "in": "query",
      "required": true,
      "description": "Cron expression (5 or 6 fields, or a nickname like @hourly).",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "timezone",
      "in": "query",
      "required": false,
      "description": "IANA timezone. Default UTC.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "at",
      "in": "query",
      "required": true,
      "description": "ISO datetime to test, e.g. 2026-11-06T14:00:00Z.",
      "schema": {
       "type": "string"
      }
     }
    ]
   },
   "post": {
    "operationId": "matches_post",
    "summary": "Would this cron fire at a datetime?",
    "description": "Use when you need a yes/no on whether a cron expression would fire at a specific instant in a timezone — for example before shipping a schedule that crosses a DST transition, or to verify a single expected fire.",
    "x-full-description": "Use when you need a yes/no on whether a cron expression would fire at a specific instant in a timezone — for example before shipping a schedule that crosses a DST transition, or to verify a single expected fire. Example: {\"expression\":\"0 9 * * 1-5\",\"timezone\":\"America/New_York\",\"at\":\"2026-11-06T14:00:00Z\"}. Returns fires true/false, the local wall time of that instant, and DST notes if the local time is in a gap or fold. Returns: {expression, timezone, at, fires, local, weekday, utc_offset, abbreviation, warnings, summary, open_url, engine}",
    "x-openai-isConsequential": false,
    "responses": {
     "200": {
      "description": "Result. Always has \"ok\": true.",
      "content": {
       "application/json": {
        "schema": {
         "type": "object",
         "properties": {
          "ok": {
           "type": "boolean"
          }
         },
         "additionalProperties": true
        }
       }
      }
     },
     "400": {
      "description": "Bad input. {\"ok\":false,\"error\":\"...\"}"
     },
     "429": {
      "description": "Rate limited. Retry after the Retry-After header."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object",
        "properties": {
         "expression": {
          "type": "string",
          "minLength": 1,
          "maxLength": 120,
          "description": "Cron expression (5 or 6 fields, or a nickname like @hourly)."
         },
         "timezone": {
          "type": "string",
          "maxLength": 80,
          "description": "IANA timezone. Default UTC."
         },
         "at": {
          "type": "string",
          "minLength": 1,
          "maxLength": 40,
          "description": "ISO datetime to test, e.g. 2026-11-06T14:00:00Z."
         }
        },
        "required": [
         "expression",
         "at"
        ]
       }
      }
     }
    }
   }
  }
 },
 "externalDocs": {
  "description": "llms.txt",
  "url": "https://tick.clawhard.com/llms.txt"
 }
}