{
    "openapi": "3.1.0",
    "info": {
        "title": "Digital Greenhouse free tools API",
        "version": "1.0",
        "description": "Free, keyless endpoints for AI agents and scripts to check their work or look something up: Australian GST and ABN/ACN checks, DNS and email-setup checks, calculators, encoders and converters. Same maths as the tool pages at https://digitalgreenhouse.com.au/tools. Fair use: calculators 120/min per IP, dns-lookup 20/min, mx-email-check 6/min. General information only.",
        "contact": {
            "name": "Digital Greenhouse",
            "url": "https://digitalgreenhouse.com.au/contact"
        }
    },
    "servers": [
        {
            "url": "https://digitalgreenhouse.com.au/api/tools"
        }
    ],
    "externalDocs": {
        "url": "https://digitalgreenhouse.com.au/tools/api"
    },
    "paths": {
        "/gst-calculator": {
            "get": {
                "operationId": "gstCalculator",
                "summary": "GST Calculator (Australia)",
                "description": "Add Australia's 10% GST to a price, or work out the GST already included in a total. Human page: https://digitalgreenhouse.com.au/tools/gst-calculator",
                "tags": [
                    "Australian business"
                ],
                "parameters": [
                    {
                        "name": "amount",
                        "in": "query",
                        "required": true,
                        "description": "The amount in AUD. \"$1,100\" style input is accepted.",
                        "schema": {
                            "type": "number"
                        },
                        "example": "110"
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "add = the amount excludes GST; remove = the amount already includes GST.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "add",
                                "remove"
                            ],
                            "default": "add"
                        },
                        "example": "remove"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "gstCalculatorPost",
                "summary": "GST Calculator (Australia) (POST body)",
                "description": "Add Australia's 10% GST to a price, or work out the GST already included in a total.",
                "tags": [
                    "Australian business"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "description": "The amount in AUD. \"$1,100\" style input is accepted."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "add",
                                            "remove"
                                        ],
                                        "default": "add",
                                        "description": "add = the amount excludes GST; remove = the amount already includes GST."
                                    }
                                },
                                "required": [
                                    "amount"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "description": "The amount in AUD. \"$1,100\" style input is accepted."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "add",
                                            "remove"
                                        ],
                                        "default": "add",
                                        "description": "add = the amount excludes GST; remove = the amount already includes GST."
                                    }
                                },
                                "required": [
                                    "amount"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/abn-validator": {
            "get": {
                "operationId": "abnValidator",
                "summary": "ABN / ACN Validator",
                "description": "Check an Australian Business Number (11 digits) or Australian Company Number (9 digits) against its official checksum. Spaces and punctuation are ignored. Human page: https://digitalgreenhouse.com.au/tools/abn-validator",
                "tags": [
                    "Australian business"
                ],
                "parameters": [
                    {
                        "name": "number",
                        "in": "query",
                        "required": true,
                        "description": "The ABN or ACN.",
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "example": "51824753556"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "abnValidatorPost",
                "summary": "ABN / ACN Validator (POST body)",
                "description": "Check an Australian Business Number (11 digits) or Australian Company Number (9 digits) against its official checksum. Spaces and punctuation are ignored.",
                "tags": [
                    "Australian business"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "number": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "The ABN or ACN."
                                    }
                                },
                                "required": [
                                    "number"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "number": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "The ABN or ACN."
                                    }
                                },
                                "required": [
                                    "number"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/invoice-due-date": {
            "get": {
                "operationId": "invoiceDueDate",
                "summary": "Invoice Due-Date Calculator (Australia)",
                "description": "The due date for an invoice from its payment terms (net days, days after end of month, a day of the following month, business days, or on receipt), moved off weekends and Australian public holidays for the chosen state or territory. Only full-day statewide public holidays count. Human page: https://digitalgreenhouse.com.au/tools/invoice-due-date",
                "tags": [
                    "Australian business"
                ],
                "parameters": [
                    {
                        "name": "date",
                        "in": "query",
                        "required": true,
                        "description": "Invoice date, YYYY-MM-DD.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "2026-11-27"
                    },
                    {
                        "name": "terms",
                        "in": "query",
                        "required": false,
                        "description": "net = days after the invoice date; eom = days after the end of the invoice month; following = a day of the following month (set day); business = business days after the invoice date; receipt = due on the invoice date.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "net",
                                "eom",
                                "following",
                                "business",
                                "receipt"
                            ],
                            "default": "net"
                        },
                        "example": "net"
                    },
                    {
                        "name": "days",
                        "in": "query",
                        "required": false,
                        "description": "Number of days for net, eom and business terms.",
                        "schema": {
                            "type": "integer",
                            "default": 30,
                            "minimum": 0,
                            "maximum": 365
                        },
                        "example": "30"
                    },
                    {
                        "name": "day",
                        "in": "query",
                        "required": false,
                        "description": "Day of the following month for \"following\" terms (clamped to the month's length).",
                        "schema": {
                            "type": "integer",
                            "default": 20,
                            "minimum": 1,
                            "maximum": 31
                        }
                    },
                    {
                        "name": "state",
                        "in": "query",
                        "required": false,
                        "description": "Whose public holidays to skip: nsw, vic, qld, wa, sa, tas, act, nt, or national (only the holidays every state shares).",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "nsw",
                                "vic",
                                "qld",
                                "wa",
                                "sa",
                                "tas",
                                "act",
                                "nt",
                                "national"
                            ],
                            "default": "nsw"
                        },
                        "example": "nsw"
                    },
                    {
                        "name": "roll",
                        "in": "query",
                        "required": false,
                        "description": "If the due date lands on a weekend or public holiday: move to the next business day, the previous one, or leave it.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "next",
                                "previous",
                                "none"
                            ],
                            "default": "next"
                        }
                    },
                    {
                        "name": "holidays",
                        "in": "query",
                        "required": false,
                        "description": "false = skip weekends only.",
                        "schema": {
                            "type": "boolean",
                            "default": true
                        }
                    },
                    {
                        "name": "today",
                        "in": "query",
                        "required": false,
                        "description": "Date to count \"days from today\" from, YYYY-MM-DD. Defaults to today in Australia/Sydney.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "invoiceDueDatePost",
                "summary": "Invoice Due-Date Calculator (Australia) (POST body)",
                "description": "The due date for an invoice from its payment terms (net days, days after end of month, a day of the following month, business days, or on receipt), moved off weekends and Australian public holidays for the chosen state or territory. Only full-day statewide public holidays count.",
                "tags": [
                    "Australian business"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "date": {
                                        "type": "string",
                                        "description": "Invoice date, YYYY-MM-DD."
                                    },
                                    "terms": {
                                        "type": "string",
                                        "enum": [
                                            "net",
                                            "eom",
                                            "following",
                                            "business",
                                            "receipt"
                                        ],
                                        "default": "net",
                                        "description": "net = days after the invoice date; eom = days after the end of the invoice month; following = a day of the following month (set day); business = business days after the invoice date; receipt = due on the invoice date."
                                    },
                                    "days": {
                                        "type": "integer",
                                        "default": 30,
                                        "minimum": 0,
                                        "maximum": 365,
                                        "description": "Number of days for net, eom and business terms."
                                    },
                                    "day": {
                                        "type": "integer",
                                        "default": 20,
                                        "minimum": 1,
                                        "maximum": 31,
                                        "description": "Day of the following month for \"following\" terms (clamped to the month's length)."
                                    },
                                    "state": {
                                        "type": "string",
                                        "enum": [
                                            "nsw",
                                            "vic",
                                            "qld",
                                            "wa",
                                            "sa",
                                            "tas",
                                            "act",
                                            "nt",
                                            "national"
                                        ],
                                        "default": "nsw",
                                        "description": "Whose public holidays to skip: nsw, vic, qld, wa, sa, tas, act, nt, or national (only the holidays every state shares)."
                                    },
                                    "roll": {
                                        "type": "string",
                                        "enum": [
                                            "next",
                                            "previous",
                                            "none"
                                        ],
                                        "default": "next",
                                        "description": "If the due date lands on a weekend or public holiday: move to the next business day, the previous one, or leave it."
                                    },
                                    "holidays": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "false = skip weekends only."
                                    },
                                    "today": {
                                        "type": "string",
                                        "description": "Date to count \"days from today\" from, YYYY-MM-DD. Defaults to today in Australia/Sydney."
                                    }
                                },
                                "required": [
                                    "date"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "date": {
                                        "type": "string",
                                        "description": "Invoice date, YYYY-MM-DD."
                                    },
                                    "terms": {
                                        "type": "string",
                                        "enum": [
                                            "net",
                                            "eom",
                                            "following",
                                            "business",
                                            "receipt"
                                        ],
                                        "default": "net",
                                        "description": "net = days after the invoice date; eom = days after the end of the invoice month; following = a day of the following month (set day); business = business days after the invoice date; receipt = due on the invoice date."
                                    },
                                    "days": {
                                        "type": "integer",
                                        "default": 30,
                                        "minimum": 0,
                                        "maximum": 365,
                                        "description": "Number of days for net, eom and business terms."
                                    },
                                    "day": {
                                        "type": "integer",
                                        "default": 20,
                                        "minimum": 1,
                                        "maximum": 31,
                                        "description": "Day of the following month for \"following\" terms (clamped to the month's length)."
                                    },
                                    "state": {
                                        "type": "string",
                                        "enum": [
                                            "nsw",
                                            "vic",
                                            "qld",
                                            "wa",
                                            "sa",
                                            "tas",
                                            "act",
                                            "nt",
                                            "national"
                                        ],
                                        "default": "nsw",
                                        "description": "Whose public holidays to skip: nsw, vic, qld, wa, sa, tas, act, nt, or national (only the holidays every state shares)."
                                    },
                                    "roll": {
                                        "type": "string",
                                        "enum": [
                                            "next",
                                            "previous",
                                            "none"
                                        ],
                                        "default": "next",
                                        "description": "If the due date lands on a weekend or public holiday: move to the next business day, the previous one, or leave it."
                                    },
                                    "holidays": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "false = skip weekends only."
                                    },
                                    "today": {
                                        "type": "string",
                                        "description": "Date to count \"days from today\" from, YYYY-MM-DD. Defaults to today in Australia/Sydney."
                                    }
                                },
                                "required": [
                                    "date"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/dns-lookup": {
            "get": {
                "operationId": "dnsLookup",
                "summary": "DNS Record Lookup",
                "description": "Live A, AAAA, CNAME, MX, TXT, NS, SOA and CAA records for a domain, with plain-English notes and the DNSSEC status. Resolved over DNS-over-HTTPS (Cloudflare, falling back to Google). Human page: https://digitalgreenhouse.com.au/tools/dns-lookup",
                "tags": [
                    "Domain, DNS & network"
                ],
                "parameters": [
                    {
                        "name": "domain",
                        "in": "query",
                        "required": true,
                        "description": "Domain name. A URL or email address also works; the host part is used.",
                        "schema": {
                            "type": "string",
                            "maxLength": 300
                        },
                        "example": "digitalgreenhouse.com.au"
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "Record type(s), comma-separated: A, AAAA, CNAME, MX, TXT, NS, SOA, CAA, or all.",
                        "schema": {
                            "type": "string",
                            "default": "all"
                        },
                        "example": "MX,TXT"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "dnsLookupPost",
                "summary": "DNS Record Lookup (POST body)",
                "description": "Live A, AAAA, CNAME, MX, TXT, NS, SOA and CAA records for a domain, with plain-English notes and the DNSSEC status. Resolved over DNS-over-HTTPS (Cloudflare, falling back to Google).",
                "tags": [
                    "Domain, DNS & network"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL or email address also works; the host part is used."
                                    },
                                    "type": {
                                        "type": "string",
                                        "default": "all",
                                        "description": "Record type(s), comma-separated: A, AAAA, CNAME, MX, TXT, NS, SOA, CAA, or all."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL or email address also works; the host part is used."
                                    },
                                    "type": {
                                        "type": "string",
                                        "default": "all",
                                        "description": "Record type(s), comma-separated: A, AAAA, CNAME, MX, TXT, NS, SOA, CAA, or all."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/whois-lookup": {
            "get": {
                "operationId": "whoisLookup",
                "summary": "WHOIS / RDAP Domain Lookup",
                "description": "Who a domain is registered with, when it was registered and expires, its status codes in plain English, nameservers and DNSSEC, straight from the registry over RDAP (the modern replacement for WHOIS). .au domains also show the registrant and eligibility the .au registry publishes. A 404-style \"registered\": false means the registry has no such domain. One domain per request; registries do not allow bulk harvesting. Human page: https://digitalgreenhouse.com.au/tools/whois-lookup",
                "tags": [
                    "Domain, DNS & network"
                ],
                "parameters": [
                    {
                        "name": "domain",
                        "in": "query",
                        "required": true,
                        "description": "Domain name. A URL, email address or subdomain also works; the registered domain is looked up.",
                        "schema": {
                            "type": "string",
                            "maxLength": 300
                        },
                        "example": "digitalgreenhouse.com.au"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "whoisLookupPost",
                "summary": "WHOIS / RDAP Domain Lookup (POST body)",
                "description": "Who a domain is registered with, when it was registered and expires, its status codes in plain English, nameservers and DNSSEC, straight from the registry over RDAP (the modern replacement for WHOIS). .au domains also show the registrant and eligibility the .au registry publishes. A 404-style \"registered\": false means the registry has no such domain. One domain per request; registries do not allow bulk harvesting.",
                "tags": [
                    "Domain, DNS & network"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL, email address or subdomain also works; the registered domain is looked up."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL, email address or subdomain also works; the registered domain is looked up."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/mx-email-check": {
            "get": {
                "operationId": "mxEmailCheck",
                "summary": "MX & Email Setup Check",
                "description": "Checks a domain's email setup: MX servers (and whether they resolve), SPF (following every include and counting DNS lookups against the limit of 10), DKIM under 23 common selectors (or yours) with RSA key length, and DMARC policy. Returns a verdict and a plain-English list of what to fix, with copy-paste records. Human page: https://digitalgreenhouse.com.au/tools/mx-email-check",
                "tags": [
                    "Domain, DNS & network"
                ],
                "parameters": [
                    {
                        "name": "domain",
                        "in": "query",
                        "required": true,
                        "description": "Domain name. A URL or email address also works.",
                        "schema": {
                            "type": "string",
                            "maxLength": 300
                        },
                        "example": "digitalgreenhouse.com.au"
                    },
                    {
                        "name": "selector",
                        "in": "query",
                        "required": false,
                        "description": "Optional DKIM selector to check as well as the common ones (the s= value in a DKIM-Signature header).",
                        "schema": {
                            "type": "string",
                            "maxLength": 140
                        },
                        "example": "selector1"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "mxEmailCheckPost",
                "summary": "MX & Email Setup Check (POST body)",
                "description": "Checks a domain's email setup: MX servers (and whether they resolve), SPF (following every include and counting DNS lookups against the limit of 10), DKIM under 23 common selectors (or yours) with RSA key length, and DMARC policy. Returns a verdict and a plain-English list of what to fix, with copy-paste records.",
                "tags": [
                    "Domain, DNS & network"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL or email address also works."
                                    },
                                    "selector": {
                                        "type": "string",
                                        "maxLength": 140,
                                        "description": "Optional DKIM selector to check as well as the common ones (the s= value in a DKIM-Signature header)."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "domain": {
                                        "type": "string",
                                        "maxLength": 300,
                                        "description": "Domain name. A URL or email address also works."
                                    },
                                    "selector": {
                                        "type": "string",
                                        "maxLength": 140,
                                        "description": "Optional DKIM selector to check as well as the common ones (the s= value in a DKIM-Signature header)."
                                    }
                                },
                                "required": [
                                    "domain"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/subnet-calculator": {
            "get": {
                "operationId": "subnetCalculator",
                "summary": "Subnet / CIDR Calculator",
                "description": "Network, broadcast, netmask, wildcard, host range and usable host count for an IPv4 CIDR block. Human page: https://digitalgreenhouse.com.au/tools/subnet-calculator",
                "tags": [
                    "Domain, DNS & network"
                ],
                "parameters": [
                    {
                        "name": "cidr",
                        "in": "query",
                        "required": true,
                        "description": "IPv4 address with prefix length.",
                        "schema": {
                            "type": "string",
                            "maxLength": 40
                        },
                        "example": "192.168.10.37/26"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "subnetCalculatorPost",
                "summary": "Subnet / CIDR Calculator (POST body)",
                "description": "Network, broadcast, netmask, wildcard, host range and usable host count for an IPv4 CIDR block.",
                "tags": [
                    "Domain, DNS & network"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "cidr": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "IPv4 address with prefix length."
                                    }
                                },
                                "required": [
                                    "cidr"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "cidr": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "IPv4 address with prefix length."
                                    }
                                },
                                "required": [
                                    "cidr"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/whats-my-ip": {
            "get": {
                "operationId": "whatsMyIp",
                "summary": "What's My IP",
                "description": "The public IP address the request came from, and its reverse DNS name. Called by an agent, this is the agent's own server address. Human page: https://digitalgreenhouse.com.au/tools/whats-my-ip",
                "tags": [
                    "Domain, DNS & network"
                ],
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "whatsMyIpPost",
                "summary": "What's My IP (POST body)",
                "description": "The public IP address the request came from, and its reverse DNS name. Called by an agent, this is the agent's own server address.",
                "tags": [
                    "Domain, DNS & network"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {}
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {}
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/percentage-calculator": {
            "get": {
                "operationId": "percentageCalculator",
                "summary": "Percentage Calculator",
                "description": "From two numbers x and y: x% of y, x as a percentage of y, and the percentage change from x to y. Human page: https://digitalgreenhouse.com.au/tools/percentage-calculator",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "x",
                        "in": "query",
                        "required": true,
                        "description": "First number.",
                        "schema": {
                            "type": "number"
                        },
                        "example": "15"
                    },
                    {
                        "name": "y",
                        "in": "query",
                        "required": true,
                        "description": "Second number.",
                        "schema": {
                            "type": "number"
                        },
                        "example": "80"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "percentageCalculatorPost",
                "summary": "Percentage Calculator (POST body)",
                "description": "From two numbers x and y: x% of y, x as a percentage of y, and the percentage change from x to y.",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "x": {
                                        "type": "number",
                                        "description": "First number."
                                    },
                                    "y": {
                                        "type": "number",
                                        "description": "Second number."
                                    }
                                },
                                "required": [
                                    "x",
                                    "y"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "x": {
                                        "type": "number",
                                        "description": "First number."
                                    },
                                    "y": {
                                        "type": "number",
                                        "description": "Second number."
                                    }
                                },
                                "required": [
                                    "x",
                                    "y"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/discount-calculator": {
            "get": {
                "operationId": "discountCalculator",
                "summary": "Discount / Sale Price",
                "description": "Sale price and saving after a percentage discount, with an optional stacked \"extra % off\". Human page: https://digitalgreenhouse.com.au/tools/discount-calculator",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "price",
                        "in": "query",
                        "required": true,
                        "description": "Original price.",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        },
                        "example": "249.95"
                    },
                    {
                        "name": "discount",
                        "in": "query",
                        "required": true,
                        "description": "Percentage off.",
                        "schema": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": "30"
                    },
                    {
                        "name": "extra",
                        "in": "query",
                        "required": false,
                        "description": "Optional further percentage off the already-reduced price.",
                        "schema": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": "10"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "discountCalculatorPost",
                "summary": "Discount / Sale Price (POST body)",
                "description": "Sale price and saving after a percentage discount, with an optional stacked \"extra % off\".",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "price": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Original price."
                                    },
                                    "discount": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Percentage off."
                                    },
                                    "extra": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Optional further percentage off the already-reduced price."
                                    }
                                },
                                "required": [
                                    "price",
                                    "discount"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "price": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Original price."
                                    },
                                    "discount": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Percentage off."
                                    },
                                    "extra": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Optional further percentage off the already-reduced price."
                                    }
                                },
                                "required": [
                                    "price",
                                    "discount"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/loan-calculator": {
            "get": {
                "operationId": "loanCalculator",
                "summary": "Loan Repayment Calculator",
                "description": "Monthly repayment, total repaid and total interest for a fixed-rate loan (standard amortisation, monthly compounding). Human page: https://digitalgreenhouse.com.au/tools/loan-calculator",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "amount",
                        "in": "query",
                        "required": true,
                        "description": "Amount borrowed.",
                        "schema": {
                            "type": "number",
                            "minimum": 0.01
                        },
                        "example": "35000"
                    },
                    {
                        "name": "rate",
                        "in": "query",
                        "required": true,
                        "description": "Annual interest rate in percent.",
                        "schema": {
                            "type": "number",
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": "8.5"
                    },
                    {
                        "name": "years",
                        "in": "query",
                        "required": true,
                        "description": "Loan term in years (decimals allowed).",
                        "schema": {
                            "type": "number",
                            "minimum": 0.08,
                            "maximum": 50
                        },
                        "example": "5"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "loanCalculatorPost",
                "summary": "Loan Repayment Calculator (POST body)",
                "description": "Monthly repayment, total repaid and total interest for a fixed-rate loan (standard amortisation, monthly compounding).",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0.01,
                                        "description": "Amount borrowed."
                                    },
                                    "rate": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Annual interest rate in percent."
                                    },
                                    "years": {
                                        "type": "number",
                                        "minimum": 0.08,
                                        "maximum": 50,
                                        "description": "Loan term in years (decimals allowed)."
                                    }
                                },
                                "required": [
                                    "amount",
                                    "rate",
                                    "years"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0.01,
                                        "description": "Amount borrowed."
                                    },
                                    "rate": {
                                        "type": "number",
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Annual interest rate in percent."
                                    },
                                    "years": {
                                        "type": "number",
                                        "minimum": 0.08,
                                        "maximum": 50,
                                        "description": "Loan term in years (decimals allowed)."
                                    }
                                },
                                "required": [
                                    "amount",
                                    "rate",
                                    "years"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/bill-splitter": {
            "get": {
                "operationId": "billSplitter",
                "summary": "Bill Splitter & Tip",
                "description": "Split a bill between people, with an optional tip percentage. Each share is rounded up to the cent. Human page: https://digitalgreenhouse.com.au/tools/bill-splitter",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "total",
                        "in": "query",
                        "required": true,
                        "description": "Bill total.",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        },
                        "example": "187.40"
                    },
                    {
                        "name": "people",
                        "in": "query",
                        "required": true,
                        "description": "Number of people.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 1000
                        },
                        "example": "4"
                    },
                    {
                        "name": "tip",
                        "in": "query",
                        "required": false,
                        "description": "Tip percentage.",
                        "schema": {
                            "type": "number",
                            "default": 0,
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": "10"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "billSplitterPost",
                "summary": "Bill Splitter & Tip (POST body)",
                "description": "Split a bill between people, with an optional tip percentage. Each share is rounded up to the cent.",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "total": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Bill total."
                                    },
                                    "people": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 1000,
                                        "description": "Number of people."
                                    },
                                    "tip": {
                                        "type": "number",
                                        "default": 0,
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Tip percentage."
                                    }
                                },
                                "required": [
                                    "total",
                                    "people"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "total": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Bill total."
                                    },
                                    "people": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 1000,
                                        "description": "Number of people."
                                    },
                                    "tip": {
                                        "type": "number",
                                        "default": 0,
                                        "minimum": 0,
                                        "maximum": 100,
                                        "description": "Tip percentage."
                                    }
                                },
                                "required": [
                                    "total",
                                    "people"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/bmi-calculator": {
            "get": {
                "operationId": "bmiCalculator",
                "summary": "BMI Calculator",
                "description": "Body Mass Index and its standard category, from metric or imperial measurements. Screening number only, not medical advice. Human page: https://digitalgreenhouse.com.au/tools/bmi-calculator",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "weight_kg",
                        "in": "query",
                        "required": false,
                        "description": "Weight in kilograms (metric).",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        },
                        "example": "72"
                    },
                    {
                        "name": "height_cm",
                        "in": "query",
                        "required": false,
                        "description": "Height in centimetres (metric).",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        },
                        "example": "178"
                    },
                    {
                        "name": "weight_lb",
                        "in": "query",
                        "required": false,
                        "description": "Weight in pounds (imperial).",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        }
                    },
                    {
                        "name": "height_ft",
                        "in": "query",
                        "required": false,
                        "description": "Height, feet part (imperial).",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        }
                    },
                    {
                        "name": "height_in",
                        "in": "query",
                        "required": false,
                        "description": "Height, inches part (imperial).",
                        "schema": {
                            "type": "number",
                            "minimum": 0
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "bmiCalculatorPost",
                "summary": "BMI Calculator (POST body)",
                "description": "Body Mass Index and its standard category, from metric or imperial measurements. Screening number only, not medical advice.",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "weight_kg": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Weight in kilograms (metric)."
                                    },
                                    "height_cm": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height in centimetres (metric)."
                                    },
                                    "weight_lb": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Weight in pounds (imperial)."
                                    },
                                    "height_ft": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height, feet part (imperial)."
                                    },
                                    "height_in": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height, inches part (imperial)."
                                    }
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "weight_kg": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Weight in kilograms (metric)."
                                    },
                                    "height_cm": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height in centimetres (metric)."
                                    },
                                    "weight_lb": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Weight in pounds (imperial)."
                                    },
                                    "height_ft": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height, feet part (imperial)."
                                    },
                                    "height_in": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "Height, inches part (imperial)."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/age-calculator": {
            "get": {
                "operationId": "ageCalculator",
                "summary": "Age Calculator",
                "description": "Exact age in years, months and days on a date (default today in Sydney), plus totals and days until the next birthday. Also works as a date-difference calculator. Human page: https://digitalgreenhouse.com.au/tools/age-calculator",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "dob",
                        "in": "query",
                        "required": true,
                        "description": "Date of birth (or start date), YYYY-MM-DD.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "1990-02-28"
                    },
                    {
                        "name": "on",
                        "in": "query",
                        "required": false,
                        "description": "Date to measure to, YYYY-MM-DD. Defaults to today in Australia/Sydney.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "2026-10-02"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "ageCalculatorPost",
                "summary": "Age Calculator (POST body)",
                "description": "Exact age in years, months and days on a date (default today in Sydney), plus totals and days until the next birthday. Also works as a date-difference calculator.",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "dob": {
                                        "type": "string",
                                        "description": "Date of birth (or start date), YYYY-MM-DD."
                                    },
                                    "on": {
                                        "type": "string",
                                        "description": "Date to measure to, YYYY-MM-DD. Defaults to today in Australia/Sydney."
                                    }
                                },
                                "required": [
                                    "dob"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "dob": {
                                        "type": "string",
                                        "description": "Date of birth (or start date), YYYY-MM-DD."
                                    },
                                    "on": {
                                        "type": "string",
                                        "description": "Date to measure to, YYYY-MM-DD. Defaults to today in Australia/Sydney."
                                    }
                                },
                                "required": [
                                    "dob"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/unit-converter": {
            "get": {
                "operationId": "unitConverter",
                "summary": "Unit Converter",
                "description": "Convert length, weight, volume (US measures), area, speed and temperature. Units: m km cm mm mi yd ft in · kg g mg t lb oz st · L mL gal qt pt cup floz · m2 km2 ha ft2 acre · m/s km/h mph kn · C F K (common names like \"pounds\" or \"celsius\" also work). Human page: https://digitalgreenhouse.com.au/tools/unit-converter",
                "tags": [
                    "Everyday & calculators"
                ],
                "parameters": [
                    {
                        "name": "value",
                        "in": "query",
                        "required": true,
                        "description": "The number to convert.",
                        "schema": {
                            "type": "number"
                        },
                        "example": "26.2"
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": true,
                        "description": "Unit to convert from.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "mi"
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": true,
                        "description": "Unit to convert to.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "km"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "unitConverterPost",
                "summary": "Unit Converter (POST body)",
                "description": "Convert length, weight, volume (US measures), area, speed and temperature. Units: m km cm mm mi yd ft in · kg g mg t lb oz st · L mL gal qt pt cup floz · m2 km2 ha ft2 acre · m/s km/h mph kn · C F K (common names like \"pounds\" or \"celsius\" also work).",
                "tags": [
                    "Everyday & calculators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "value": {
                                        "type": "number",
                                        "description": "The number to convert."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Unit to convert from."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Unit to convert to."
                                    }
                                },
                                "required": [
                                    "value",
                                    "from",
                                    "to"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "value": {
                                        "type": "number",
                                        "description": "The number to convert."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Unit to convert from."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Unit to convert to."
                                    }
                                },
                                "required": [
                                    "value",
                                    "from",
                                    "to"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/epoch-converter": {
            "get": {
                "operationId": "epochConverter",
                "summary": "Unix Timestamp Converter",
                "description": "Convert a Unix timestamp (seconds or milliseconds) to UTC, ISO 8601 and Sydney time (AEST/AEDT), or a date to a timestamp. With neither, returns the current time. Human page: https://digitalgreenhouse.com.au/tools/epoch-converter",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "timestamp",
                        "in": "query",
                        "required": false,
                        "description": "Unix timestamp in seconds or milliseconds.",
                        "schema": {
                            "type": "string",
                            "maxLength": 40
                        },
                        "example": "1759363200"
                    },
                    {
                        "name": "unit",
                        "in": "query",
                        "required": false,
                        "description": "auto treats 13+ digits as milliseconds.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "s",
                                "ms"
                            ],
                            "default": "auto"
                        }
                    },
                    {
                        "name": "date",
                        "in": "query",
                        "required": false,
                        "description": "A date/time to convert to a timestamp, ideally ISO 8601 (2026-10-02T09:30:00+10:00). Without an offset it is read in tz.",
                        "schema": {
                            "type": "string",
                            "maxLength": 100
                        }
                    },
                    {
                        "name": "tz",
                        "in": "query",
                        "required": false,
                        "description": "IANA time zone for reading \"date\" and for an extra local-time view, e.g. Australia/Perth.",
                        "schema": {
                            "type": "string",
                            "default": "Australia/Sydney",
                            "maxLength": 64
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "epochConverterPost",
                "summary": "Unix Timestamp Converter (POST body)",
                "description": "Convert a Unix timestamp (seconds or milliseconds) to UTC, ISO 8601 and Sydney time (AEST/AEDT), or a date to a timestamp. With neither, returns the current time.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "timestamp": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "Unix timestamp in seconds or milliseconds."
                                    },
                                    "unit": {
                                        "type": "string",
                                        "enum": [
                                            "auto",
                                            "s",
                                            "ms"
                                        ],
                                        "default": "auto",
                                        "description": "auto treats 13+ digits as milliseconds."
                                    },
                                    "date": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "A date/time to convert to a timestamp, ideally ISO 8601 (2026-10-02T09:30:00+10:00). Without an offset it is read in tz."
                                    },
                                    "tz": {
                                        "type": "string",
                                        "default": "Australia/Sydney",
                                        "maxLength": 64,
                                        "description": "IANA time zone for reading \"date\" and for an extra local-time view, e.g. Australia/Perth."
                                    }
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "timestamp": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "Unix timestamp in seconds or milliseconds."
                                    },
                                    "unit": {
                                        "type": "string",
                                        "enum": [
                                            "auto",
                                            "s",
                                            "ms"
                                        ],
                                        "default": "auto",
                                        "description": "auto treats 13+ digits as milliseconds."
                                    },
                                    "date": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "A date/time to convert to a timestamp, ideally ISO 8601 (2026-10-02T09:30:00+10:00). Without an offset it is read in tz."
                                    },
                                    "tz": {
                                        "type": "string",
                                        "default": "Australia/Sydney",
                                        "maxLength": 64,
                                        "description": "IANA time zone for reading \"date\" and for an extra local-time view, e.g. Australia/Perth."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/base64": {
            "get": {
                "operationId": "base64",
                "summary": "Base64 Encode / Decode",
                "description": "Encode UTF-8 text to Base64, or decode Base64 (standard or URL-safe) back to text. Binary results come back as hex. Human page: https://digitalgreenhouse.com.au/tools/base64",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "Text to encode, or Base64 to decode.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "encode or decode.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "encode",
                                "decode"
                            ],
                            "default": "encode"
                        }
                    },
                    {
                        "name": "urlsafe",
                        "in": "query",
                        "required": false,
                        "description": "Use the URL-safe alphabet (- and _, no padding).",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "base64Post",
                "summary": "Base64 Encode / Decode (POST body)",
                "description": "Encode UTF-8 text to Base64, or decode Base64 (standard or URL-safe) back to text. Binary results come back as hex.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or Base64 to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "urlsafe": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Use the URL-safe alphabet (- and _, no padding)."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or Base64 to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "urlsafe": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Use the URL-safe alphabet (- and _, no padding)."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/url-encode": {
            "get": {
                "operationId": "urlEncode",
                "summary": "URL Encode / Decode",
                "description": "Percent-encode or decode text with exactly the rules of JavaScript's encodeURIComponent/decodeURIComponent (scope=component) or encodeURI/decodeURI (scope=full). Human page: https://digitalgreenhouse.com.au/tools/url-encode",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "Text to encode or decode.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "encode or decode.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "encode",
                                "decode"
                            ],
                            "default": "encode"
                        }
                    },
                    {
                        "name": "scope",
                        "in": "query",
                        "required": false,
                        "description": "component = one query value or path segment; full = a whole URL.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "component",
                                "full"
                            ],
                            "default": "component"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "urlEncodePost",
                "summary": "URL Encode / Decode (POST body)",
                "description": "Percent-encode or decode text with exactly the rules of JavaScript's encodeURIComponent/decodeURIComponent (scope=component) or encodeURI/decodeURI (scope=full).",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode or decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "scope": {
                                        "type": "string",
                                        "enum": [
                                            "component",
                                            "full"
                                        ],
                                        "default": "component",
                                        "description": "component = one query value or path segment; full = a whole URL."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode or decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "scope": {
                                        "type": "string",
                                        "enum": [
                                            "component",
                                            "full"
                                        ],
                                        "default": "component",
                                        "description": "component = one query value or path segment; full = a whole URL."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/html-entity": {
            "get": {
                "operationId": "htmlEntity",
                "summary": "HTML Entity Encoder",
                "description": "Escape & < > \" ' as HTML entities (optionally every non-ASCII character too), or decode entities back to text. Human page: https://digitalgreenhouse.com.au/tools/html-entity",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "Text to encode, or HTML with entities to decode.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "encode or decode.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "encode",
                                "decode"
                            ],
                            "default": "encode"
                        }
                    },
                    {
                        "name": "all",
                        "in": "query",
                        "required": false,
                        "description": "When encoding, also turn non-ASCII characters into numeric entities.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "htmlEntityPost",
                "summary": "HTML Entity Encoder (POST body)",
                "description": "Escape & < > \" ' as HTML entities (optionally every non-ASCII character too), or decode entities back to text.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or HTML with entities to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "all": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "When encoding, also turn non-ASCII characters into numeric entities."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or HTML with entities to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "encode",
                                        "description": "encode or decode."
                                    },
                                    "all": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "When encoding, also turn non-ASCII characters into numeric entities."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/morse-code": {
            "get": {
                "operationId": "morseCode",
                "summary": "Morse Code Translator",
                "description": "Translate text to International Morse code (ITU-R M.1677-1) or Morse back to text, with how long it takes to send at a given speed. Morse output separates letters with a space and words with \" / \"; input also accepts | or three spaces between words, and · − for dots and dashes. Prosigns go in angle brackets, e.g. <SOS>. Human page: https://digitalgreenhouse.com.au/tools/morse-code",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "Text to encode, or Morse code to decode.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "auto decodes when the input is only dots, dashes and separators, and encodes anything else.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "auto",
                                "encode",
                                "decode"
                            ],
                            "default": "auto"
                        }
                    },
                    {
                        "name": "wpm",
                        "in": "query",
                        "required": false,
                        "description": "Character speed in words per minute (PARIS standard), used for the timing.",
                        "schema": {
                            "type": "integer",
                            "default": 20,
                            "minimum": 5,
                            "maximum": 60
                        }
                    },
                    {
                        "name": "farnsworth",
                        "in": "query",
                        "required": false,
                        "description": "Optional slower overall speed in wpm: letters stay at wpm and the gaps stretch (Farnsworth spacing).",
                        "schema": {
                            "type": "integer",
                            "minimum": 3,
                            "maximum": 60
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "morseCodePost",
                "summary": "Morse Code Translator (POST body)",
                "description": "Translate text to International Morse code (ITU-R M.1677-1) or Morse back to text, with how long it takes to send at a given speed. Morse output separates letters with a space and words with \" / \"; input also accepts | or three spaces between words, and · − for dots and dashes. Prosigns go in angle brackets, e.g. <SOS>.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or Morse code to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "auto",
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "auto",
                                        "description": "auto decodes when the input is only dots, dashes and separators, and encodes anything else."
                                    },
                                    "wpm": {
                                        "type": "integer",
                                        "default": 20,
                                        "minimum": 5,
                                        "maximum": 60,
                                        "description": "Character speed in words per minute (PARIS standard), used for the timing."
                                    },
                                    "farnsworth": {
                                        "type": "integer",
                                        "minimum": 3,
                                        "maximum": 60,
                                        "description": "Optional slower overall speed in wpm: letters stay at wpm and the gaps stretch (Farnsworth spacing)."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "Text to encode, or Morse code to decode."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "auto",
                                            "encode",
                                            "decode"
                                        ],
                                        "default": "auto",
                                        "description": "auto decodes when the input is only dots, dashes and separators, and encodes anything else."
                                    },
                                    "wpm": {
                                        "type": "integer",
                                        "default": 20,
                                        "minimum": 5,
                                        "maximum": 60,
                                        "description": "Character speed in words per minute (PARIS standard), used for the timing."
                                    },
                                    "farnsworth": {
                                        "type": "integer",
                                        "minimum": 3,
                                        "maximum": 60,
                                        "description": "Optional slower overall speed in wpm: letters stay at wpm and the gaps stretch (Farnsworth spacing)."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/slugify": {
            "get": {
                "operationId": "slugify",
                "summary": "Slugify (URL Slug)",
                "description": "Turn a title into a clean URL slug: accents stripped, anything that is not a letter or digit becomes the separator. Human page: https://digitalgreenhouse.com.au/tools/slugify",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "The title or text.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "separator",
                        "in": "query",
                        "required": false,
                        "description": "Hyphen or underscore.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "-",
                                "_"
                            ],
                            "default": "-"
                        }
                    },
                    {
                        "name": "lowercase",
                        "in": "query",
                        "required": false,
                        "description": "Lower-case the slug.",
                        "schema": {
                            "type": "boolean",
                            "default": true
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "slugifyPost",
                "summary": "Slugify (URL Slug) (POST body)",
                "description": "Turn a title into a clean URL slug: accents stripped, anything that is not a letter or digit becomes the separator.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The title or text."
                                    },
                                    "separator": {
                                        "type": "string",
                                        "enum": [
                                            "-",
                                            "_"
                                        ],
                                        "default": "-",
                                        "description": "Hyphen or underscore."
                                    },
                                    "lowercase": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "Lower-case the slug."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The title or text."
                                    },
                                    "separator": {
                                        "type": "string",
                                        "enum": [
                                            "-",
                                            "_"
                                        ],
                                        "default": "-",
                                        "description": "Hyphen or underscore."
                                    },
                                    "lowercase": {
                                        "type": "boolean",
                                        "default": true,
                                        "description": "Lower-case the slug."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/text-case-converter": {
            "get": {
                "operationId": "textCaseConverter",
                "summary": "Text Case Converter",
                "description": "Convert text to lowercase, UPPERCASE, Title Case, Sentence case, camelCase, PascalCase, snake_case, kebab-case or CONSTANT_CASE. Splits words on spaces, - _ and camel humps. Human page: https://digitalgreenhouse.com.au/tools/text-case-converter",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "The text.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "case",
                        "in": "query",
                        "required": false,
                        "description": "One case, or all of them.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "lower",
                                "upper",
                                "title",
                                "sentence",
                                "camel",
                                "pascal",
                                "snake",
                                "kebab",
                                "constant"
                            ],
                            "default": "all"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "textCaseConverterPost",
                "summary": "Text Case Converter (POST body)",
                "description": "Convert text to lowercase, UPPERCASE, Title Case, Sentence case, camelCase, PascalCase, snake_case, kebab-case or CONSTANT_CASE. Splits words on spaces, - _ and camel humps.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The text."
                                    },
                                    "case": {
                                        "type": "string",
                                        "enum": [
                                            "all",
                                            "lower",
                                            "upper",
                                            "title",
                                            "sentence",
                                            "camel",
                                            "pascal",
                                            "snake",
                                            "kebab",
                                            "constant"
                                        ],
                                        "default": "all",
                                        "description": "One case, or all of them."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The text."
                                    },
                                    "case": {
                                        "type": "string",
                                        "enum": [
                                            "all",
                                            "lower",
                                            "upper",
                                            "title",
                                            "sentence",
                                            "camel",
                                            "pascal",
                                            "snake",
                                            "kebab",
                                            "constant"
                                        ],
                                        "default": "all",
                                        "description": "One case, or all of them."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/json-formatter": {
            "get": {
                "operationId": "jsonFormatter",
                "summary": "JSON Formatter & Validator",
                "description": "Validate JSON and point to the first error by line and column, or pretty-print / minify it. Send large documents as a POST body. Human page: https://digitalgreenhouse.com.au/tools/json-formatter",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "The JSON text.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "validate only, or also return formatted/minified output.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "validate",
                                "format",
                                "minify"
                            ],
                            "default": "validate"
                        }
                    },
                    {
                        "name": "indent",
                        "in": "query",
                        "required": false,
                        "description": "Indent for mode=format.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "2",
                                "4",
                                "tab"
                            ],
                            "default": "2"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "jsonFormatterPost",
                "summary": "JSON Formatter & Validator (POST body)",
                "description": "Validate JSON and point to the first error by line and column, or pretty-print / minify it. Send large documents as a POST body.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The JSON text."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "validate",
                                            "format",
                                            "minify"
                                        ],
                                        "default": "validate",
                                        "description": "validate only, or also return formatted/minified output."
                                    },
                                    "indent": {
                                        "type": "string",
                                        "enum": [
                                            "2",
                                            "4",
                                            "tab"
                                        ],
                                        "default": "2",
                                        "description": "Indent for mode=format."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The JSON text."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "validate",
                                            "format",
                                            "minify"
                                        ],
                                        "default": "validate",
                                        "description": "validate only, or also return formatted/minified output."
                                    },
                                    "indent": {
                                        "type": "string",
                                        "enum": [
                                            "2",
                                            "4",
                                            "tab"
                                        ],
                                        "default": "2",
                                        "description": "Indent for mode=format."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/jwt-decoder": {
            "post": {
                "operationId": "jwtDecoder",
                "summary": "JWT Decoder",
                "description": "Decode a JSON Web Token's header and payload and report expiry (exp), not-before (nbf) and issued-at (iat). The signature is NOT verified. POST only, so tokens never appear in URLs or server logs.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "token": {
                                        "type": "string",
                                        "maxLength": 16384,
                                        "description": "The JWT (header.payload.signature)."
                                    }
                                },
                                "required": [
                                    "token"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "token": {
                                        "type": "string",
                                        "maxLength": 16384,
                                        "description": "The JWT (header.payload.signature)."
                                    }
                                },
                                "required": [
                                    "token"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/hash-generator": {
            "get": {
                "operationId": "hashGenerator",
                "summary": "Hash Generator",
                "description": "MD5, SHA-1, SHA-256, SHA-384 and SHA-512 of text (as UTF-8 bytes) or of hex/Base64 bytes, with an optional check against an expected hash. Use POST for anything sensitive. Human page: https://digitalgreenhouse.com.au/tools/hash-generator",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "The input.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "algorithm",
                        "in": "query",
                        "required": false,
                        "description": "One algorithm, or all.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "md5",
                                "sha1",
                                "sha256",
                                "sha384",
                                "sha512"
                            ],
                            "default": "all"
                        }
                    },
                    {
                        "name": "input_encoding",
                        "in": "query",
                        "required": false,
                        "description": "How \"text\" is encoded: text = UTF-8 string; hex or base64 = raw bytes.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "text",
                                "hex",
                                "base64"
                            ],
                            "default": "text"
                        }
                    },
                    {
                        "name": "expect",
                        "in": "query",
                        "required": false,
                        "description": "Optional expected hash (hex) to compare against.",
                        "schema": {
                            "type": "string",
                            "maxLength": 200
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "hashGeneratorPost",
                "summary": "Hash Generator (POST body)",
                "description": "MD5, SHA-1, SHA-256, SHA-384 and SHA-512 of text (as UTF-8 bytes) or of hex/Base64 bytes, with an optional check against an expected hash. Use POST for anything sensitive.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The input."
                                    },
                                    "algorithm": {
                                        "type": "string",
                                        "enum": [
                                            "all",
                                            "md5",
                                            "sha1",
                                            "sha256",
                                            "sha384",
                                            "sha512"
                                        ],
                                        "default": "all",
                                        "description": "One algorithm, or all."
                                    },
                                    "input_encoding": {
                                        "type": "string",
                                        "enum": [
                                            "text",
                                            "hex",
                                            "base64"
                                        ],
                                        "default": "text",
                                        "description": "How \"text\" is encoded: text = UTF-8 string; hex or base64 = raw bytes."
                                    },
                                    "expect": {
                                        "type": "string",
                                        "maxLength": 200,
                                        "description": "Optional expected hash (hex) to compare against."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The input."
                                    },
                                    "algorithm": {
                                        "type": "string",
                                        "enum": [
                                            "all",
                                            "md5",
                                            "sha1",
                                            "sha256",
                                            "sha384",
                                            "sha512"
                                        ],
                                        "default": "all",
                                        "description": "One algorithm, or all."
                                    },
                                    "input_encoding": {
                                        "type": "string",
                                        "enum": [
                                            "text",
                                            "hex",
                                            "base64"
                                        ],
                                        "default": "text",
                                        "description": "How \"text\" is encoded: text = UTF-8 string; hex or base64 = raw bytes."
                                    },
                                    "expect": {
                                        "type": "string",
                                        "maxLength": 200,
                                        "description": "Optional expected hash (hex) to compare against."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/uuid-generator": {
            "get": {
                "operationId": "uuidGenerator",
                "summary": "UUID / ULID Generator",
                "description": "Generate random UUID v4, time-ordered UUID v7, or ULIDs, up to 100 at a time. Human page: https://digitalgreenhouse.com.au/tools/uuid-generator",
                "tags": [
                    "Encoders & converters"
                ],
                "parameters": [
                    {
                        "name": "version",
                        "in": "query",
                        "required": false,
                        "description": "v4, v7 or ulid.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "v4",
                                "v7",
                                "ulid"
                            ],
                            "default": "v4"
                        }
                    },
                    {
                        "name": "count",
                        "in": "query",
                        "required": false,
                        "description": "How many.",
                        "schema": {
                            "type": "integer",
                            "default": 1,
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "uppercase",
                        "in": "query",
                        "required": false,
                        "description": "Upper-case UUIDs (ULIDs are always upper-case).",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "uuidGeneratorPost",
                "summary": "UUID / ULID Generator (POST body)",
                "description": "Generate random UUID v4, time-ordered UUID v7, or ULIDs, up to 100 at a time.",
                "tags": [
                    "Encoders & converters"
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "version": {
                                        "type": "string",
                                        "enum": [
                                            "v4",
                                            "v7",
                                            "ulid"
                                        ],
                                        "default": "v4",
                                        "description": "v4, v7 or ulid."
                                    },
                                    "count": {
                                        "type": "integer",
                                        "default": 1,
                                        "minimum": 1,
                                        "maximum": 100,
                                        "description": "How many."
                                    },
                                    "uppercase": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Upper-case UUIDs (ULIDs are always upper-case)."
                                    }
                                }
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "version": {
                                        "type": "string",
                                        "enum": [
                                            "v4",
                                            "v7",
                                            "ulid"
                                        ],
                                        "default": "v4",
                                        "description": "v4, v7 or ulid."
                                    },
                                    "count": {
                                        "type": "integer",
                                        "default": 1,
                                        "minimum": 1,
                                        "maximum": 100,
                                        "description": "How many."
                                    },
                                    "uppercase": {
                                        "type": "boolean",
                                        "default": false,
                                        "description": "Upper-case UUIDs (ULIDs are always upper-case)."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/word-counter": {
            "get": {
                "operationId": "wordCounter",
                "summary": "Word & Character Counter",
                "description": "Words, characters (with and without spaces), UTF-8 bytes, sentences, paragraphs, and reading/speaking time. Send long text as a POST body. Human page: https://digitalgreenhouse.com.au/tools/word-counter",
                "tags": [
                    "Text & generators"
                ],
                "parameters": [
                    {
                        "name": "text",
                        "in": "query",
                        "required": true,
                        "description": "The text to count.",
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "wordCounterPost",
                "summary": "Word & Character Counter (POST body)",
                "description": "Words, characters (with and without spaces), UTF-8 bytes, sentences, paragraphs, and reading/speaking time. Send long text as a POST body.",
                "tags": [
                    "Text & generators"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The text to count."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "text": {
                                        "type": "string",
                                        "description": "The text to count."
                                    }
                                },
                                "required": [
                                    "text"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/color-converter": {
            "get": {
                "operationId": "colorConverter",
                "summary": "Colour Converter",
                "description": "Convert a colour between HEX, RGB and HSL. Human page: https://digitalgreenhouse.com.au/tools/color-converter",
                "tags": [
                    "Design & colour"
                ],
                "parameters": [
                    {
                        "name": "color",
                        "in": "query",
                        "required": true,
                        "description": "HEX (#0E5C3A or 0E5C3A or #abc), rgb(14, 92, 58) or hsl(155, 74%, 21%).",
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "example": "#0E5C3A"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "colorConverterPost",
                "summary": "Colour Converter (POST body)",
                "description": "Convert a colour between HEX, RGB and HSL.",
                "tags": [
                    "Design & colour"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "color": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "HEX (#0E5C3A or 0E5C3A or #abc), rgb(14, 92, 58) or hsl(155, 74%, 21%)."
                                    }
                                },
                                "required": [
                                    "color"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "color": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "HEX (#0E5C3A or 0E5C3A or #abc), rgb(14, 92, 58) or hsl(155, 74%, 21%)."
                                    }
                                },
                                "required": [
                                    "color"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/contrast-checker": {
            "get": {
                "operationId": "contrastChecker",
                "summary": "WCAG Contrast Checker",
                "description": "Contrast ratio between a text colour and a background colour, with pass/fail for WCAG 2.x AA and AAA (normal text, large text, UI components). Human page: https://digitalgreenhouse.com.au/tools/contrast-checker",
                "tags": [
                    "Design & colour"
                ],
                "parameters": [
                    {
                        "name": "fg",
                        "in": "query",
                        "required": true,
                        "description": "Text (foreground) colour: HEX, rgb() or hsl().",
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "example": "#767676"
                    },
                    {
                        "name": "bg",
                        "in": "query",
                        "required": true,
                        "description": "Background colour: HEX, rgb() or hsl().",
                        "schema": {
                            "type": "string",
                            "maxLength": 64
                        },
                        "example": "#FFFFFF"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "operationId": "contrastCheckerPost",
                "summary": "WCAG Contrast Checker (POST body)",
                "description": "Contrast ratio between a text colour and a background colour, with pass/fail for WCAG 2.x AA and AAA (normal text, large text, UI components).",
                "tags": [
                    "Design & colour"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fg": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "Text (foreground) colour: HEX, rgb() or hsl()."
                                    },
                                    "bg": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "Background colour: HEX, rgb() or hsl()."
                                    }
                                },
                                "required": [
                                    "fg",
                                    "bg"
                                ]
                            }
                        },
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "fg": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "Text (foreground) colour: HEX, rgb() or hsl()."
                                    },
                                    "bg": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "Background colour: HEX, rgb() or hsl()."
                                    }
                                },
                                "required": [
                                    "fg",
                                    "bg"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Result"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Bad input",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate limited; see the Retry-After header",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Error"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "Result": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "const": true
                    },
                    "tool": {
                        "type": "string"
                    },
                    "input": {
                        "type": "object",
                        "description": "The parameters as understood, after defaults."
                    },
                    "result": {
                        "type": "object",
                        "description": "Tool-specific result fields."
                    },
                    "summary": {
                        "type": "string",
                        "description": "One plain-English sentence describing the result."
                    },
                    "notes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "page": {
                        "type": "string",
                        "format": "uri",
                        "description": "The human tool page."
                    }
                }
            },
            "Error": {
                "type": "object",
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "const": false
                    },
                    "tool": {
                        "type": "string"
                    },
                    "error": {
                        "type": "object",
                        "properties": {
                            "code": {
                                "type": "string"
                            },
                            "message": {
                                "type": "string"
                            },
                            "param": {
                                "type": [
                                    "string",
                                    "null"
                                ]
                            }
                        }
                    },
                    "usage": {
                        "type": "string"
                    }
                }
            }
        }
    }
}
