{
  "openapi": "3.0.3",
  "info": {
    "title": "WardByWard Platform API",
    "description": "Public JSON API for the WardByWard ward-by-ward civic platform: ward lookup by GPS or text search, ward funding aggregates, campaign discovery, nomination standing and signing, and service health. Write endpoints authenticate with a session issued by POST /login (see /auth.md).",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://wardbyward.co.za"
    }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Service health",
        "operationId": "getHealth",
        "responses": {
          "200": {
            "description": "Healthy",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "uptime": {
                      "type": "number"
                    },
                    "db": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "description": "Database not ready"
          }
        }
      }
    },
    "/api/wards/search": {
      "get": {
        "summary": "Search wards by name, area or voting station",
        "operationId": "searchWards",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search text",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching wards",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "wards": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "q required"
          }
        }
      }
    },
    "/api/wards/lookup": {
      "get": {
        "summary": "Resolve a ward from GPS coordinates",
        "operationId": "lookupWard",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ward found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "ward": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "lat and lng required"
          },
          "404": {
            "description": "ward not found"
          }
        }
      }
    },
    "/api/wards/funding": {
      "get": {
        "summary": "Funding aggregates and targets for a ward",
        "operationId": "wardFunding",
        "parameters": [
          {
            "name": "ward",
            "in": "query",
            "required": true,
            "description": "WardId",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Funding breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "ward": {
                      "type": "object"
                    },
                    "funding": {
                      "type": "object"
                    },
                    "targets": {
                      "type": "object"
                    },
                    "score": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "ward required"
          },
          "404": {
            "description": "ward not found"
          }
        }
      }
    },
    "/api/wards/set-ward": {
      "post": {
        "summary": "Set the merchant's home ward (session required)",
        "operationId": "setWard",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "ward_id": {
                    "type": "string"
                  }
                },
                "required": [
                  "token",
                  "phone",
                  "ward_id"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ward set"
          },
          "400": {
            "description": "ward_id required"
          },
          "401": {
            "description": "invalid session"
          },
          "404": {
            "description": "merchant or ward not found"
          }
        }
      }
    },
    "/api/campaigns/featured": {
      "get": {
        "summary": "Featured campaigns",
        "operationId": "featuredCampaigns",
        "responses": {
          "200": {
            "description": "Featured campaigns",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/campaigns/by-ward": {
      "get": {
        "summary": "Active campaigns for a ward",
        "operationId": "campaignsByWard",
        "parameters": [
          {
            "name": "ward",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Campaigns",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/nominations/list": {
      "get": {
        "summary": "List nominations",
        "operationId": "listNominations",
        "responses": {
          "200": {
            "description": "Nominations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/nominations/sign": {
      "post": {
        "summary": "Sign a nomination",
        "operationId": "signNomination",
        "responses": {
          "200": {
            "description": "Signed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/signatures/endorse": {
      "post": {
        "summary": "Endorse a nomination with an SA ID",
        "operationId": "endorseSignature",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ward_id": {
                    "type": "string"
                  },
                  "signer_id_number": {
                    "type": "string"
                  }
                },
                "required": [
                  "ward_id",
                  "signer_id_number"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Endorsed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/marketplace/requests": {
      "get": {
        "summary": "List marketplace requests",
        "operationId": "listMarketplaceRequests",
        "responses": {
          "200": {
            "description": "Requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  }
}