{
  "openapi": "3.1.0",
  "info": {
    "title": "Provenance Africa API",
    "description": "Structured, queryable JSON for African and diaspora history: verified historical events and researched articles from Provenance Africa, an independent archive. Intended for AI agents, search tools, and researchers to query directly rather than scrape rendered HTML.",
    "version": "1.0.0",
    "contact": {
      "url": "https://provenanceafrica.com/about/"
    },
    "license": {
      "name": "CC BY 4.0",
      "identifier": "CC-BY-4.0"
    },
    "termsOfService": "https://provenanceafrica.com/terms/#licence"
  },
  "servers": [
    {
      "url": "https://provenanceafrica.com/api/v1"
    }
  ],
  "paths": {
    "/today": {
      "get": {
        "summary": "Verified historical events for today's date",
        "description": "Reflects the calendar date at last deploy time, not the visitor's live clock — use /on-this-day/{MM-DD} for a date that's always correct.",
        "operationId": "getToday",
        "responses": {
          "200": {
            "description": "Events for today",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnThisDayResponse"
                }
              }
            }
          }
        }
      }
    },
    "/on-this-day/{date}": {
      "get": {
        "summary": "Verified historical events for a specific calendar date",
        "operationId": "getOnThisDay",
        "parameters": [
          {
            "name": "date",
            "in": "path",
            "required": true,
            "description": "Calendar date as MM-DD",
            "schema": {
              "type": "string",
              "pattern": "^\\d{2}-\\d{2}$",
              "example": "03-06"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Events for the given date",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnThisDayResponse"
                }
              }
            }
          }
        }
      }
    },
    "/facts": {
      "get": {
        "summary": "Filtered, paginated archive of researched articles",
        "operationId": "getFacts",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "algeria",
                "angola",
                "benin",
                "botswana",
                "burkina-faso",
                "burundi",
                "cabo-verde",
                "cameroon",
                "central-african-republic",
                "chad",
                "comoros",
                "congo-brazzaville",
                "dr-congo",
                "djibouti",
                "egypt",
                "equatorial-guinea",
                "eritrea",
                "eswatini",
                "ethiopia",
                "gabon",
                "gambia",
                "ghana",
                "guinea",
                "guinea-bissau",
                "ivory-coast",
                "kenya",
                "lesotho",
                "liberia",
                "libya",
                "madagascar",
                "malawi",
                "mali",
                "mauritania",
                "mauritius",
                "morocco",
                "mozambique",
                "namibia",
                "niger",
                "nigeria",
                "rwanda",
                "sao-tome-and-principe",
                "senegal",
                "seychelles",
                "sierra-leone",
                "somalia",
                "south-africa",
                "south-sudan",
                "sudan",
                "tanzania",
                "togo",
                "tunisia",
                "uganda",
                "zambia",
                "zimbabwe"
              ]
            }
          },
          {
            "name": "era",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ancient-and-precolonial",
                "slave-trade-and-early-contact",
                "colonial-era",
                "independence-era",
                "post-independence-cold-war",
                "contemporary-africa"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated article list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FactsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Unknown country or era slug"
          },
          "429": {
            "description": "Rate limit exceeded — 30 requests/minute per IP"
          }
        }
      }
    },
    "/search": {
      "get": {
        "summary": "Full-text search across researched articles",
        "operationId": "getSearch",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Search query, minimum 2 characters",
            "schema": {
              "type": "string",
              "minLength": 2
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResponse"
                }
              }
            }
          },
          "400": {
            "description": "Query too short"
          },
          "429": {
            "description": "Rate limit exceeded — 20 requests/minute per IP"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "OnThisDayEvent": {
        "type": "object",
        "properties": {
          "year": {
            "type": "integer"
          },
          "text": {
            "type": "string"
          },
          "tag": {
            "type": [
              "string",
              "null"
            ]
          },
          "imageUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "imageCredit": {
            "type": [
              "string",
              "null"
            ]
          },
          "videoId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "OnThisDayResponse": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "sourceUrl": {
            "type": "string"
          },
          "count": {
            "type": "integer"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OnThisDayEvent"
            }
          }
        }
      },
      "Fact": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "metaDescription": {
            "type": [
              "string",
              "null"
            ]
          },
          "articlePublishedDate": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "image": {
            "type": [
              "string",
              "null"
            ]
          },
          "imageCredit": {
            "type": [
              "string",
              "null"
            ]
          },
          "videoId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "FactsResponse": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "total": {
            "type": "integer"
          },
          "totalPages": {
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "facts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Fact"
            }
          }
        }
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "article"
            ]
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "snippet": {
            "type": "string"
          },
          "date": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "SearchResponse": {
        "type": "object",
        "properties": {
          "source": {
            "type": "string"
          },
          "total": {
            "type": "integer"
          },
          "totalPages": {
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SearchResult"
            }
          }
        }
      }
    }
  }
}