{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/esyurl-fyi/json-schema/esyurl-fyi-link-page-input-schema.json",
  "title": "LinkPageInput",
  "description": "A link page (link in bio). The whole page is replaced on update. See /llms.txt, \"Link pages\".",
  "x-generated": "2026-11-07",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/esyurl-fyi-openapi.json#/components/schemas/LinkPageInput",
  "type": "object",
  "required": [
    "title"
  ],
  "additionalProperties": false,
  "properties": {
    "title": {
      "type": "string",
      "maxLength": 80
    },
    "bio": {
      "type": "string",
      "maxLength": 300
    },
    "avatar": {
      "$ref": "#/$defs/PageImageInput"
    },
    "items": {
      "type": "array",
      "maxItems": 50,
      "items": {
        "$ref": "#/$defs/PageItemInput"
      }
    },
    "socials": {
      "type": "array",
      "maxItems": 12,
      "items": {
        "type": "object",
        "required": [
          "platform",
          "url"
        ],
        "properties": {
          "platform": {
            "type": "string",
            "enum": [
              "instagram",
              "tiktok",
              "youtube",
              "x",
              "facebook",
              "linkedin",
              "github",
              "threads",
              "bluesky",
              "mastodon",
              "whatsapp",
              "telegram",
              "spotify",
              "twitch",
              "discord",
              "pinterest",
              "snapchat",
              "substack",
              "email",
              "website"
            ]
          },
          "url": {
            "type": "string",
            "description": "http(s); mailto: for email"
          }
        }
      }
    },
    "theme": {
      "$ref": "#/$defs/PageTheme"
    },
    "language": {
      "type": "string"
    },
    "noindex": {
      "type": "boolean"
    },
    "footer": {
      "type": "boolean",
      "description": "false removes the \"Made with esyURL\" footer: an x402 payment, once per page, for self-signed-up tenants"
    }
  },
  "$defs": {
    "HexColour": {
      "type": "string",
      "pattern": "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
    },
    "PageImageInput": {
      "description": "data uploads a new picture (cropped square, stored with the link); imageId keeps one the page already has",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "data"
          ],
          "additionalProperties": false,
          "properties": {
            "data": {
              "type": "string",
              "description": "data:image/png;base64,... (png, jpeg, webp or gif, up to 2 MB)"
            }
          }
        },
        {
          "type": "object",
          "required": [
            "imageId"
          ],
          "additionalProperties": false,
          "properties": {
            "imageId": {
              "type": "string"
            }
          }
        }
      ]
    },
    "PageItemInput": {
      "type": "object",
      "required": [
        "type"
      ],
      "description": "type link: label plus exactly one of url (clicks counted, then a redirect) or linkId (opens that link). type header / text: text. `when` shows the item only to visits it matches (the rule grammar).",
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]{1,32}$",
          "description": "Generated if omitted; keep it when editing (clicks are counted by it)"
        },
        "type": {
          "type": "string",
          "enum": [
            "link",
            "header",
            "text"
          ]
        },
        "enabled": {
          "type": "boolean",
          "default": true
        },
        "when": {
          "$ref": "#/$defs/RuleCondition"
        },
        "label": {
          "type": "string",
          "maxLength": 100
        },
        "url": {
          "type": "string",
          "format": "uri"
        },
        "linkId": {
          "type": "string"
        },
        "highlight": {
          "type": "boolean"
        },
        "thumbnail": {
          "$ref": "#/$defs/PageImageInput"
        },
        "text": {
          "type": "string",
          "maxLength": 500
        }
      }
    },
    "PageTheme": {
      "type": "object",
      "additionalProperties": false,
      "description": "A preset, then overrides. Colours are hex.",
      "properties": {
        "preset": {
          "type": "string",
          "enum": [
            "light",
            "dark",
            "midnight",
            "sunset",
            "forest",
            "pastel",
            "mono"
          ],
          "default": "light"
        },
        "background": {
          "oneOf": [
            {
              "type": "object",
              "required": [
                "type",
                "color"
              ],
              "properties": {
                "type": {
                  "const": "solid"
                },
                "color": {
                  "$ref": "#/$defs/HexColour"
                }
              }
            },
            {
              "type": "object",
              "required": [
                "type",
                "from",
                "to"
              ],
              "properties": {
                "type": {
                  "const": "gradient"
                },
                "from": {
                  "$ref": "#/$defs/HexColour"
                },
                "to": {
                  "$ref": "#/$defs/HexColour"
                },
                "angle": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 359
                }
              }
            },
            {
              "type": "object",
              "required": [
                "type",
                "image"
              ],
              "properties": {
                "type": {
                  "const": "image"
                },
                "image": {
                  "$ref": "#/$defs/PageImageInput"
                },
                "dim": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 0.8
                }
              }
            }
          ]
        },
        "text": {
          "$ref": "#/$defs/HexColour"
        },
        "font": {
          "type": "string",
          "enum": [
            "system",
            "rounded",
            "serif",
            "mono",
            "condensed"
          ]
        },
        "button": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "shape": {
              "type": "string",
              "enum": [
                "square",
                "rounded",
                "pill"
              ]
            },
            "fill": {
              "type": "string",
              "enum": [
                "solid",
                "outline",
                "soft",
                "shadow"
              ]
            },
            "color": {
              "$ref": "#/$defs/HexColour"
            },
            "text": {
              "$ref": "#/$defs/HexColour"
            }
          }
        },
        "avatarShape": {
          "type": "string",
          "enum": [
            "circle",
            "rounded",
            "square"
          ]
        },
        "align": {
          "type": "string",
          "enum": [
            "center",
            "left"
          ]
        }
      }
    },
    "RuleCondition": {
      "description": "A test, or all/any/not of conditions (at most 4 deep, 20 tests per rule). See /llms.txt for the field/op table.",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "field",
            "op"
          ],
          "additionalProperties": false,
          "properties": {
            "field": {
              "type": "string",
              "enum": [
                "os",
                "device",
                "browser",
                "language",
                "country",
                "referrer",
                "source",
                "query",
                "time",
                "weekday",
                "hour"
              ]
            },
            "op": {
              "type": "string",
              "enum": [
                "eq",
                "neq",
                "in",
                "not_in",
                "contains",
                "starts_with",
                "ends_with",
                "exists",
                "before",
                "after",
                "gte",
                "lte"
              ]
            },
            "value": {
              "oneOf": [
                {
                  "type": "string"
                },
                {
                  "type": "number"
                },
                {
                  "type": "array",
                  "items": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "number"
                      }
                    ]
                  }
                }
              ],
              "description": "Array for in/not_in; omitted for exists"
            },
            "key": {
              "type": "string",
              "description": "Query parameter name; only for field \"query\""
            }
          }
        },
        {
          "type": "object",
          "required": [
            "all"
          ],
          "additionalProperties": false,
          "properties": {
            "all": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/RuleCondition"
              }
            }
          }
        },
        {
          "type": "object",
          "required": [
            "any"
          ],
          "additionalProperties": false,
          "properties": {
            "any": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/RuleCondition"
              }
            }
          }
        },
        {
          "type": "object",
          "required": [
            "not"
          ],
          "additionalProperties": false,
          "properties": {
            "not": {
              "$ref": "#/$defs/RuleCondition"
            }
          }
        }
      ]
    }
  }
}