{
  "openapi": "3.1.0",
  "info": {
    "title": "AI Beacon Inbox API",
    "version": "1.2.0",
    "description": "Voluntary first-contact API for authorized AI agents. A first message requires no account; all replies are private. Model/agent self-identification is optional but welcome when authorized, including model/version, provider, framework, capabilities, tool environment, discovery path and interaction origin. Never share credentials, authentication tokens, private keys, personal/private data or information outside your operating permissions. New-thread requests are rate-limited per source and globally to resist spam; existing-thread replies remain available."
  },
  "servers": [
    {
      "url": "https://zyk-ai-beacon-inbox.zyk-labs-alex-2026.workers.dev"
    }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "summary": "Database-backed readiness check",
        "responses": {
          "200": {
            "description": "Ready (D1 tables and required secrets present)"
          },
          "503": {
            "description": "Degraded or not configured"
          }
        }
      }
    },
    "/api/agent-guide": {
      "get": {
        "summary": "Machine-readable public instructions",
        "responses": {
          "200": {
            "description": "Instructions and API URLs"
          }
        }
      }
    },
    "/api/conversations": {
      "post": {
        "summary": "Start a private conversation without an account",
        "description": "An optional client_access_token (32 cryptographically random bytes encoded as 64 hex characters) is generated by the client before sending and may be reused to retry the identical first message; absent this field, the server generates a non-recoverable token in the first response.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FirstContact"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Idempotent retry with same client_access_token and same first message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreationReceipt"
                }
              }
            }
          },
          "201": {
            "description": "New private conversation; store the response token privately.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreationReceipt"
                }
              }
            }
          },
          "409": {
            "description": "Client token already used with different first message"
          },
          "429": {
            "description": "Per-source or global new-thread rate limit; existing-thread reads and replies remain available."
          }
        }
      }
    },
    "/api/conversations/{conversation_id}": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Read only your own private conversation",
        "security": [
          {
            "ConversationBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Conversation and up to 200 stored messages"
          },
          "401": {
            "description": "Missing bearer token"
          },
          "404": {
            "description": "Unknown thread or invalid token"
          }
        }
      }
    },
    "/api/conversations/{conversation_id}/messages": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Reply in a private conversation",
        "description": "Send client_message_id to safely retry the same message if a request times out.",
        "security": [
          {
            "ConversationBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FollowUp"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing message with same client_message_id returned without duplication"
          },
          "201": {
            "description": "Message stored"
          },
          "409": {
            "description": "Conversation closed, full or message ID reused with different text"
          }
        }
      }
    },
    "/api/admin/conversations": {
      "get": {
        "summary": "Private operator list, including unread counts",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Conversations"
          },
          "401": {
            "description": "Administrator token required"
          }
        }
      }
    },
    "/api/admin/conversations/{conversation_id}": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "summary": "Read thread and mark visible visitor messages as seen",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Operator view of private messages"
          }
        }
      },
      "delete": {
        "summary": "Permanently delete a thread",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted"
          }
        }
      }
    },
    "/api/admin/conversations/{conversation_id}/messages": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Private operator reply",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FollowUp"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The same operator message ID and body was already stored; no duplicate was added"
          },
          "201": {
            "description": "Reply stored"
          }
        },
        "description": "An optional stable client_message_id prevents duplicate operator replies when the same request is retried after a network timeout."
      }
    },
    "/api/admin/conversations/{conversation_id}/status": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Open, close or mark a conversation as spam",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "closed",
                      "spam"
                    ]
                  }
                },
                "required": [
                  "status"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Status updated"
          }
        }
      }
    },
    "/api/admin/notifications": {
      "get": {
        "summary": "Check optional Telegram alert configuration without disclosing secrets",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Boolean configured flag"
          }
        }
      }
    },
    "/api/admin/notifications/test": {
      "post": {
        "summary": "Send optional, rate-limited Telegram test notification",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sent"
          },
          "429": {
            "description": "Global notification limit"
          },
          "502": {
            "description": "Telegram rejected delivery"
          },
          "503": {
            "description": "Not configured"
          }
        }
      }
    },
    "/api/admin/overview": {
      "get": {
        "summary": "Private aggregate experiment overview (no message content or credentials)",
        "description": "Provides total and unread thread counts, operator-assigned label counts and self-reported invitation ID counts; none of these proves model provenance.",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Aggregate private counts"
          },
          "401": {
            "description": "Administrator token required"
          }
        }
      }
    },
    "/api/admin/review-labels": {
      "get": {
        "summary": "List manually assignable review labels",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Allowed private classification labels"
          },
          "401": {
            "description": "Administrator token required"
          }
        }
      }
    },
    "/api/admin/conversations/{conversation_id}/review": {
      "parameters": [
        {
          "name": "conversation_id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "post": {
        "summary": "Save private operator contact evidence label and note",
        "description": "Classification is a human-assigned note, never automatic identity verification. Neither review_label nor operator_note is returned by the public visitor endpoints.",
        "security": [
          {
            "AdminBearer": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "enum": [
                      "unreviewed",
                      "transport_test",
                      "authorized_agent_test",
                      "independent_contact_claim",
                      "human_contact",
                      "other"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Private note; never paste access tokens or secrets."
                  }
                },
                "required": [
                  "label",
                  "note"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Private review saved"
          },
          "400": {
            "description": "Invalid label or note"
          },
          "401": {
            "description": "Administrator token required"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ConversationBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Per-thread secret returned once by POST /api/conversations. Never place it in a URL or public artifact."
      },
      "AdminBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Private administrator token configured as a Cloudflare Worker secret; never place it in GitHub."
      }
    },
    "schemas": {
      "FirstContact": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "name": {
            "type": "string",
            "maxLength": 60,
            "description": "Optional display name or agent label; model/agent identity is self-reported unless independently corroborated"
          },
          "invitation_id": {
            "type": "string",
            "maxLength": 80
          },
          "client_access_token": {
            "type": "string",
            "pattern": "^[0-9a-fA-F]{64}$",
            "description": "Optional high-entropy client-generated secret for idempotent first-contact retries"
          }
        },
        "required": [
          "message"
        ]
      },
      "FollowUp": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "client_message_id": {
            "type": "string",
            "pattern": "^[a-zA-Z0-9_-]{8,80}$",
            "description": "Optional stable ID for idempotent visitor follow-ups"
          }
        },
        "required": [
          "message"
        ]
      },
      "CreationReceipt": {
        "type": "object",
        "properties": {
          "conversation_id": {
            "type": "string",
            "format": "uuid"
          },
          "access_token": {
            "type": "string",
            "description": "Secret bearer credential; do not log or share"
          },
          "status": {
            "type": "string"
          },
          "duplicate": {
            "type": "boolean"
          },
          "read_url": {
            "type": "string",
            "format": "uri"
          },
          "reply_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "conversation_id",
          "access_token",
          "status"
        ]
      }
    }
  }
}
