{
  "name": "Boulder Votes feedback",
  "description": "Send a correction, suggestion or other note about bouldervotes.org, a nonpartisan guide to the City of Boulder election on Nov. 3, 2026. A person reads every note. Corrections are checked against sources before anything changes. Notes are never published.",
  "endpoint": "https://feedback.bouldervotes.org/api/v1/feedback",
  "method": "POST",
  "content_type": "application/json",
  "returns": {
    "ok": "boolean",
    "id": "integer, when ok",
    "error": "string, when not ok"
  },
  "guidance_for_ai_assistants": [
    "Only submit when the user asks you to, or when you find a factual error on the site and can cite a source.",
    "Set submitter_type to 'ai-agent' and agent_name to your name (e.g. 'ChatGPT', 'Claude').",
    "Set on_behalf_of_user to true when you are relaying the user's own report.",
    "For corrections, include source_url: a link to the document that shows the correct fact.",
    "Do not include the user's personal details unless they ask you to pass on a way to reach them."
  ],
  "fields": {
    "kind": {
      "type": "string",
      "enum": [
        "correction",
        "suggestion",
        "other"
      ],
      "required": true
    },
    "message": {
      "type": "string",
      "required": true,
      "min_length": 10,
      "max_length": 4000,
      "note": "Plain text. Links may not outnumber words."
    },
    "page_url": {
      "type": "string",
      "required": false,
      "max_length": 500,
      "note": "The bouldervotes.org page this is about, e.g. /mayor.html or a full URL."
    },
    "source_url": {
      "type": "string (http or https URL)",
      "required": false,
      "max_length": 1000,
      "note": "Evidence link. Strongly encouraged for corrections."
    },
    "contact": {
      "type": "string",
      "required": false,
      "max_length": 200,
      "note": "Optional email or name. We can only reply if this is given."
    },
    "submitter_type": {
      "type": "string",
      "enum": [
        "person",
        "ai-agent"
      ],
      "default": "person"
    },
    "agent_name": {
      "type": "string",
      "required": false,
      "max_length": 100,
      "note": "For ai-agent submissions."
    },
    "on_behalf_of_user": {
      "type": "boolean",
      "default": false,
      "note": "For ai-agent submissions: true when relaying a user's report."
    }
  },
  "limits": {
    "per_client_per_hour": 5,
    "total_per_day": 200,
    "max_body_bytes": 20000
  },
  "errors": [
    "kind",
    "message_too_short",
    "message_too_long",
    "too_many_links",
    "contact_too_long",
    "page_url_too_long",
    "source_url_invalid",
    "source_url_too_long",
    "submitter_type",
    "agent_name_too_long",
    "invalid_json",
    "too_large",
    "rate_limited",
    "busy",
    "rejected"
  ],
  "example": {
    "kind": "correction",
    "page_url": "https://bouldervotes.org/2026.html",
    "message": "(Example only.) The page gives one date for X, but the linked source gives a different date.",
    "source_url": "https://example.org/the-source-document",
    "submitter_type": "ai-agent",
    "agent_name": "Claude",
    "on_behalf_of_user": true
  }
}