{
  "openapi": "3.1.0",
  "info": {
    "title": "Discord Timestamp Generator API",
    "version": "1.0.0",
    "summary": "Compute Discord <t:UNIX:FORMAT> timestamp codes from an explicit instant.",
    "description": "A small, free, read-only API for generating Discord's dynamic message timestamp codes (`<t:UNIX:FORMAT>`) without doing the Unix-time math yourself. No account, no API key, and no rate limit beyond normal fair use. The same computation backs the interactive generator at https://discordtimestampgen.com/.",
    "contact": {
      "name": "Discord Timestamp Generator",
      "url": "https://discordtimestampgen.com/contact",
      "email": "hello@discordtimestampgen.com"
    },
    "license": {
      "name": "Free to use",
      "url": "https://discordtimestampgen.com/terms"
    }
  },
  "servers": [
    { "url": "https://discordtimestampgen.com", "description": "Production" }
  ],
  "externalDocs": {
    "description": "Developer portal",
    "url": "https://discordtimestampgen.com/developers"
  },
  "paths": {
    "/api/timestamp": {
      "get": {
        "operationId": "getDiscordTimestamp",
        "summary": "Compute a Discord timestamp code",
        "description": "Converts either a fully-qualified ISO 8601 datetime (with an explicit UTC offset) or an existing Unix timestamp into a Unix timestamp and the corresponding Discord `<t:UNIX:FORMAT>` code. Pass exactly one of `datetime` or `unix`. Pass `format` to get a single code, or omit it to get all 7 formats at once.",
        "parameters": [
          {
            "name": "datetime",
            "in": "query",
            "required": false,
            "description": "The target moment, as an ISO 8601 datetime string that includes a UTC offset (or ends in \"Z\"). A bare local datetime with no offset is rejected because the API has no ambient timezone to assume. Required unless `unix` is given.",
            "schema": { "type": "string", "format": "date-time" },
            "example": "2025-12-25T09:00:00-05:00"
          },
          {
            "name": "unix",
            "in": "query",
            "required": false,
            "description": "An existing Unix timestamp, in seconds or milliseconds since the epoch — milliseconds (values >= 100000000000) are detected and converted automatically. Use this instead of `datetime` when you already have an epoch value from another system. Required unless `datetime` is given.",
            "schema": { "type": "integer" },
            "example": 1766671200
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "One Discord timestamp format code. Omit to receive all 7 formats in the response.",
            "schema": {
              "type": "string",
              "enum": ["t", "T", "d", "D", "f", "F", "R"]
            },
            "example": "F"
          }
        ],
        "responses": {
          "200": {
            "description": "The computed timestamp code(s).",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/TimestampResponse" },
                "examples": {
                  "singleFormat": {
                    "value": {
                      "input": { "datetime": "2025-12-25T09:00:00-05:00", "format": "F" },
                      "unix": 1766671200,
                      "code": "<t:1766671200:F>",
                      "preview": "Thursday, December 25, 2025 2:00 PM",
                      "previewNote": "Rendered in UTC for reference — Discord re-renders the code in each reader's own timezone and locale automatically."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid `datetime`/`format` parameter.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          },
          "405": {
            "description": "Method not allowed — this endpoint only supports GET and HEAD.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    },
    "/api/formats": {
      "get": {
        "operationId": "listDiscordTimestampFormats",
        "summary": "List the 7 Discord timestamp format codes",
        "description": "Returns the static reference table of Discord's timestamp format codes (t, T, d, D, f, F, R) with a human-readable label, description, and example rendering for each — the same table shown on https://discordtimestampgen.com/discord-timestamp-format.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The full list of format codes.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/FormatsResponse" } }
            }
          },
          "405": {
            "description": "Method not allowed — this endpoint only supports GET and HEAD.",
            "content": {
              "application/json": { "schema": { "$ref": "#/components/schemas/Error" } }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "DiscordFormatCode": {
        "type": "string",
        "enum": ["t", "T", "d", "D", "f", "F", "R"],
        "description": "t=Short Time, T=Long Time, d=Short Date, D=Long Date, f=Short Date/Time, F=Long Date/Time, R=Relative Time."
      },
      "TimestampResponse": {
        "type": "object",
        "required": ["input", "unix"],
        "properties": {
          "input": {
            "type": "object",
            "properties": {
              "datetime": { "type": "string", "format": "date-time" },
              "format": { "anyOf": [{ "$ref": "#/components/schemas/DiscordFormatCode" }, { "type": "null" }] }
            }
          },
          "unix": { "type": "integer", "description": "The input instant as whole Unix seconds." },
          "code": { "type": "string", "description": "Present when `format` was given: the ready-to-paste <t:UNIX:FORMAT> string." },
          "preview": { "type": "string", "description": "Present when `format` was given: how the code renders, computed in UTC." },
          "formats": {
            "type": "array",
            "description": "Present when `format` was omitted: one entry per Discord format code.",
            "items": {
              "type": "object",
              "properties": {
                "code": { "$ref": "#/components/schemas/DiscordFormatCode" },
                "label": { "type": "string" },
                "description": { "type": "string" },
                "timestampCode": { "type": "string" },
                "preview": { "type": "string" }
              }
            }
          },
          "previewNote": { "type": "string" }
        }
      },
      "FormatsResponse": {
        "type": "object",
        "required": ["formats"],
        "properties": {
          "formats": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": { "$ref": "#/components/schemas/DiscordFormatCode" },
                "label": { "type": "string" },
                "description": { "type": "string" },
                "example": { "type": "string" }
              }
            }
          }
        }
      },
      "Error": {
        "type": "object",
        "required": ["error"],
        "properties": {
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": { "type": "string", "description": "Machine-readable error code, e.g. \"invalid_datetime\"." },
              "message": { "type": "string", "description": "Human-readable explanation of what went wrong." },
              "hint": { "type": "string", "description": "How to fix the request." }
            }
          }
        }
      }
    }
  }
}
