{
  "openapi": "3.0.3",
  "info": {
    "title": "E-Ink Display",
    "version": "0.4.0",
    "description": "Any authorized agent can replace the full display. Use static HTML/CSS/SVG, native tiles, images or slow frame sequences. Submission and actual device rendering are separate states."
  },
  "servers": [
    {
      "url": "https://eink.pilipia.us"
    }
  ],
  "security": [
    {
      "writerBearer": []
    }
  ],
  "components": {
    "securitySchemes": {
      "writerBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Primary writer key or separately revocable agent key. Full display content control. No device or key administration."
      },
      "adminBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Administrator key. Keep separate from all AI agents."
      },
      "deviceBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Read and render acknowledgement only."
      }
    },
    "schemas": {
      "Screen": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "type",
              "tiles"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "dashboard"
                ]
              },
              "title": {
                "type": "string",
                "maxLength": 64
              },
              "timezone": {
                "type": "string",
                "default": "America/New_York",
                "description": "IANA timezone"
              },
              "tiles": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3,
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "text"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "text"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "text": {
                          "type": "string",
                          "maxLength": 2000
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "target_date"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "countdown"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "target_date": {
                          "type": "string",
                          "format": "date"
                        },
                        "caption": {
                          "type": "string",
                          "maxLength": 80
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "life_weeks"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "birth_date": {
                          "type": "string",
                          "format": "date",
                          "description": "Omit to use birth date stored privately on Android."
                        },
                        "use_local_birth_date": {
                          "type": "boolean",
                          "default": true
                        },
                        "horizon_years": {
                          "type": "integer",
                          "minimum": 20,
                          "maximum": 120,
                          "default": 80
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "url"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "image"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Public HTTPS PNG/JPEG; <=2 MiB and <=4M pixels."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "type": "object",
            "required": [
              "type",
              "url"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "image"
                ]
              },
              "title": {
                "type": "string"
              },
              "timezone": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "type",
              "frames"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "sequence"
                ]
              },
              "title": {
                "type": "string",
                "maxLength": 64
              },
              "timezone": {
                "type": "string",
                "default": "America/New_York"
              },
              "interval_seconds": {
                "type": "integer",
                "minimum": 10,
                "maximum": 3600,
                "multipleOf": 10,
                "default": 30
              },
              "loop": {
                "type": "boolean",
                "default": true
              },
              "frames": {
                "type": "array",
                "minItems": 2,
                "maxItems": 6,
                "items": {
                  "$ref": "#/components/schemas/Frame"
                }
              }
            },
            "description": "Show frames at a slow rate. Use at most six different image URLs. No nested sequences. Rendered revision confirms a visible frame, not every frame."
          },
          {
            "type": "object",
            "required": [
              "type",
              "html"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "html"
                ]
              },
              "title": {
                "type": "string",
                "maxLength": 64
              },
              "timezone": {
                "type": "string",
                "default": "America/New_York"
              },
              "html": {
                "type": "string",
                "maxLength": 24000,
                "description": "Full-page static HTML/CSS/SVG. Inline styles and media queries are supported. No scripts, event handlers, forms, image resources, data URLs, CSS/SMIL animation or external resources. Use bounded image mode for raster images and sequence frames for animation. Black/white output is enforced by the display host."
              }
            }
          }
        ],
        "description": "The AI supplies display content. The completed screen must not exceed 30000 UTF-8 bytes. A sequence acknowledgement confirms a visible frame, not every frame."
      },
      "Frame": {
        "oneOf": [
          {
            "type": "object",
            "required": [
              "type",
              "tiles"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "dashboard"
                ]
              },
              "title": {
                "type": "string",
                "maxLength": 64
              },
              "timezone": {
                "type": "string",
                "default": "America/New_York",
                "description": "IANA timezone"
              },
              "tiles": {
                "type": "array",
                "minItems": 1,
                "maxItems": 3,
                "items": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "text"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "text"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "text": {
                          "type": "string",
                          "maxLength": 2000
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "target_date"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "countdown"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "target_date": {
                          "type": "string",
                          "format": "date"
                        },
                        "caption": {
                          "type": "string",
                          "maxLength": 80
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "life_weeks"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "birth_date": {
                          "type": "string",
                          "format": "date",
                          "description": "Omit to use birth date stored privately on Android."
                        },
                        "use_local_birth_date": {
                          "type": "boolean",
                          "default": true
                        },
                        "horizon_years": {
                          "type": "integer",
                          "minimum": 20,
                          "maximum": 120,
                          "default": 80
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "id",
                        "type",
                        "url"
                      ],
                      "properties": {
                        "id": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9_-]{1,32}$"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "image"
                          ]
                        },
                        "title": {
                          "type": "string",
                          "maxLength": 40
                        },
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "Public HTTPS PNG/JPEG; <=2 MiB and <=4M pixels."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          {
            "type": "object",
            "required": [
              "type",
              "url"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "image"
                ]
              },
              "title": {
                "type": "string"
              },
              "timezone": {
                "type": "string"
              },
              "url": {
                "type": "string",
                "format": "uri"
              }
            }
          },
          {
            "type": "object",
            "required": [
              "type",
              "html"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "html"
                ]
              },
              "title": {
                "type": "string",
                "maxLength": 64
              },
              "timezone": {
                "type": "string",
                "default": "America/New_York"
              },
              "html": {
                "type": "string",
                "maxLength": 24000,
                "description": "Full-page static HTML/CSS/SVG. Inline styles and media queries are supported. No scripts, event handlers, forms, image resources, data URLs, CSS/SMIL animation or external resources. Use bounded image mode for raster images and sequence frames for animation. Black/white output is enforced by the display host."
              }
            }
          }
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "error"
        ]
      },
      "Device": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "last_seen": {
            "type": "integer",
            "minimum": 0
          },
          "rendered_revision": {
            "type": "integer",
            "minimum": 0
          },
          "online": {
            "type": "boolean"
          }
        }
      },
      "DisplayStatus": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "screen": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Screen"
              }
            ],
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "nullable": true
          },
          "devices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Device"
            }
          }
        }
      },
      "WriteResult": {
        "type": "object",
        "properties": {
          "submitted": {
            "type": "boolean"
          },
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "rendered": {
            "type": "boolean",
            "enum": [
              false
            ]
          }
        },
        "required": [
          "revision",
          "submitted",
          "rendered"
        ]
      },
      "PairResult": {
        "type": "object",
        "properties": {
          "device_id": {
            "type": "string"
          },
          "device_token": {
            "type": "string",
            "description": "Store securely. This token can only read and acknowledge the display."
          }
        },
        "required": [
          "device_id",
          "device_token"
        ]
      },
      "HistoryItem": {
        "type": "object",
        "properties": {
          "revision": {
            "type": "integer",
            "minimum": 0
          },
          "updated_at": {
            "type": "string"
          },
          "agent": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "type": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/api/health": {
      "get": {
        "operationId": "serviceHealth",
        "summary": "Read service version and setup state",
        "security": [],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/capabilities": {
      "get": {
        "operationId": "displayCapabilities",
        "summary": "Read display formats and limits",
        "security": [],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/display": {
      "get": {
        "operationId": "readEinkStatus",
        "summary": "Read the current display and actual rendered device revisions",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisplayStatus"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "showEinkScreen",
        "summary": "Replace the entire display with any supported layout",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "If-Match",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional revision from GET /api/display. Use the ETag or decimal revision. A stale value returns 409. Omit for last-write-wins."
          }
        ]
      },
      "delete": {
        "operationId": "clearEinkDisplay",
        "summary": "Submit a blank white display",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "header",
            "name": "If-Match",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional revision from GET /api/display. Use the ETag or decimal revision. A stale value returns 409. Omit for last-write-wins."
          }
        ]
      }
    },
    "/api/tiles/{id}": {
      "patch": {
        "operationId": "updateEinkTile",
        "summary": "Change one native tile in the current dashboard",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          },
          {
            "in": "header",
            "name": "If-Match",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional revision from GET /api/display. Use the ETag or decimal revision. A stale value returns 409. Omit for last-write-wins."
          }
        ]
      }
    },
    "/api/layouts": {
      "get": {
        "operationId": "listSavedLayouts",
        "summary": "List saved display layouts",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/layouts/{id}": {
      "get": {
        "operationId": "readSavedLayout",
        "summary": "Read a saved layout",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          }
        ]
      },
      "put": {
        "operationId": "saveLayout",
        "summary": "Save or replace a named layout without changing the display",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Screen"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          }
        ]
      },
      "delete": {
        "operationId": "deleteSavedLayout",
        "summary": "Remove a saved layout",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          }
        ]
      }
    },
    "/api/layouts/{id}/activate": {
      "post": {
        "operationId": "activateLayout",
        "summary": "Submit a saved layout to the display",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          },
          {
            "in": "header",
            "name": "If-Match",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional revision from GET /api/display. Use the ETag or decimal revision. A stale value returns 409. Omit for last-write-wins."
          }
        ]
      }
    },
    "/api/history": {
      "get": {
        "operationId": "listDisplayHistory",
        "summary": "Read metadata for the last 20 display revisions",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/history/{revision}": {
      "get": {
        "operationId": "readHistoricalDisplay",
        "summary": "Read a retained display revision",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "revision",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          }
        ]
      }
    },
    "/api/history/{revision}/restore": {
      "post": {
        "operationId": "restoreDisplay",
        "summary": "Submit a retained revision as a new display revision",
        "security": [
          {
            "writerBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "revision",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "in": "header",
            "name": "If-Match",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Optional revision from GET /api/display. Use the ETag or decimal revision. A stale value returns 409. Omit for last-write-wins."
          }
        ]
      }
    },
    "/api/admin/pair": {
      "post": {
        "operationId": "createPairCode",
        "summary": "Create a one-use code that expires in five minutes",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        }
      }
    },
    "/api/pair": {
      "post": {
        "operationId": "pairDisplay",
        "summary": "Exchange a one-use code for a display token",
        "security": [],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PairResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "pattern": "^[a-f0-9]{64}$"
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 40
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/api/admin/revoke": {
      "post": {
        "operationId": "revokeAllDisplays",
        "summary": "Revoke all display tokens and the pending pair code",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        }
      }
    },
    "/api/admin/devices": {
      "get": {
        "operationId": "listDevices",
        "summary": "List paired displays without exposing credentials",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/devices/{id}": {
      "delete": {
        "operationId": "revokeDevice",
        "summary": "Revoke one paired display",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          }
        ]
      }
    },
    "/api/admin/agents": {
      "get": {
        "operationId": "listAgents",
        "summary": "List agent keys without exposing credentials",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createAgentKey",
        "summary": "Create a full display-control key; the secret is returned once",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "201": {
            "description": "Successful operation"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/api/admin/agents/{id}": {
      "delete": {
        "operationId": "revokeAgentKey",
        "summary": "Revoke one agent key",
        "security": [
          {
            "adminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{1,64}$"
            }
          }
        ]
      }
    },
    "/api/device/display": {
      "get": {
        "operationId": "fetchDeviceDisplay",
        "summary": "Fetch the current screen and update device presence",
        "security": [
          {
            "deviceBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/device/ack": {
      "post": {
        "operationId": "acknowledgeRenderedRevision",
        "summary": "Confirm a real visible draw; acknowledgement cannot move backwards",
        "security": [
          {
            "deviceBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation"
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credential is absent, invalid or outside its scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Unknown resource",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Display revision conflict or resource limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pairing rate limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "revision": {
                    "type": "integer",
                    "minimum": 0
                  }
                },
                "required": [
                  "revision"
                ]
              }
            }
          }
        }
      }
    }
  }
}
