{"openapi":"3.1.0","info":{"title":"Africa Data Bank API","description":"\n    Pan-African statistical data platform covering all 55 African nations with machine-readable data and row-level provenance.\n\n    ## Features\n    - **54 Countries**: All African nations with metadata, regions, and income classification\n    - **Live Indicator Catalog**: Registry-driven coverage that expands as sources are added\n    - **6 Trade Blocs**: EAC, COMESA, IGAD, ECOWAS, SADC, AU with aggregate analytics\n    - **FRED-style Transforms**: % change, YoY, per capita, per GDP, moving averages, indexed\n    - **Rich Metadata**: OWID-style descriptions, methodology, limitations, African context\n    - **Observations**: Time-series data from 2000 to the latest published year (typically current year minus 1-2 for most indicators)\n    - **Exports**: CSV, JSON, XLSX formats\n    - **Embeddable Charts**: Iframe widgets for websites\n    - **Data Provenance**: Full lineage for every data point\n    - **Watchlist & Alerts**: Track indicators and get notified\n\n    ## Data Sources\n    - World Bank Open Data\n    - IMF Statistics & Government Finance Statistics\n    - WHO Global Health Observatory\n    - African Development Bank\n    - UNData / UNSD\n    - EAC Central Banks (official forex rates)\n    - FRED/FAO/WFP (commodity & food prices)\n    - DHS Program (sub-national health surveys)\n    ","version":"1.0.0"},"paths":{"/api/v1/admin/users":{"get":{"tags":["Admin","Admin"],"summary":"Admin List Users","description":"List all users.","operationId":"admin_list_users_api_v1_admin_users_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/users/{email}/disable":{"post":{"tags":["Admin","Admin"],"summary":"Admin Disable User","description":"Disable a user account. Blocks login and invalidates tokens.","operationId":"admin_disable_user_api_v1_admin_users__email__disable_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/enable":{"post":{"tags":["Admin","Admin"],"summary":"Admin Enable User","description":"Re-enable a previously disabled user.","operationId":"admin_enable_user_api_v1_admin_users__email__enable_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}":{"patch":{"tags":["Admin","Admin"],"summary":"Admin Update User","description":"Update a user's tier, role, name or company.","operationId":"admin_update_user_api_v1_admin_users__email__patch","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUpdateUserRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/api-keys/{key_id}":{"delete":{"tags":["Admin","Admin"],"summary":"Admin Revoke Single Api Key","description":"Revoke a single API key on behalf of a user.","operationId":"admin_revoke_single_api_key_api_v1_admin_users__email__api_keys__key_id__delete","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}},{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/reset-api-key":{"post":{"tags":["Admin","Admin"],"summary":"Admin Reset Api Key","description":"Revoke all of a user's API keys and issue a fresh one.","operationId":"admin_reset_api_key_api_v1_admin_users__email__reset_api_key_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/send-password-reset":{"post":{"tags":["Admin","Admin"],"summary":"Admin Send Password Reset","description":"Email a single-use password-reset link on behalf of support staff.","operationId":"admin_send_password_reset_api_v1_admin_users__email__send_password_reset_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/grant-tier":{"post":{"tags":["Admin","Admin"],"summary":"Admin Grant Tier","description":"Grant the user the named tier. Payment-agnostic.","operationId":"admin_grant_tier_api_v1_admin_users__email__grant_tier_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminGrantTierRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/users/{email}/email":{"post":{"tags":["Admin","Admin"],"summary":"Admin Send Email","description":"Send an ad-hoc email to a user. Reply-To defaults to support@.","operationId":"admin_send_email_api_v1_admin_users__email__email_post","parameters":[{"name":"email","in":"path","required":true,"schema":{"type":"string","title":"Email"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSendEmailRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/orgs":{"get":{"tags":["Admin","Admin"],"summary":"Admin List Orgs","description":"List all organizations (team + enterprise plans).","operationId":"admin_list_orgs_api_v1_admin_orgs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Admin","Admin"],"summary":"Admin Create Org","description":"Provision a new org.","operationId":"admin_create_org_api_v1_admin_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateOrgRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/orgs/{org_id}":{"get":{"tags":["Admin","Admin"],"summary":"Admin Get Org","description":"Get an org by ID.","operationId":"admin_get_org_api_v1_admin_orgs__org_id__get","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Admin","Admin"],"summary":"Admin Update Org","description":"Edit an org's name / tier / seats / billing status.","operationId":"admin_update_org_api_v1_admin_orgs__org_id__patch","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUpdateOrgRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Admin","Admin"],"summary":"Admin Delete Org","description":"Hard-delete an org. All members detached.","operationId":"admin_delete_org_api_v1_admin_orgs__org_id__delete","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/orgs/{org_id}/members":{"post":{"tags":["Admin","Admin"],"summary":"Admin Add Org Member","description":"Add a registered user to an org.","operationId":"admin_add_org_member_api_v1_admin_orgs__org_id__members_post","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAddMemberRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/orgs/{org_id}/members/{member_email}":{"delete":{"tags":["Admin","Admin"],"summary":"Admin Remove Org Member","description":"Remove a member from an org.","operationId":"admin_remove_org_member_api_v1_admin_orgs__org_id__members__member_email__delete","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}},{"name":"member_email","in":"path","required":true,"schema":{"type":"string","title":"Member Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/orgs/{org_id}/transfer":{"post":{"tags":["Admin","Admin"],"summary":"Admin Transfer Org Owner","description":"Hand the billing-contact role to another existing member.","operationId":"admin_transfer_org_owner_api_v1_admin_orgs__org_id__transfer_post","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminTransferOwnershipRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/settings":{"get":{"tags":["Admin","Admin"],"summary":"Admin Get Settings","description":"Read platform settings + email provider config (secrets masked).","operationId":"admin_get_settings_api_v1_admin_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"put":{"tags":["Admin","Admin"],"summary":"Admin Save Settings","description":"Persist editable platform settings to disk (allowlisted keys only).","operationId":"admin_save_settings_api_v1_admin_settings_put","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/email/test":{"post":{"tags":["Admin","Admin"],"summary":"Admin Email Test","description":"Send a test email through Resend.","operationId":"admin_email_test_api_v1_admin_email_test_post","parameters":[{"name":"to","in":"query","required":true,"schema":{"type":"string","description":"Recipient address","title":"To"},"description":"Recipient address"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/email/recent":{"get":{"tags":["Admin","Admin"],"summary":"Admin Email Recent","description":"Newest-first log of recent transactional email attempts.\n\nIn-memory ring buffer; restart-clears. Powers the admin diagnostic\npanel so a failing signup / reset send surfaces immediately with\nits Resend error detail instead of requiring container-log access.","operationId":"admin_email_recent_api_v1_admin_email_recent_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/news/refresh":{"post":{"tags":["Admin","Admin"],"summary":"Admin News Refresh","description":"Force a news RSS refresh now.","operationId":"admin_news_refresh_api_v1_admin_news_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/news/status":{"get":{"tags":["Admin","Admin"],"summary":"Admin News Status","description":"Per-feed RSS diagnostics.","operationId":"admin_news_status_api_v1_admin_news_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/analytics/usage":{"get":{"tags":["Admin","Admin"],"summary":"Admin Usage","description":"Real traffic snapshot for the admin analytics page.","operationId":"admin_usage_api_v1_admin_analytics_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":14,"title":"Days"}},{"name":"top","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Top"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/data-source-metrics":{"get":{"tags":["Admin","Admin"],"summary":"Admin Data Source Metrics","description":"Counters for how observation endpoints are resolving.\n\nEvery request is tagged by which layer served it: `local` (ingested\nstore), `cache` (in-process TTL), `live` (upstream network fetch),\nor `empty` (no data anywhere). A healthy platform serves ~100%\nfrom local; every `live` hit is a coverage-gap signal worth\ntriaging (ingestion pipeline hasn't covered that country /\nindicator / year combo yet).\n\nAlso returns a ring buffer of the last ~200 live-fallback events\nwith country + endpoint + latency so ops can see exactly which\nrequests are cold-hitting the wire in real time.","operationId":"admin_data_source_metrics_api_v1_admin_data_source_metrics_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/data-source-metrics/reset":{"post":{"tags":["Admin","Admin"],"summary":"Admin Data Source Metrics Reset","description":"Zero the fallback counters. Useful after finishing an ingestion\nsweep — the next window of readings shows only NEW fallbacks.","operationId":"admin_data_source_metrics_reset_api_v1_admin_data_source_metrics_reset_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/catalog/harvest":{"post":{"tags":["Admin"],"summary":"Run Harvest","operationId":"run_harvest_api_v1_admin_catalog_harvest_post","parameters":[{"name":"provider","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(re3data|openafrica)$"},{"type":"null"}],"title":"Provider"}},{"name":"max_records","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10000,"minimum":1},{"type":"null"}],"title":"Max Records"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/catalog/profiles":{"get":{"tags":["Admin"],"summary":"Catalog Profiles","operationId":"catalog_profiles_api_v1_admin_catalog_profiles_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(pending|running|profiled|approved|rejected|failed)$"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/catalog/datasets/{dataset_remote_id}/profile/{distribution_remote_id}":{"post":{"tags":["Admin"],"summary":"Queue Distribution Profile","operationId":"queue_distribution_profile_api_v1_admin_catalog_datasets__dataset_remote_id__profile__distribution_remote_id__post","parameters":[{"name":"dataset_remote_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Remote Id"}},{"name":"distribution_remote_id","in":"path","required":true,"schema":{"type":"string","title":"Distribution Remote Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/catalog/profiles/{profile_id}/decision":{"post":{"tags":["Admin"],"summary":"Decide Catalog Profile","operationId":"decide_catalog_profile_api_v1_admin_catalog_profiles__profile_id__decision_post","parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}},{"name":"decision","in":"query","required":true,"schema":{"type":"string","pattern":"^(approved|rejected)$","title":"Decision"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Note"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ingestion/trigger":{"post":{"tags":["Admin","Admin"],"summary":"Trigger Ingestion","description":"Trigger an ingestion run for the given source.","operationId":"trigger_ingestion_api_v1_admin_ingestion_trigger_post","parameters":[{"name":"source","in":"query","required":false,"schema":{"type":"string","default":"worldbank","title":"Source"}},{"name":"countries","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Countries"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ingestion/jobs":{"get":{"tags":["Admin","Admin"],"summary":"List Ingestion Jobs","description":"Return recent ingestion jobs (in-memory).","operationId":"list_ingestion_jobs_api_v1_admin_ingestion_jobs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/ingestion/status":{"get":{"tags":["Admin","Admin"],"summary":"Ingestion Status","description":"Ingestion status for monitoring — proxies observations-api.","operationId":"ingestion_status_api_v1_admin_ingestion_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/contact/requests":{"get":{"tags":["Admin","Admin"],"summary":"List Contact Leads","description":"List inbound contact leads (newest first).\n\n``kind`` accepts either an exact value (``enterprise``,\n``community_signup``, ``data_request``) or a prefix ending in\n``:`` (``contact:`` matches every topic of the general contact\nform).","operationId":"list_contact_leads_api_v1_admin_contact_requests_get","parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/contact/requests/counts":{"get":{"tags":["Admin","Admin"],"summary":"Counts By Kind","description":"Return a {bucket: count} map for the inbox sidebar badges.","operationId":"counts_by_kind_api_v1_admin_contact_requests_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/contact/requests/{request_id}/status":{"patch":{"tags":["Admin","Admin"],"summary":"Update Request Status","description":"Mark a lead ``new`` / ``in_progress`` / ``done`` / ``ignored``.","operationId":"update_request_status_api_v1_admin_contact_requests__request_id__status_patch","parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"integer","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/runs":{"get":{"tags":["Admin","Admin"],"summary":"List Stored Runs","description":"List ingestion runs persisted to MinIO.","operationId":"list_stored_runs_api_v1_admin_runs_get","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/runs/{source}/{run_id}/{kind}":{"get":{"tags":["Admin","Admin"],"summary":"Fetch Run Artifact","description":"Fetch the raw or normalized JSON for a run.","operationId":"fetch_run_artifact_api_v1_admin_runs__source___run_id___kind__get","parameters":[{"name":"source","in":"path","required":true,"schema":{"type":"string","title":"Source"}},{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries":{"get":{"tags":["Admin","Admin"],"summary":"List Discoveries","description":"List proposed indicators from the discovery agent.","operationId":"list_discoveries_api_v1_admin_discoveries_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"pending | approved | rejected","title":"Status"},"description":"pending | approved | rejected"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/{disc_id}/approve":{"post":{"tags":["Admin","Admin"],"summary":"Approve Discovery","description":"Mark a discovery as approved AND promote it into the registry.","operationId":"approve_discovery_api_v1_admin_discoveries__disc_id__approve_post","parameters":[{"name":"disc_id","in":"path","required":true,"schema":{"type":"string","title":"Disc Id"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"reviewer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin display name","title":"Reviewer"},"description":"Admin display name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/{disc_id}/reject":{"post":{"tags":["Admin","Admin"],"summary":"Reject Discovery","description":"Mark a discovery as rejected.","operationId":"reject_discovery_api_v1_admin_discoveries__disc_id__reject_post","parameters":[{"name":"disc_id","in":"path","required":true,"schema":{"type":"string","title":"Disc Id"}},{"name":"note","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},{"name":"reviewer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin display name","title":"Reviewer"},"description":"Admin display name"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/scheduler":{"get":{"tags":["Admin","Admin"],"summary":"Discovery Scheduler Status","description":"Return last-run stats + config of the in-process discovery scheduler.","operationId":"discovery_scheduler_status_api_v1_admin_discoveries_scheduler_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/discoveries/run":{"post":{"tags":["Admin","Admin"],"summary":"Discovery Run Now","description":"Trigger a discovery pass immediately.","operationId":"discovery_run_now_api_v1_admin_discoveries_run_post","parameters":[{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Limit to one source (worldbank/imf/osm/comtrade/faostat)","title":"Source"},"description":"Limit to one source (worldbank/imf/osm/comtrade/faostat)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/webhook-deliveries":{"get":{"tags":["Admin","Admin"],"summary":"Webhook Deliveries","operationId":"webhook_deliveries_api_v1_admin_discoveries_webhook_deliveries_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"pending | delivered | dead_letter","title":"Status"},"description":"pending | delivered | dead_letter"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/webhook-deliveries/{delivery_id}/retry":{"post":{"tags":["Admin","Admin"],"summary":"Retry Webhook Delivery","operationId":"retry_webhook_delivery_api_v1_admin_discoveries_webhook_deliveries__delivery_id__retry_post","parameters":[{"name":"delivery_id","in":"path","required":true,"schema":{"type":"string","title":"Delivery Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/discoveries/reload":{"post":{"tags":["Admin","Admin"],"summary":"Reload Approved Registry","description":"Refresh caches so newly-approved agent indicators show up without restart.","operationId":"reload_approved_registry_api_v1_admin_discoveries_reload_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/ingest-queue":{"get":{"tags":["Admin","Admin"],"summary":"List Ingest Queue","description":"List ingestion jobs queued by approved discoveries.","operationId":"list_ingest_queue_api_v1_admin_ingest_queue_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"pending | running | done | failed","title":"Status"},"description":"pending | running | done | failed"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ingest-queue/drain":{"post":{"tags":["Admin","Admin"],"summary":"Drain Ingest Queue","description":"Run up to N pending jobs now.","operationId":"drain_ingest_queue_api_v1_admin_ingest_queue_drain_post","parameters":[{"name":"max_jobs","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Max Jobs"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ingest-queue/{job_id}/retry":{"post":{"tags":["Admin","Admin"],"summary":"Retry Ingest Job","description":"Flip a failed (or done) ingest job back to pending.","operationId":"retry_ingest_job_api_v1_admin_ingest_queue__job_id__retry_post","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/ingest-queue/retry-failed":{"post":{"tags":["Admin","Admin"],"summary":"Retry All Failed Ingest Jobs","description":"Flip every currently-failed job back to pending in one call.","operationId":"retry_all_failed_ingest_jobs_api_v1_admin_ingest_queue_retry_failed_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/refresh-schedule":{"get":{"tags":["Admin","Admin"],"summary":"List Refresh Schedule","description":"List refresh schedules.","operationId":"list_refresh_schedule_api_v1_admin_refresh_schedule_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"active | due","title":"Status"},"description":"active | due"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/refresh-schedule/{indicator_id}":{"get":{"tags":["Admin","Admin"],"summary":"Get Refresh Schedule","description":"Return the schedule entry for one indicator.","operationId":"get_refresh_schedule_api_v1_admin_refresh_schedule__indicator_id__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Admin","Admin"],"summary":"Set Refresh Schedule","description":"Create or update an indicator's refresh cadence.","operationId":"set_refresh_schedule_api_v1_admin_refresh_schedule__indicator_id__put","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"interval","in":"query","required":true,"schema":{"type":"string","description":"daily | weekly | monthly | never","title":"Interval"},"description":"daily | weekly | monthly | never"},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Discovery source slug (e.g. faostat-dictionary). Inferred from the indicator id if unset.","title":"Source"},"description":"Discovery source slug (e.g. faostat-dictionary). Inferred from the indicator id if unset."},{"name":"reviewer","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Admin display name for the audit trail","title":"Reviewer"},"description":"Admin display name for the audit trail"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Admin","Admin"],"summary":"Delete Refresh Schedule","description":"Remove the schedule entry.","operationId":"delete_refresh_schedule_api_v1_admin_refresh_schedule__indicator_id__delete","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/schema/status":{"get":{"tags":["Admin","Admin"],"summary":"Schema Status","description":"Return the last-run migration report.\n\nResponse shape::\n\n    {\n      \"attempted\": bool,\n      \"applied\":   [migration_id, ...],\n      \"skipped\":   [migration_id, ...],\n      \"failed\":    [{\"id\": ..., \"error\": ...}, ...],\n      \"error\":     None | str,\n      \"last_attempt_at\": ISO-8601 UTC | None,\n      \"clickhouse_reachable\": bool,\n      \"pending\":   [migration_id, ...]\n    }\n\n``pending`` is derived on-the-fly from the ``MIGRATIONS`` list minus\nwhat's recorded in the tracker — this is what an operator wants to\nsee, not just what the last apply attempted.","operationId":"schema_status_api_v1_admin_schema_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/schema/apply":{"post":{"tags":["Admin","Admin"],"summary":"Schema Apply","description":"Force an immediate migration apply cycle.\n\nUseful when the boot-time retry loop gave up (CH was down for the\nwhole retry window) or when a hotfix migration was hand-added to\nthe running container. Idempotent — pending migrations run; already-\napplied ones are skipped.","operationId":"schema_apply_api_v1_admin_schema_apply_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/pipeline/health":{"get":{"tags":["Admin","Admin"],"summary":"Pipeline Health","description":"One-stop health surface for the ingest + read pipeline.\n\nAggregates: ClickHouse migration state, per-source circuit-breaker\nstate (WB timeseries + compare, plus any connector breakers), and\nreachability of the analytics stores. This is what on-call watches\nwhen a bloc page starts showing dashes — the answer is here without\nssh'ing into a container.","operationId":"pipeline_health_api_v1_admin_pipeline_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/pipeline/circuits/{name}/reset":{"post":{"tags":["Admin","Admin"],"summary":"Reset Circuit","description":"Manually close a circuit after an on-call has fixed downstream.\n\nRarely needed — breakers half-open + close themselves within the\ncooldown window. This exists for the \"we know the fix landed 60s\nago, don't want to wait for the natural recovery\" case.","operationId":"reset_circuit_api_v1_admin_pipeline_circuits__name__reset_post","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/indicators/category-overrides":{"get":{"tags":["Admin","Admin"],"summary":"List Overrides","operationId":"list_overrides_api_v1_admin_indicators_category_overrides_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/indicators/{indicator_id}/category":{"patch":{"tags":["Admin","Admin"],"summary":"Set Category","operationId":"set_category_api_v1_admin_indicators__indicator_id__category_patch","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryOverride"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/settings/email":{"get":{"tags":["Admin","Admin"],"summary":"Get Email Settings","description":"Return the current sender-name overrides for the signup drip\n(welcome / day 2 / day 3). Empty dict for a key means the\ntemplate is using its compiled-in default (Peris / Sharon / Sharon).","operationId":"get_email_settings_api_v1_admin_settings_email_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/settings/email/{key}":{"put":{"tags":["Admin","Admin"],"summary":"Put Email Setting","description":"Set the sender name (and optional title) for one signup email.","operationId":"put_email_setting_api_v1_admin_settings_email__key__put","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderConfig"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/backfill-transform-hash":{"post":{"tags":["Admin","Admin"],"summary":"Backfill Transform Hash","description":"Kick off the transform_hash backfill in the background.","operationId":"backfill_transform_hash_api_v1_admin_maintenance_backfill_transform_hash_post","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Report without mutating","default":false,"title":"Dry Run"},"description":"Report without mutating"},{"name":"limit_runs","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":0,"description":"Cap on distinct run_ids per call. 0 = all.","default":0,"title":"Limit Runs"},"description":"Cap on distinct run_ids per call. 0 = all."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/faostat-hdx-sync":{"post":{"tags":["Admin","Admin"],"summary":"Faostat Hdx Sync","description":"Kick off the FAOSTAT-HDX sync in the background.","operationId":"faostat_hdx_sync_api_v1_admin_maintenance_faostat_hdx_sync_post","parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Re-download packages even if metadata_modified unchanged","default":false,"title":"Force"},"description":"Re-download packages even if metadata_modified unchanged"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Report which packages would fetch, no download","default":false,"title":"Dry Run"},"description":"Report which packages would fetch, no download"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/kamis-sync":{"post":{"tags":["Admin","Admin"],"summary":"Kamis Sync","description":"Kick off the KAMIS market-price scrape in the background.","operationId":"kamis_sync_api_v1_admin_maintenance_kamis_sync_post","parameters":[{"name":"max_pages","in":"query","required":false,"schema":{"type":"integer","maximum":3500,"minimum":1,"description":"How many KAMIS market-page windows (10 rows each) to walk","default":100,"title":"Max Pages"},"description":"How many KAMIS market-page windows (10 rows each) to walk"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Report the planned offset window without fetching","default":false,"title":"Dry Run"},"description":"Report the planned offset window without fetching"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/nipfn-sync":{"post":{"tags":["Admin","Admin"],"summary":"Nipfn Sync","description":"Kick off the NIPFN catalog + file mirror sync in the background.","operationId":"nipfn_sync_api_v1_admin_maintenance_nipfn_sync_post","parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Re-download every package regardless of update epoch","default":false,"title":"Force"},"description":"Re-download every package regardless of update epoch"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Fetch listing only; skip file downloads","default":false,"title":"Dry Run"},"description":"Fetch listing only; skip file downloads"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/nipfn-extract":{"post":{"tags":["Admin","Admin"],"summary":"Nipfn Extract","description":"Run per-file XLSX extractors against the mirrored NIPFN packages.\n\nWalks every slug in MinIO under ``nipfn/`` and dispatches by\nregistered exact-slug or pattern extractor. Writes a run envelope,\ninserts into ClickHouse, and auto-registers new indicators. A\nre-run is idempotent: the same (indicator, country, date) tuples\noverwrite via ClickHouse ReplacingMergeTree.","operationId":"nipfn_extract_api_v1_admin_maintenance_nipfn_extract_post","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Report mirrored slugs + extractor coverage without extraction","default":false,"title":"Dry Run"},"description":"Report mirrored slugs + extractor coverage without extraction"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/nipfn-slugs":{"get":{"tags":["Admin","Admin"],"summary":"Nipfn Slugs","description":"List every slug mirrored under ``nipfn/`` in MinIO with its\nextractor coverage (``exact``, ``pattern``, or ``none``).","operationId":"nipfn_slugs_api_v1_admin_maintenance_nipfn_slugs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/admin/maintenance/signup-nudges":{"post":{"tags":["Admin","Admin"],"summary":"Signup Nudges","description":"Kick off an ad-hoc signup nudge pass in the background.","operationId":"signup_nudges_api_v1_admin_maintenance_signup_nudges_post","parameters":[{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Preview eligible users without emailing","default":false,"title":"Dry Run"},"description":"Preview eligible users without emailing"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/jobs/{job_id}":{"get":{"tags":["Admin","Admin"],"summary":"Maintenance Job","description":"Return the current state + result (if finished) for one job.","operationId":"maintenance_job_api_v1_admin_maintenance_jobs__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/maintenance/jobs":{"get":{"tags":["Admin","Admin"],"summary":"Maintenance Jobs Recent","description":"Newest-first list of recent maintenance jobs (in-memory only).","operationId":"maintenance_jobs_recent_api_v1_admin_maintenance_jobs_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/query":{"post":{"tags":["Agent"],"summary":"Agent Query","operationId":"agent_query_api_v1_agent_query_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentQueryRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentQueryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/freshness":{"get":{"tags":["Analytics"],"summary":"Analytics Freshness","description":"Data-freshness dashboard: per-publisher and per-category lag rollups.","operationId":"analytics_freshness_api_v1_analytics_freshness_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/analytics/freshness/breaches":{"get":{"tags":["Analytics"],"summary":"Analytics Freshness Breaches","description":"Every indicator whose current freshness matches the requested\nstatus bands. Machine-readable companion to /analytics/freshness\n(which is aggregated) — this one is designed for agent scheduler\npolling and for building the \"watch these indicators\" ops surface.","operationId":"analytics_freshness_breaches_api_v1_analytics_freshness_breaches_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated freshness statuses to include. Choices: fresh, aging, stale, critical.","default":"stale,critical","title":"Status"},"description":"Comma-separated freshness statuses to include. Choices: fresh, aging, stale, critical."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/projections/{indicator_id}/{country_code}":{"get":{"tags":["Analytics"],"summary":"Get Projection","description":"Project an indicator forward by ``years`` years for a country.","operationId":"get_projection_api_v1_projections__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"years","in":"query","required":false,"schema":{"type":"integer","maximum":15,"minimum":1,"description":"Horizon in years","default":5,"title":"Years"},"description":"Horizon in years"},{"name":"history_years","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":5,"description":"History window to fit","default":20,"title":"History Years"},"description":"History window to fit"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/rankings":{"get":{"tags":["Analytics"],"summary":"Analytics Rankings","description":"Rank countries by an indicator with percentiles, growth rates, and insight.","operationId":"analytics_rankings_api_v1_analytics_rankings_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID (e.g. NY.GDP.MKTP.CD)","title":"Indicator"},"description":"Indicator ID (e.g. NY.GDP.MKTP.CD)"},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Year (default: latest available)","title":"Year"},"description":"Year (default: latest available)"},{"name":"scope","in":"query","required":false,"schema":{"type":"string","description":"'africa' for all 55, or a bloc code (EAC, ECOWAS, SADC, etc.)","default":"africa","title":"Scope"},"description":"'africa' for all 55, or a bloc code (EAC, ECOWAS, SADC, etc.)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/growth/{indicator_id}/{country_code}":{"get":{"tags":["Analytics"],"summary":"Analytics Growth","description":"Full growth analysis for one indicator + country.","operationId":"analytics_growth_api_v1_analytics_growth__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"start_year","in":"query","required":false,"schema":{"type":"integer","description":"Start year","default":2000,"title":"Start Year"},"description":"Start year"},{"name":"end_year","in":"query","required":false,"schema":{"type":"integer","description":"End year (defaults to current year)","title":"End Year"},"description":"End year (defaults to current year)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/scorecard/{country_code}":{"get":{"tags":["Analytics"],"summary":"Analytics Scorecard","description":"Comprehensive country scorecard: composite scores + peer comparison.","operationId":"analytics_scorecard_api_v1_analytics_scorecard__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/overview":{"get":{"tags":["Analytics"],"summary":"Analytics Overview","description":"Regional overview: aggregate stats, top performers, recent trends.","operationId":"analytics_overview_api_v1_analytics_overview_get","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","description":"'africa' for all 55 countries, or a bloc code (EAC, ECOWAS, SADC, COMESA, AU, etc.)","default":"africa","title":"Scope"},"description":"'africa' for all 55 countries, or a bloc code (EAC, ECOWAS, SADC, COMESA, AU, etc.)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/analytics/compare-growth":{"get":{"tags":["Analytics"],"summary":"Analytics Compare Growth","description":"Compare growth trajectories across multiple countries. Pro+ subscription.","operationId":"analytics_compare_growth_api_v1_analytics_compare_growth_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID","title":"Indicator"},"description":"Indicator ID"},{"name":"countries","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated country codes","title":"Countries"},"description":"Comma-separated country codes"},{"name":"years","in":"query","required":false,"schema":{"type":"integer","description":"Number of years to compare","default":10,"title":"Years"},"description":"Number of years to compare"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys":{"get":{"tags":["API Keys"],"summary":"List Keys","description":"List all API keys (masked) for current user.","operationId":"list_keys_api_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["API Keys"],"summary":"Create Key","description":"Generate a new API key.","operationId":"create_key_api_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateKeyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys/{key_id}":{"delete":{"tags":["API Keys"],"summary":"Delete Key","description":"Revoke an API key.","operationId":"delete_key_api_v1_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ask":{"post":{"tags":["Natural Language"],"summary":"Ask Question","description":"Answer a natural-language question about African statistical data.","operationId":"ask_question_api_v1_ask_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AskRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/signup":{"post":{"tags":["Auth"],"summary":"Signup","description":"Register a new user account.\n\nFailure modes are split into three distinct outcomes so a bug in a\npost-create step never leaves the client thinking their account\ndoesn't exist when it does:\n\n* **400** — validation / duplicate email. Nothing was written.\n* **201 + warning** — account created but tokens or welcome email\n  failed. The user *is* signed up and can sign in; the response\n  body carries ``status: \"created_signin_required\"`` so the client\n  can route to /login instead of showing a hard failure.\n* **500** — the ``create_user`` call itself blew up. Nothing was\n  written; safe to retry.\n\nPrior versions only caught ``ValueError``, so a JWT-encoding or\n``user_to_response`` glitch turned into a 500 while the row was\nalready committed. Symptom: \"signup failed\" toast in the UI, user\nvisible in admin, user unable to log in because the client didn't\npersist the tokens.","operationId":"signup_api_v1_auth_signup_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/forgot-password":{"post":{"tags":["Auth"],"summary":"Forgot Password","description":"Issue a one-time password-reset token and email the link.\n\nAlways returns 200 with a generic message — we never confirm or deny\nthat the email is registered (anti-enumeration).","operationId":"forgot_password_api_v1_auth_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/reset-password":{"post":{"tags":["Auth"],"summary":"Reset Password","description":"Consume a reset token + set the new password.","operationId":"reset_password_api_v1_auth_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/set-password":{"post":{"tags":["Auth"],"summary":"Set Password","description":"First-time password set for accounts that came in through an\nOAuth provider (Google today) and don't yet have a local password.\n\nRejects with 409 if a password already exists — the user must go\nthrough /auth/change-password in that case, which requires the\ncurrent password. This asymmetry is the whole point: we do NOT\nwant a compromised Google session to be able to silently reset a\nreal password without knowing the current one.\n\nFires the same password_changed security notification the reset\nand change flows use, so the user gets an audit-trail email even\nfor a first-time password set.","operationId":"set_password_api_v1_auth_set_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/change-password":{"post":{"tags":["Auth"],"summary":"Change Password","description":"Logged-in user changes their own password.","operationId":"change_password_api_v1_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["Auth"],"summary":"Login","description":"Authenticate and get JWT token.","operationId":"login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/session/anonymous":{"post":{"tags":["Auth"],"summary":"Issue Browser Session","description":"Issue a short-lived browser-session JWT.\n\nOrigin must match SESSION_ALLOWED_ORIGINS and per-IP throttle applies.\nCombined those two layers stop bots from minting tokens at scale.","operationId":"issue_browser_session_api_v1_session_anonymous_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/refresh":{"post":{"tags":["Auth"],"summary":"Refresh Token","description":"Refresh access token.","operationId":"refresh_token_api_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user/profile":{"get":{"tags":["Auth"],"summary":"Get Profile","description":"Get current user profile.","operationId":"get_profile_api_v1_user_profile_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/user/dashboard":{"get":{"tags":["Auth","Dashboard"],"summary":"User Dashboard","description":"Get aggregated dashboard data for current user.","operationId":"user_dashboard_api_v1_user_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/auth/firebase-exchange":{"post":{"tags":["Auth"],"summary":"Firebase Exchange","description":"Verify a Firebase ID token, upsert the user, mint AfricaDB JWTs.\n\nResponse shape matches /auth/login exactly so the frontend can\ntreat this as a drop-in alternative code path.","operationId":"firebase_exchange_api_v1_auth_firebase_exchange_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirebaseExchangeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blocs":{"get":{"tags":["Trade Blocs"],"summary":"List Blocs","description":"List all African trade blocs.","operationId":"list_blocs_api_v1_blocs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/blocs/compare":{"get":{"tags":["Trade Blocs"],"summary":"Compare Blocs Endpoint","description":"Compare an indicator across multiple trade blocs.","operationId":"compare_blocs_endpoint_api_v1_blocs_compare_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID","title":"Indicator"},"description":"Indicator ID"},{"name":"blocs","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated bloc codes (e.g. EAC,COMESA,ECOWAS)","title":"Blocs"},"description":"Comma-separated bloc codes (e.g. EAC,COMESA,ECOWAS)"},{"name":"year","in":"query","required":false,"schema":{"type":"integer","description":"Year to compare","default":2023,"title":"Year"},"description":"Year to compare"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blocs/{code}":{"get":{"tags":["Trade Blocs"],"summary":"Get Bloc Detail","description":"Get trade bloc details including member countries.","operationId":"get_bloc_detail_api_v1_blocs__code__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blocs/{code}/indicators":{"get":{"tags":["Trade Blocs"],"summary":"Get Bloc Indicators Batch","description":"Batch aggregate for N indicators in one round-trip.\n\nFires one ``compute_bloc_aggregate`` per indicator concurrently\n(asyncio.gather, no browser HTTP/1.1 6-connection cap here). The\nfrontend bloc detail page uses this so all ~25 tiles land in a\nsingle fetch instead of being throttled into 4-5 waves of six.\n\nResponse shape: ``{\"bloc\": \"COMESA\", \"year\": 2026,\n                   \"indicators\": {\"NY.GDP.MKTP.CD\": <agg>, ...}}``.\nIndividual indicator errors return `null` in the map rather than\nfailing the whole request.","operationId":"get_bloc_indicators_batch_api_v1_blocs__code__indicators_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"ids","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated indicator IDs","title":"Ids"},"description":"Comma-separated indicator IDs"},{"name":"year","in":"query","required":false,"schema":{"type":"integer","description":"Target year. Per-member values fall back to latest available year <= this if the exact year is unpublished.","title":"Year"},"description":"Target year. Per-member values fall back to latest available year <= this if the exact year is unpublished."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blocs/{code}/indicators/{indicator_id}":{"get":{"tags":["Trade Blocs"],"summary":"Get Bloc Indicator","description":"Get aggregate indicator value for a trade bloc with member breakdown.","operationId":"get_bloc_indicator_api_v1_blocs__code__indicators__indicator_id__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"year","in":"query","required":false,"schema":{"type":"integer","description":"Target year. Per-member values fall back to latest available year ≤ this if the exact year is unpublished.","title":"Year"},"description":"Target year. Per-member values fall back to latest available year ≤ this if the exact year is unpublished."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/blocs/{code}/timeseries/{indicator_id}":{"get":{"tags":["Trade Blocs"],"summary":"Get Bloc Timeseries","description":"Get aggregate time series for a trade bloc.","operationId":"get_bloc_timeseries_api_v1_blocs__code__timeseries__indicator_id__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}},{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"start_year","in":"query","required":false,"schema":{"type":"integer","default":2000,"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"type":"integer","title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/catalog/providers":{"get":{"tags":["Catalog"],"summary":"Catalog Providers","description":"Machine-readable capabilities for fixed, read-only providers.","operationId":"catalog_providers_api_v1_catalog_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/catalog/health":{"get":{"tags":["Catalog"],"summary":"Catalog Health","description":"Last-success, failure, durability, and schema-drift state by provider.","operationId":"catalog_health_api_v1_catalog_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/catalog/search":{"get":{"tags":["Catalog"],"summary":"Catalog Search","description":"Search persisted repository and dataset metadata.","operationId":"catalog_search_api_v1_catalog_search_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"title":"Query"}},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(repository|dataset)$"},{"type":"null"}],"title":"Kind"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/catalog/repositories":{"get":{"tags":["Catalog"],"summary":"Catalog Repositories","description":"Search the re3data repository index; this does not import datasets.","operationId":"catalog_repositories_api_v1_catalog_repositories_get","parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":200,"default":"","title":"Query"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/catalog/repositories/{repository_id}":{"get":{"tags":["Catalog"],"summary":"Catalog Repository","description":"Return normalized re3data v4 metadata for one repository.","operationId":"catalog_repository_api_v1_catalog_repositories__repository_id__get","parameters":[{"name":"repository_id","in":"path","required":true,"schema":{"type":"string","title":"Repository Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/catalog/datasets":{"get":{"tags":["Catalog"],"summary":"Catalog Datasets","description":"Search openAFRICA packages and normalize their distributions.\n\nServes from the local mirror first (postgres if durable, else the\nin-process cache). Falls back to a live open.africa search. If the\nlive call also fails, we return an empty page tagged with the\nreason rather than 500-ing the whole endpoint — the UI can then\nshow a \"sources temporarily unavailable\" state instead of a crash.","operationId":"catalog_datasets_api_v1_catalog_datasets_get","parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":200,"default":"","title":"Query"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/contact":{"post":{"tags":["Contact"],"summary":"Submit Contact","description":"Persist a public contact-form message + notify the matching inbox.\n\nTopic discriminator routes the email to support@ / billing@ / etc.\nso we don't need separate endpoints per team. All submissions land\nin the ``contact_requests`` table tagged\n``kind='contact:<topic>'`` for admin review.","operationId":"submit_contact_api_v1_contact_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/contact/data-requests":{"post":{"tags":["Contact"],"summary":"Submit Data Request","description":"Persist a \"please add this dataset\" request.\n\nRather than lumping into ``contact_requests`` with kind='contact:*',\nwe tag it kind='data_request' + serialize the structured fields into\n``extra`` so the admin queue can render them in a table. Fulfillment\ntracking (status, assignee) is a later add.","operationId":"submit_data_request_api_v1_contact_data_requests_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataRequestBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/contact/enterprise":{"post":{"tags":["Contact"],"summary":"Submit Enterprise Contact","description":"Persist an enterprise lead + notify sales.","operationId":"submit_enterprise_contact_api_v1_contact_enterprise_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnterpriseContactRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/contact/community/join":{"post":{"tags":["Contact"],"summary":"Submit Community Join","description":"Persist a community sign-up + notify the community inbox.\n\nStored in ``contact_requests`` under ``kind='community_signup'`` so\nadmin triage happens in the same place as every other public form.","operationId":"submit_community_join_api_v1_contact_community_join_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityJoinRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/countries":{"get":{"tags":["Countries"],"summary":"List Countries","description":"List every African country, with optional region / income filters.","operationId":"list_countries_api_v1_countries_get","parameters":[{"name":"region","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"}},{"name":"income_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Group"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/countries/{code}":{"get":{"tags":["Countries"],"summary":"Get Country","description":"Return one country's registry entry, augmented with bloc membership.","operationId":"get_country_api_v1_countries__code__get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/countries/{code}/blocs":{"get":{"tags":["Countries"],"summary":"Get Country Bloc Memberships","description":"Return the trade blocs a country belongs to.","operationId":"get_country_bloc_memberships_api_v1_countries__code__blocs_get","parameters":[{"name":"code","in":"path","required":true,"schema":{"type":"string","title":"Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email/unsubscribe":{"post":{"tags":["Email"],"summary":"Unsubscribe","operationId":"unsubscribe_api_v1_email_unsubscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/embed/config":{"get":{"tags":["Embed"],"summary":"Embed Config","description":"Public endpoint providing chart data for embeddable widgets.","operationId":"embed_config_api_v1_embed_config_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID","title":"Indicator"},"description":"Indicator ID"},{"name":"countries","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated country codes","title":"Countries"},"description":"Comma-separated country codes"},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"Chart type: line or bar","default":"line","title":"Type"},"description":"Chart type: line or bar"},{"name":"start_year","in":"query","required":false,"schema":{"type":"integer","default":2000,"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"type":"integer","title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/event":{"post":{"tags":["Analytics"],"summary":"Record Event","description":"Record one first-party event. Honours DNT. No third-party SDK.","operationId":"record_event_api_v1_event_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/funnel":{"get":{"tags":["Analytics","Admin"],"summary":"Admin Funnel","description":"Top-of-funnel counts since a given ISO timestamp (default: 14 days).","operationId":"admin_funnel_api_v1_admin_funnel_get","parameters":[{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/admin/event-breakdown":{"get":{"tags":["Analytics","Admin"],"summary":"Admin Event Breakdown","description":"Group occurrences of an event by one property key.\n\nExample: ``name=lane_click`` ``prop=lane`` returns\n``{analyst: N, developer: N, enterprise: N}``.","operationId":"admin_event_breakdown_api_v1_admin_event_breakdown_get","parameters":[{"name":"name","in":"query","required":true,"schema":{"type":"string","description":"Event name to break down","title":"Name"},"description":"Event name to break down"},{"name":"prop","in":"query","required":true,"schema":{"type":"string","description":"Property key to group by","title":"Prop"},"description":"Property key to group by"},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Since"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":25,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/export/csv":{"get":{"tags":["Export"],"summary":"Export Csv","description":"Export observations as CSV (available to signed-in users).","operationId":"export_csv_api_v1_export_csv_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","title":"Indicator"}},{"name":"countries","in":"query","required":true,"schema":{"type":"string","title":"Countries"}},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/export/json":{"get":{"tags":["Export"],"summary":"Export Json","description":"Export observations as JSON with citation metadata.","operationId":"export_json_api_v1_export_json_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","title":"Indicator"}},{"name":"countries","in":"query","required":true,"schema":{"type":"string","title":"Countries"}},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/export/xlsx":{"get":{"tags":["Export"],"summary":"Export Xlsx","description":"Export observations as Excel XLSX with metadata sheet.","operationId":"export_xlsx_api_v1_export_xlsx_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","title":"Indicator"}},{"name":"countries","in":"query","required":true,"schema":{"type":"string","title":"Countries"}},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/export/svg":{"get":{"tags":["Export"],"summary":"Export Svg","description":"Export a line chart as SVG with a provenance watermark burned in.\n\nThe bottom of the image carries ``Retrieved <ISO-8601 UTC>``,\nup to two ``run_id`` and transformation-hash values, and the\nverify-endpoint URL. Anyone\nwith the image (embedded on a blog, dropped into a PDF, screenshot\nin a paper) can trace the data back to its source without needing\na companion citation.\n\nSVG-only (no PNG rasterization) — kept dependency-light. Renders in\nevery browser, prints crisp at any zoom, and downstream users can\nconvert to PNG with any headless renderer.","operationId":"export_svg_api_v1_export_svg_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","title":"Indicator"}},{"name":"countries","in":"query","required":true,"schema":{"type":"string","title":"Countries"}},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":2000,"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End Year"}},{"name":"width","in":"query","required":false,"schema":{"type":"integer","maximum":2400,"minimum":320,"default":960,"title":"Width"}},{"name":"height","in":"query","required":false,"schema":{"type":"integer","maximum":1600,"minimum":240,"default":540,"title":"Height"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/export/bulk":{"get":{"tags":["Export"],"summary":"Export Bulk","description":"Bulk export multiple indicators for multiple countries.","operationId":"export_bulk_api_v1_export_bulk_get","parameters":[{"name":"indicators","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated indicator IDs","title":"Indicators"},"description":"Comma-separated indicator IDs"},{"name":"countries","in":"query","required":false,"schema":{"type":"string","description":"Comma-separated country codes or 'all'","default":"all","title":"Countries"},"description":"Comma-separated country codes or 'all'"},{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(csv|json)$","description":"Format: csv, json","default":"csv","title":"Format"},"description":"Format: csv, json"},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/facts":{"get":{"tags":["Facts"],"summary":"Get Facts","description":"Return the current fact set + a cache-hint envelope.\n\nResponse shape::\n\n    {\n      \"version\": \"1.0.0\",           # bump when facts change\n      \"generated_at\": \"...\",        # server render time (UTC)\n      \"recommended_cache_seconds\": 604800,  # 7 days\n      \"count\": 30,\n      \"facts\": [{\"text\": \"...\", \"category\": \"...\"}, ...]\n    }\n\nThe frontend should stash this in localStorage and only refetch\nwhen either (a) version has changed or (b) recommended_cache_seconds\nhas elapsed. The endpoint itself is cheap; the caching is about\nkeeping the loading UX zero-round-trip after first visit.","operationId":"get_facts_api_v1_facts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/forecast/methods":{"get":{"tags":["Forecasting"],"summary":"List Forecast Methods","description":"List available forecast methods.","operationId":"list_forecast_methods_api_v1_forecast_methods_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/forecast/{indicator_id}/{country_code}":{"get":{"tags":["Forecasting"],"summary":"Forecast Endpoint","description":"Get forecast/projection for an indicator in a specific country.","operationId":"forecast_endpoint_api_v1_forecast__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"method","in":"query","required":false,"schema":{"type":"string","description":"Forecast method: linear, exponential, imf_weo","default":"linear","title":"Method"},"description":"Forecast method: linear, exponential, imf_weo"},{"name":"years_ahead","in":"query","required":false,"schema":{"type":"integer","description":"Number of years to forecast","default":5,"title":"Years Ahead"},"description":"Number of years to forecast"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/indicators":{"get":{"tags":["Indicators"],"summary":"List Indicators","description":"Get all available indicators with rich metadata.","operationId":"list_indicators_api_v1_indicators_get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/indicators/categories":{"get":{"tags":["Indicators"],"summary":"List Categories","description":"Get all indicator categories.","operationId":"list_categories_api_v1_indicators_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/indicators/export":{"get":{"tags":["Indicators"],"summary":"Export Indicators","description":"Full indicator-catalog export for registered users.","operationId":"export_indicators_api_v1_indicators_export_get","parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(csv|json)$","description":"csv | json","default":"csv","title":"Format"},"description":"csv | json"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by source label (e.g. 'WB WDI', 'IMF WEO')","title":"Source"},"description":"Filter by source label (e.g. 'WB WDI', 'IMF WEO')"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/indicators/derived":{"get":{"tags":["Indicators"],"summary":"List Derived Indicators","description":"List all derived/computed indicators with their formulas and inputs.","operationId":"list_derived_indicators_api_v1_indicators_derived_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/indicators/{indicator_id}":{"get":{"tags":["Indicators"],"summary":"Get Indicator","description":"Get indicator by ID with full rich metadata.","operationId":"get_indicator_api_v1_indicators__indicator_id__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"tags":["Info"],"summary":"Root","description":"API root — service info and headline endpoints.","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/health":{"get":{"tags":["Info"],"summary":"Health Check","description":"Health check: per-backend reachability rollup for the LB probe.\n\nBoth backend probes run in parallel with a shared 1.5s timeout so a\nsingle slow sub-service can never push the health endpoint above ~2s\n(LB probes typically fire every 5-30s and count consecutive failures,\nso a slow /health cascades into false unhealthy reports fast).","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/map/data":{"get":{"tags":["Map"],"summary":"Map Data","description":"Get indicator values for all 55 African countries — for map rendering.","operationId":"map_data_api_v1_map_data_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID","title":"Indicator"},"description":"Indicator ID"},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Year (default: latest)","title":"Year"},"description":"Year (default: latest)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mcp/manifest":{"get":{"tags":["MCP"],"summary":"Agent Interface Manifest","description":"Public machine-readable discovery for REST and MCP agent clients.","operationId":"get_agent_interface_manifest","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentInterfaceManifest"}}}}}}},"/api/v1/mcp/access":{"get":{"tags":["MCP"],"summary":"Agent Account Access","description":"Return the authenticated agent caller's live plan and API allowance.","operationId":"get_agent_account_access","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentAccountAccess"}}}}}}},"/api/v1/mcp/audit":{"post":{"tags":["MCP"],"summary":"Record Mcp Audit","operationId":"record_mcp_audit_api_v1_mcp_audit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCPAuditEvent"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news":{"get":{"tags":["News"],"summary":"Get News","description":"Get latest African news with the full filter set.","operationId":"get_news_api_v1_news_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by country code (KE, NG, etc.)","title":"Country"},"description":"Filter by country code (KE, NG, etc.)"},{"name":"indicator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by indicator ID","title":"Indicator"},"description":"Filter by indicator ID"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"general|business|tech|energy|agriculture|health|education|analysis|security|climate","title":"Category"},"description":"general|business|tech|energy|agriculture|health|education|analysis|security|climate"},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by source_id (e.g. bbc_africa)","title":"Source"},"description":"Filter by source_id (e.g. bbc_africa)"},{"name":"region","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"east-africa|west-africa|southern-africa|pan-african","title":"Region"},"description":"east-africa|west-africa|southern-africa|pan-african"},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Keyword search across title + summary","title":"Q"},"description":"Keyword search across title + summary"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Number of articles to return (max 500)","default":20,"title":"Limit"},"description":"Number of articles to return (max 500)"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","description":"Pagination offset","default":0,"title":"Offset"},"description":"Pagination offset"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/news/sources":{"get":{"tags":["News"],"summary":"List News Sources","description":"List all configured RSS sources with category + region metadata.","operationId":"list_news_sources_api_v1_news_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/news/refresh":{"post":{"tags":["News"],"summary":"Refresh News","description":"Force an immediate news cache refresh from RSS feeds.","operationId":"refresh_news_api_v1_news_refresh_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/calendar":{"get":{"tags":["News"],"summary":"Economic Calendar","description":"Get the economic calendar of key African events.","operationId":"economic_calendar_api_v1_calendar_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by country code","title":"Country"},"description":"Filter by country code"},{"name":"month","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by month (1-12)","title":"Month"},"description":"Filter by month (1-12)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations":{"get":{"tags":["Observations"],"summary":"Query Observations","description":"Query time-series observations for one indicator across N countries.","operationId":"query_observations_api_v1_observations_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID (e.g., NY.GDP.MKTP.CD)","title":"Indicator"},"description":"Indicator ID (e.g., NY.GDP.MKTP.CD)"},{"name":"countries","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated country codes (e.g., KE,UG,TZ)","title":"Countries"},"description":"Comma-separated country codes (e.g., KE,UG,TZ)"},{"name":"start_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Start year","title":"Start Year"},"description":"Start year"},{"name":"end_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"End year","title":"End Year"},"description":"End year"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations/latest/{indicator_id}/{country_code}":{"get":{"tags":["Observations"],"summary":"Get Latest Observation","description":"Return the most recent observation for one indicator + country.","operationId":"get_latest_observation_api_v1_observations_latest__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations/compare":{"get":{"tags":["Observations"],"summary":"Compare Countries Endpoint","description":"Compare one indicator across a set of countries at a single point in time.","operationId":"compare_countries_endpoint_api_v1_observations_compare_get","parameters":[{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID","title":"Indicator"},"description":"Indicator ID"},{"name":"countries","in":"query","required":true,"schema":{"type":"string","description":"Comma-separated country codes","title":"Countries"},"description":"Comma-separated country codes"},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Year (default: latest)","title":"Year"},"description":"Year (default: latest)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations/timeseries/{indicator_id}/{country_code}":{"get":{"tags":["Observations"],"summary":"Get Timeseries","description":"Return the full time series for one indicator + country, with optional transform.","operationId":"get_timeseries_api_v1_observations_timeseries__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"start_year","in":"query","required":false,"schema":{"type":"integer","default":2000,"title":"Start Year"}},{"name":"end_year","in":"query","required":false,"schema":{"type":"integer","description":"Defaults to current year + 5 so IMF WEO forecasts are included","default":2031,"title":"End Year"},"description":"Defaults to current year + 5 so IMF WEO forecasts are included"},{"name":"transform","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Transform: pct_change, yoy, per_capita, per_gdp, moving_avg_3, moving_avg_5, indexed","title":"Transform"},"description":"Transform: pct_change, yoy, per_capita, per_gdp, moving_avg_3, moving_avg_5, indexed"},{"name":"base_year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Base year for indexed transform","title":"Base Year"},"description":"Base year for indexed transform"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/observations/countries/{country_code}":{"get":{"tags":["Observations"],"summary":"Get Country Indicators","description":"Return every indicator resolved for a single country at a target year.\n\nResolution order:\n\n  1. **Local store** (``_LOCAL_OBS``, populated by ingested runs).\n     This is the correct + fastest path and should serve nearly\n     100% of requests. Cached in RAM, no upstream call.\n  2. **Live upstream fetch** (World Bank API) — fallback only when\n     the local store has nothing for this country. Every fallback\n     increments the ``worldbank/live`` counter in\n     :mod:`core.data_source_metrics` with the country + endpoint\n     so ops can see coverage gaps without waiting for a support\n     ticket.\n\nWe WANT the fallback to be rare. If the counters show a lot of\nlive hits, the ingestion pipeline needs a bigger coverage sweep.","operationId":"get_country_indicators_api_v1_observations_countries__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"year","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs":{"post":{"tags":["Organizations"],"summary":"Self Create Org","description":"Current user creates their own organization.","operationId":"self_create_org_api_v1_orgs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SelfCreateOrgRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/mine":{"get":{"tags":["Organizations"],"summary":"My Org","description":"Return the current user's org (with pending invites if they're owner).","operationId":"my_org_api_v1_orgs_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/orgs/{org_id}/invite":{"post":{"tags":["Organizations"],"summary":"Invite Org Member","description":"Owner invites a teammate by email.","operationId":"invite_org_member_api_v1_orgs__org_id__invite_post","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgInviteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{org_id}/invite/{target_email}":{"delete":{"tags":["Organizations"],"summary":"Cancel Invite","description":"Owner cancels a pending invite.","operationId":"cancel_invite_api_v1_orgs__org_id__invite__target_email__delete","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}},{"name":"target_email","in":"path","required":true,"schema":{"type":"string","title":"Target Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/accept-invite":{"post":{"tags":["Organizations"],"summary":"Accept Org Invite","description":"Invitee accepts an invite link. Must be signed in as the token's email.","operationId":"accept_org_invite_api_v1_orgs_accept_invite_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgAcceptInviteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/{org_id}/leave":{"post":{"tags":["Organizations"],"summary":"Leave Org","description":"Member voluntarily leaves the org. Owner must transfer or delete first.","operationId":"leave_org_api_v1_orgs__org_id__leave_post","parameters":[{"name":"org_id","in":"path","required":true,"schema":{"type":"string","title":"Org Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog":{"get":{"tags":["Partners"],"summary":"Public Catalog","operationId":"public_catalog_api_v1_partners_catalog_get","parameters":[{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":10000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Api V1 Partners Catalog Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog/categories":{"get":{"tags":["Partners"],"summary":"Public Catalog Categories","operationId":"public_catalog_categories_api_v1_partners_catalog_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Categories Api V1 Partners Catalog Categories Get"}}}}}}},"/api/v1/partners/catalog/{partner_id}/{dataset_slug}":{"get":{"tags":["Partners"],"summary":"Public Catalog Detail","operationId":"public_catalog_detail_api_v1_partners_catalog__partner_id___dataset_slug__get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"path","required":true,"schema":{"type":"string","title":"Dataset Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Detail Api V1 Partners Catalog  Partner Id   Dataset Slug  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog/{partner_id}/{dataset_slug}/download":{"post":{"tags":["Partners"],"summary":"Public Catalog Download","operationId":"public_catalog_download_api_v1_partners_catalog__partner_id___dataset_slug__download_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"path","required":true,"schema":{"type":"string","title":"Dataset Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Download Api V1 Partners Catalog  Partner Id   Dataset Slug  Download Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog/{partner_id}/{dataset_slug}/preview":{"get":{"tags":["Partners"],"summary":"Public Catalog Preview","description":"Return the first N rows of a dataset as a preview sample.\n\nWorks on every published dataset regardless of ``access_policy`` —\nthe point is to help buyers evaluate before paying. We cap the read\nto a small byte window so previewing a multi-GB file doesn't stream\nthe whole thing.\n\nCSV is parsed inline; other content types return only the first\ncouple of KB as raw text with ``content_type`` set so the client\ncan decide how to render it.","operationId":"public_catalog_preview_api_v1_partners_catalog__partner_id___dataset_slug__preview_get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"path","required":true,"schema":{"type":"string","title":"Dataset Slug"}},{"name":"rows","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Rows"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Preview Api V1 Partners Catalog  Partner Id   Dataset Slug  Preview Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog/{partner_id}/{dataset_slug}/revisions":{"get":{"tags":["Partners"],"summary":"Public Catalog Revisions","operationId":"public_catalog_revisions_api_v1_partners_catalog__partner_id___dataset_slug__revisions_get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"path","required":true,"schema":{"type":"string","title":"Dataset Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Public Catalog Revisions Api V1 Partners Catalog  Partner Id   Dataset Slug  Revisions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/catalog/{partner_id}/{dataset_slug}/file":{"get":{"tags":["Partners"],"summary":"Public Catalog File","description":"Stream the actual dataset file. Records a download event\nonly after the object store returns a real body, so a missing\nfile never bills the caller.","operationId":"public_catalog_file_api_v1_partners_catalog__partner_id___dataset_slug__file_get","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"path","required":true,"schema":{"type":"string","title":"Dataset Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me":{"get":{"tags":["Partners"],"summary":"Get My Partner","operationId":"get_my_partner_api_v1_partners_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get My Partner Api V1 Partners Me Get"}}}}}}},"/api/v1/partners/me/summary":{"get":{"tags":["Partners"],"summary":"Get My Summary","operationId":"get_my_summary_api_v1_partners_me_summary_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"default":30,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Get My Summary Api V1 Partners Me Summary Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets":{"get":{"tags":["Partners"],"summary":"List My Datasets","operationId":"list_my_datasets_api_v1_partners_me_datasets_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(draft|published|retired)$"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List My Datasets Api V1 Partners Me Datasets Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Partners"],"summary":"Create My Dataset","operationId":"create_my_dataset_api_v1_partners_me_datasets_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDatasetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Create My Dataset Api V1 Partners Me Datasets Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}":{"patch":{"tags":["Partners"],"summary":"Update My Dataset","operationId":"update_my_dataset_api_v1_partners_me_datasets__dataset_id__patch","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDatasetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Update My Dataset Api V1 Partners Me Datasets  Dataset Id  Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}/events":{"post":{"tags":["Partners"],"summary":"Record My Event","operationId":"record_my_event_api_v1_partners_me_datasets__dataset_id__events_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordEventRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Record My Event Api V1 Partners Me Datasets  Dataset Id  Events Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/events":{"get":{"tags":["Partners"],"summary":"List My Events","operationId":"list_my_events_api_v1_partners_me_events_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","maximum":100000,"minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List My Events Api V1 Partners Me Events Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}/upload":{"post":{"tags":["Partners"],"summary":"Upload My Dataset File","operationId":"upload_my_dataset_file_api_v1_partners_me_datasets__dataset_id__upload_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_my_dataset_file_api_v1_partners_me_datasets__dataset_id__upload_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Upload My Dataset File Api V1 Partners Me Datasets  Dataset Id  Upload Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Partners"],"summary":"Clear My Dataset File","operationId":"clear_my_dataset_file_api_v1_partners_me_datasets__dataset_id__upload_delete","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Clear My Dataset File Api V1 Partners Me Datasets  Dataset Id  Upload Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}/revisions":{"get":{"tags":["Partners"],"summary":"List My Dataset Revisions","operationId":"list_my_dataset_revisions_api_v1_partners_me_datasets__dataset_id__revisions_get","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List My Dataset Revisions Api V1 Partners Me Datasets  Dataset Id  Revisions Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}/publish":{"post":{"tags":["Partners"],"summary":"Publish My Dataset","operationId":"publish_my_dataset_api_v1_partners_me_datasets__dataset_id__publish_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Publish My Dataset Api V1 Partners Me Datasets  Dataset Id  Publish Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/datasets/{dataset_id}/unpublish":{"post":{"tags":["Partners"],"summary":"Unpublish My Dataset","operationId":"unpublish_my_dataset_api_v1_partners_me_datasets__dataset_id__unpublish_post","parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Unpublish My Dataset Api V1 Partners Me Datasets  Dataset Id  Unpublish Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/me/payouts":{"get":{"tags":["Partners"],"summary":"List My Payouts","operationId":"list_my_payouts_api_v1_partners_me_payouts_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response List My Payouts Api V1 Partners Me Payouts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners":{"get":{"tags":["Partners"],"summary":"Admin List Partners","operationId":"admin_list_partners_api_v1_partners_get","parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(pending|active|suspended)$"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":200,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin List Partners Api V1 Partners Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Partners"],"summary":"Admin Create Partner","operationId":"admin_create_partner_api_v1_partners_post","parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string","title":"Org Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePartnerRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Create Partner Api V1 Partners Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/{partner_id}/status":{"patch":{"tags":["Partners"],"summary":"Admin Update Partner Status","operationId":"admin_update_partner_status_api_v1_partners__partner_id__status_patch","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePartnerStatusRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Update Partner Status Api V1 Partners  Partner Id  Status Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/{partner_id}/payouts/close":{"post":{"tags":["Partners"],"summary":"Admin Close Payout","operationId":"admin_close_payout_api_v1_partners__partner_id__payouts_close_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClosePayoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Close Payout Api V1 Partners  Partner Id  Payouts Close Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/partners/{partner_id}/payouts/{payout_id}/paid":{"post":{"tags":["Partners"],"summary":"Admin Mark Payout Paid","operationId":"admin_mark_payout_paid_api_v1_partners__partner_id__payouts__payout_id__paid_post","parameters":[{"name":"partner_id","in":"path","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"payout_id","in":"path","required":true,"schema":{"type":"string","title":"Payout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","title":"Response Admin Mark Payout Paid Api V1 Partners  Partner Id  Payouts  Payout Id  Paid Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/create-checkout-session":{"post":{"tags":["Payments"],"summary":"Checkout","description":"Create a Stripe Checkout session for a subscription tier.","operationId":"checkout_api_v1_payments_create_checkout_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/portal":{"get":{"tags":["Payments"],"summary":"Customer Portal","description":"Return the Stripe Customer Portal URL for the signed-in user.","operationId":"customer_portal_api_v1_payments_portal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/config":{"get":{"tags":["Payments"],"summary":"Payment Config","description":"Return the publishable key + tier pricing so the frontend can\ninitialise Stripe.js without a separate config round-trip.","operationId":"payment_config_api_v1_payments_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/webhook":{"post":{"tags":["Payments"],"summary":"Stripe Webhook","description":"Handle Stripe webhook events.\n\nStripe must be configured and every payload must have a valid signature.","operationId":"stripe_webhook_api_v1_payments_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/dev-upgrade":{"post":{"tags":["Payments"],"summary":"Dev Upgrade","description":"DEV ONLY: promote the signed-in user's tier without Stripe.\n\nKept behind auth so it only ever runs for a real logged-in user; the\nadmin surface has the same capability via ``grant-tier`` for use\nagainst arbitrary users.","operationId":"dev_upgrade_api_v1_payments_dev_upgrade_post","parameters":[{"name":"tier","in":"query","required":false,"schema":{"type":"string","default":"pro","title":"Tier"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/subscribe":{"post":{"tags":["Payments"],"summary":"Start Subscription","description":"Create a PayPal subscription. Returns approval URL for the frontend to redirect to.","operationId":"start_subscription_api_v1_payments_paypal_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/subscription/return":{"get":{"tags":["Payments"],"summary":"Subscription Return","description":"Called when the user is redirected back from PayPal approval.\n\nPromotes the tier immediately (webhook does the same later; both are\nidempotent). The frontend then lands on /payment/success.","operationId":"subscription_return_api_v1_payments_paypal_subscription_return_get","parameters":[{"name":"subscription_id","in":"query","required":false,"schema":{"type":"string","default":"","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/subscription/cancel":{"post":{"tags":["Payments"],"summary":"Cancel Subscription","description":"Cancel the caller's PayPal subscription and downgrade to free.","operationId":"cancel_subscription_api_v1_payments_paypal_subscription_cancel_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/paypal/orders":{"post":{"tags":["Payments"],"summary":"Start Order","description":"Create a marketplace order for a paid dataset. Returns approval URL.","operationId":"start_order_api_v1_payments_paypal_orders_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/orders/{purchase_id}/capture":{"post":{"tags":["Payments"],"summary":"Capture Order","description":"Capture funds for an approved order + grant access.\n\nCalled by the frontend right after the user approves at PayPal. The\nwebhook will fire the same capture path (idempotent) as a\nbelt-and-braces guarantee.","operationId":"capture_order_api_v1_payments_paypal_orders__purchase_id__capture_post","parameters":[{"name":"purchase_id","in":"path","required":true,"schema":{"type":"string","title":"Purchase Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/purchases/me":{"get":{"tags":["Payments"],"summary":"My Purchases","operationId":"my_purchases_api_v1_payments_paypal_purchases_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/payments/paypal/dataset-access":{"get":{"tags":["Payments"],"summary":"Dataset Access Check","description":"Frontend polls this to decide whether to show 'Buy' or 'Download'.","operationId":"dataset_access_check_api_v1_payments_paypal_dataset_access_get","parameters":[{"name":"partner_id","in":"query","required":true,"schema":{"type":"string","title":"Partner Id"}},{"name":"dataset_slug","in":"query","required":true,"schema":{"type":"string","title":"Dataset Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/payments/paypal/webhook":{"post":{"tags":["Payments"],"summary":"Paypal Webhook","description":"Signed PayPal webhook.\n\nHandles:\n  BILLING.SUBSCRIPTION.ACTIVATED  -> promote user tier\n  BILLING.SUBSCRIPTION.CANCELLED  -> downgrade to free\n  PAYMENT.CAPTURE.COMPLETED       -> flip dataset purchase to captured\n                                     (in case the return-URL leg didn't)\n\nIdempotent via ``payment_webhook_events`` (provider, event_id).","operationId":"paypal_webhook_api_v1_payments_paypal_webhook_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/provenance/citation/{indicator_id}/{country_code}":{"get":{"tags":["Provenance"],"summary":"Get Machine Citation","description":"Return all citation styles with run IDs and transform hashes.","operationId":"get_machine_citation_api_v1_provenance_citation__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/provenance/{indicator_id}/{country_code}":{"get":{"tags":["Provenance"],"summary":"Get Provenance","description":"Data provenance chain showing where a data point came from and how it was processed.","operationId":"get_provenance_api_v1_provenance__indicator_id___country_code__get","parameters":[{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}},{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/realtime/forex":{"get":{"tags":["Real-Time"],"summary":"Realtime Forex","description":"Get latest forex rates for African currencies vs USD.","operationId":"realtime_forex_api_v1_realtime_forex_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by country code","title":"Country"},"description":"Filter by country code"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/realtime/forex/{country_code}":{"get":{"tags":["Real-Time"],"summary":"Realtime Forex Country","description":"Get latest forex rate for a specific country.","operationId":"realtime_forex_country_api_v1_realtime_forex__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/realtime/commodities":{"get":{"tags":["Real-Time"],"summary":"Realtime Commodities","description":"Get latest commodity prices.","operationId":"realtime_commodities_api_v1_realtime_commodities_get","parameters":[{"name":"commodity","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by commodity ID","title":"Commodity"},"description":"Filter by commodity ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/realtime/commodities/{commodity_id}":{"get":{"tags":["Real-Time"],"summary":"Realtime Commodity","description":"Get latest price for a specific commodity.","operationId":"realtime_commodity_api_v1_realtime_commodities__commodity_id__get","parameters":[{"name":"commodity_id","in":"path","required":true,"schema":{"type":"string","title":"Commodity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/realtime/ticker":{"get":{"tags":["Real-Time"],"summary":"Realtime Ticker","description":"Get a combined ticker of latest forex and commodity updates.","operationId":"realtime_ticker_api_v1_realtime_ticker_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Number of items","default":20,"title":"Limit"},"description":"Number of items"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/country/{country_code}":{"get":{"tags":["Reports"],"summary":"Country Report","description":"Return the composite country intelligence report.","operationId":"country_report_api_v1_reports_country__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/bloc/{bloc_code}":{"get":{"tags":["Reports"],"summary":"Bloc Report","description":"Return the composite trade-bloc intelligence report.","operationId":"bloc_report_api_v1_reports_bloc__bloc_code__get","parameters":[{"name":"bloc_code","in":"path","required":true,"schema":{"type":"string","title":"Bloc Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/risk/scores":{"get":{"tags":["Risk"],"summary":"Get Risk Scores","description":"Composite sovereign risk scores for all 55 African countries.","operationId":"get_risk_scores_api_v1_risk_scores_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/risk/{country_code}":{"get":{"tags":["Risk"],"summary":"Get Country Risk","description":"Detailed risk breakdown for a single country.","operationId":"get_country_risk_api_v1_risk__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/screener":{"get":{"tags":["Screener"],"summary":"Get Screener","description":"Return the composite screener payload for every African country.","operationId":"get_screener_api_v1_screener_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/search":{"get":{"tags":["Search"],"summary":"Global Search","description":"Typo-tolerant search across indicators + countries.","operationId":"global_search_api_v1_search_get","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","description":"Search query","default":"","title":"Q"},"description":"Search query"},{"name":"types","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated subset of: indicator,country","title":"Types"},"description":"Comma-separated subset of: indicator,country"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"default":8,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sentiment":{"get":{"tags":["Sentiment"],"summary":"Get All Sentiments","description":"Compute news sentiment for all African countries.","operationId":"get_all_sentiments_api_v1_sentiment_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","description":"Max articles to process","default":200,"title":"Limit"},"description":"Max articles to process"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sentiment/{country_code}":{"get":{"tags":["Sentiment"],"summary":"Get Country Sentiment","description":"Compute news sentiment for a specific country.","operationId":"get_country_sentiment_api_v1_sentiment__country_code__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sources":{"get":{"tags":["Indicators"],"summary":"List Sources","description":"Per-publisher rollup: labels, counts, vintages, categories.","operationId":"list_sources_api_v1_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/stats":{"get":{"tags":["Statistics"],"summary":"Get Database Stats","description":"Get platform statistics + data freshness (60s cache).","operationId":"get_database_stats_api_v1_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/subnational/{country_code}/{indicator_id}":{"get":{"tags":["Sub-National"],"summary":"Subnational Data","description":"Get sub-national (region/county) data from DHS surveys.","operationId":"subnational_data_api_v1_subnational__country_code___indicator_id__get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}},{"name":"indicator_id","in":"path","required":true,"schema":{"type":"string","title":"Indicator Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subnational/{country_code}/regions":{"get":{"tags":["Sub-National"],"summary":"Subnational Regions","description":"Get list of sub-national regions for a country.","operationId":"subnational_regions_api_v1_subnational__country_code__regions_get","parameters":[{"name":"country_code","in":"path","required":true,"schema":{"type":"string","title":"Country Code"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/subnational/indicators":{"get":{"tags":["Sub-National"],"summary":"Subnational Indicators","description":"List available sub-national (DHS) indicators.","operationId":"subnational_indicators_api_v1_subnational_indicators_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/subnational/countries":{"get":{"tags":["Sub-National"],"summary":"Subnational Countries","description":"List countries with available DHS sub-national data.","operationId":"subnational_countries_api_v1_subnational_countries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/teams":{"post":{"tags":["Teams"],"summary":"Create Team Endpoint","description":"Create a new team/organization.","operationId":"create_team_endpoint_api_v1_teams_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/{team_id}":{"get":{"tags":["Teams"],"summary":"Get Team Endpoint","description":"Get team details.","operationId":"get_team_endpoint_api_v1_teams__team_id__get","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/{team_id}/members":{"post":{"tags":["Teams"],"summary":"Add Member","description":"Add a member to the team.","operationId":"add_member_api_v1_teams__team_id__members_post","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddMemberRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/teams/{team_id}/members/{member_email}":{"delete":{"tags":["Teams"],"summary":"Remove Member","description":"Remove a member from the team.","operationId":"remove_member_api_v1_teams__team_id__members__member_email__delete","parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","title":"Team Id"}},{"name":"member_email","in":"path","required":true,"schema":{"type":"string","title":"Member Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/transforms":{"get":{"tags":["Transforms"],"summary":"List Transforms","description":"List all available time-series transforms with descriptions.","operationId":"list_transforms_api_v1_transforms_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/trust":{"get":{"tags":["Trust"],"summary":"Trust Center","operationId":"trust_center_api_v1_trust_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/verify/{run_id}":{"get":{"tags":["Verify"],"summary":"Verify Run","description":"Return the run's ingestion envelope, unaltered.\n\nSame JSON that was written on the day the run completed:\n``{source, connector_version, transform_hash, fetched_at, year_range,\nindicator_count, country_count, quality, normalized: [...]}``. Consumers\ncan grep this for any specific observation they cited.","operationId":"verify_run_api_v1_verify__run_id__get","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/verify/{run_id}/observation":{"get":{"tags":["Verify"],"summary":"Verify Observation","description":"Return the single row this run wrote for `(indicator, country, date)`.\n\nResponse shape::\n\n    {\n        \"run_id\": \"...\",\n        \"requested\": {indicator, country, date, expected_value},\n        \"found\": {indicator_id, country_code, date, value, unit,\n                  source_id, run_id, transform_hash, ingested_at},\n        \"checksum\": \"af38ff77ae5a54ab\",  # 16-char sha256 prefix of value fields\n        \"matches\": true | false | null    # only present when expected_value given\n    }\n\nReturns 404 if the row is not in the run. That is itself a useful\nverification signal — it means the citation is claiming something\nthe run did not produce.","operationId":"verify_observation_api_v1_verify__run_id__observation_get","parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"indicator","in":"query","required":true,"schema":{"type":"string","description":"Indicator ID from the citation","title":"Indicator"},"description":"Indicator ID from the citation"},{"name":"country","in":"query","required":true,"schema":{"type":"string","description":"ISO-2 country code from the citation","title":"Country"},"description":"ISO-2 country code from the citation"},{"name":"date","in":"query","required":true,"schema":{"type":"string","description":"Observation date (YYYY-MM-DD or YYYY)","title":"Date"},"description":"Observation date (YYYY-MM-DD or YYYY)"},{"name":"expected_value","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"If provided, the response's ``matches`` boolean confirms whether the stored value equals it (within 1e-6).","title":"Expected Value"},"description":"If provided, the response's ``matches`` boolean confirms whether the stored value equals it (within 1e-6)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/watchlist":{"get":{"tags":["Watchlist"],"summary":"Get Watchlist","description":"Get user's watchlist enriched with latest values.","operationId":"get_watchlist_api_v1_watchlist_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Watchlist"],"summary":"Add To Watchlist","description":"Add an indicator+country pair to user's watchlist.","operationId":"add_to_watchlist_api_v1_watchlist_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchlistAddRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/watchlist/{item_id}":{"delete":{"tags":["Watchlist"],"summary":"Remove From Watchlist","description":"Remove an item from user's watchlist.","operationId":"remove_from_watchlist_api_v1_watchlist__item_id__delete","parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts":{"get":{"tags":["Watchlist","Alerts"],"summary":"List Alerts","description":"List user's data alerts.","operationId":"list_alerts_api_v1_alerts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Watchlist","Alerts"],"summary":"Create Data Alert","description":"Create a threshold-based data alert.","operationId":"create_data_alert_api_v1_alerts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/{alert_id}":{"delete":{"tags":["Watchlist","Alerts"],"summary":"Delete Alert","description":"Delete a data alert.","operationId":"delete_alert_api_v1_alerts__alert_id__delete","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","title":"Alert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/check":{"get":{"tags":["Watchlist","Alerts"],"summary":"Check Alerts","description":"Check all user's alerts against current data values.","operationId":"check_alerts_api_v1_alerts_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/webhooks":{"get":{"tags":["Watchlist","Webhooks"],"summary":"List Webhooks","description":"List user's registered webhooks.","operationId":"list_webhooks_api_v1_webhooks_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["Watchlist","Webhooks"],"summary":"Register Webhook","description":"Register a webhook to be called when an alert condition is met.","operationId":"register_webhook_api_v1_webhooks_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/{webhook_id}":{"delete":{"tags":["Watchlist","Webhooks"],"summary":"Delete Webhook","description":"Delete a webhook registration.","operationId":"delete_webhook_api_v1_webhooks__webhook_id__delete","parameters":[{"name":"webhook_id","in":"path","required":true,"schema":{"type":"string","title":"Webhook Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AddMemberRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"member"}},"type":"object","required":["email"],"title":"AddMemberRequest"},"AdminAddMemberRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"member"}},"type":"object","required":["email"],"title":"AdminAddMemberRequest"},"AdminCreateOrgRequest":{"properties":{"name":{"type":"string","title":"Name"},"owner_email":{"type":"string","title":"Owner Email"},"tier":{"type":"string","title":"Tier","default":"team"},"seats":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seats"}},"type":"object","required":["name","owner_email"],"title":"AdminCreateOrgRequest"},"AdminGrantTierRequest":{"properties":{"tier":{"type":"string","title":"Tier"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["tier"],"title":"AdminGrantTierRequest"},"AdminSendEmailRequest":{"properties":{"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"reply_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply To"}},"type":"object","required":["subject","body"],"title":"AdminSendEmailRequest"},"AdminTransferOwnershipRequest":{"properties":{"new_owner_email":{"type":"string","title":"New Owner Email"}},"type":"object","required":["new_owner_email"],"title":"AdminTransferOwnershipRequest"},"AdminUpdateOrgRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"seats":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seats"},"billing_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Billing Status"},"stripe_customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Customer Id"},"stripe_subscription_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe Subscription Id"}},"type":"object","title":"AdminUpdateOrgRequest"},"AdminUpdateUserRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"}},"type":"object","title":"AdminUpdateUserRequest"},"AgentAccountAccess":{"properties":{"account_required":{"const":true,"title":"Account Required","default":true},"authenticated":{"const":true,"title":"Authenticated","default":true},"tier":{"type":"string","enum":["free","pro","team","enterprise"],"title":"Tier"},"plan_name":{"type":"string","title":"Plan Name"},"quota":{"$ref":"#/components/schemas/AgentQuota"},"account_url":{"type":"string","title":"Account Url","default":"https://africadb.com/dashboard"},"upgrade_url":{"type":"string","title":"Upgrade Url","default":"https://africadb.com/pricing"}},"type":"object","required":["tier","plan_name","quota"],"title":"AgentAccountAccess"},"AgentInterfaceManifest":{"properties":{"name":{"type":"string","title":"Name","default":"Africa Data Bank"},"version":{"type":"string","title":"Version","default":"1.0.0"},"description":{"type":"string","title":"Description"},"canonical_api":{"type":"string","title":"Canonical Api"},"openapi":{"type":"string","title":"Openapi"},"mcp_registry_name":{"type":"string","title":"Mcp Registry Name"},"authentication":{"type":"object","title":"Authentication"},"safety":{"type":"object","title":"Safety"},"tools":{"items":{"$ref":"#/components/schemas/AgentToolDescriptor"},"type":"array","title":"Tools"}},"type":"object","required":["description","canonical_api","openapi","mcp_registry_name","authentication","safety","tools"],"title":"AgentInterfaceManifest"},"AgentQueryRequest":{"properties":{"question":{"type":"string","maxLength":500,"minLength":2,"title":"Question","description":"Plain-English question about African data. Examples: \"What's the GDP of Kenya?\" or \"Compare inflation in Nigeria and South Africa\" or \"Which African country has the highest life expectancy?\""},"max_countries":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Max Countries","default":5}},"type":"object","required":["question"],"title":"AgentQueryRequest"},"AgentQueryResponse":{"properties":{"ok":{"type":"boolean","title":"Ok","default":true},"question":{"type":"string","title":"Question"},"answer":{"type":"string","title":"Answer"},"indicator":{"anyOf":[{"$ref":"#/components/schemas/ResolvedIndicator"},{"type":"null"}]},"countries":{"items":{"$ref":"#/components/schemas/ResolvedCountry"},"type":"array","title":"Countries"},"rows":{"items":{"$ref":"#/components/schemas/AnswerRow"},"type":"array","title":"Rows"},"citations":{"additionalProperties":{"type":"string"},"type":"object","title":"Citations"},"grounded":{"type":"boolean","title":"Grounded","default":true},"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"diagnostics":{"type":"object","title":"Diagnostics"}},"type":"object","required":["question","answer"],"title":"AgentQueryResponse"},"AgentQuota":{"properties":{"limit_per_day":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit Per Day"},"used_today":{"type":"integer","title":"Used Today"},"remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining"},"reset_at_epoch":{"type":"integer","title":"Reset At Epoch"}},"type":"object","required":["limit_per_day","used_today","remaining","reset_at_epoch"],"title":"AgentQuota"},"AgentToolDescriptor":{"properties":{"name":{"type":"string","title":"Name"},"purpose":{"type":"string","title":"Purpose"},"rest_endpoint":{"type":"string","title":"Rest Endpoint"},"provenance_expected":{"type":"boolean","title":"Provenance Expected","default":true}},"type":"object","required":["name","purpose","rest_endpoint"],"title":"AgentToolDescriptor"},"AlertCreateRequest":{"properties":{"indicator_id":{"type":"string","title":"Indicator Id"},"country_code":{"type":"string","title":"Country Code"},"condition":{"type":"string","title":"Condition"},"threshold":{"type":"number","title":"Threshold"}},"type":"object","required":["indicator_id","country_code","condition","threshold"],"title":"AlertCreateRequest"},"AnswerRow":{"properties":{"country_code":{"type":"string","title":"Country Code"},"country_name":{"type":"string","title":"Country Name"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Year"},"unit":{"type":"string","title":"Unit","default":""},"source_id":{"type":"string","title":"Source Id","default":""},"run_id":{"type":"string","title":"Run Id","default":""},"verify_url":{"type":"string","title":"Verify Url","default":""}},"type":"object","required":["country_code","country_name","value","year"],"title":"AnswerRow"},"AskRequest":{"properties":{"question":{"type":"string","title":"Question"}},"type":"object","required":["question"],"title":"AskRequest"},"Body_upload_my_dataset_file_api_v1_partners_me_datasets__dataset_id__upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_my_dataset_file_api_v1_partners_me_datasets__dataset_id__upload_post"},"CategoryOverride":{"properties":{"category":{"type":"string","title":"Category"}},"type":"object","required":["category"],"title":"CategoryOverride"},"ChangePasswordRequest":{"properties":{"current_password":{"type":"string","title":"Current Password"},"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["current_password","new_password"],"title":"ChangePasswordRequest"},"CheckoutRequest":{"properties":{"tier":{"type":"string","title":"Tier"},"interval":{"type":"string","title":"Interval","default":"month"}},"type":"object","required":["tier"],"title":"CheckoutRequest"},"ClosePayoutRequest":{"properties":{"period_start":{"type":"string","format":"date","title":"Period Start"},"period_end":{"type":"string","format":"date","title":"Period End"}},"type":"object","required":["period_start","period_end"],"title":"ClosePayoutRequest"},"CommunityJoinRequest":{"properties":{"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"},"email":{"type":"string","title":"Email"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"use_case":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Use Case"},"heard_from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Heard From"},"heard_from_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Heard From Detail"},"company_website_hp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Website Hp"}},"type":"object","required":["first_name","last_name","email"],"title":"CommunityJoinRequest","description":"Community sign-up form (Discord invite + newsletter + events)."},"ContactRequest":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"topic":{"type":"string","title":"Topic","default":"general"},"message":{"type":"string","title":"Message"},"organization":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization"},"company_website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Website"}},"type":"object","required":["name","email","message"],"title":"ContactRequest"},"CreateDatasetRequest":{"properties":{"slug":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]?$","title":"Slug"},"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"category":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"},"unit_price_cents":{"type":"integer","minimum":0.0,"title":"Unit Price Cents","default":0},"access_policy":{"type":"string","pattern":"^(public|beta|paid)$","title":"Access Policy","default":"public"}},"type":"object","required":["slug","title"],"title":"CreateDatasetRequest"},"CreateKeyRequest":{"properties":{"name":{"type":"string","title":"Name","default":"Default Key"}},"type":"object","title":"CreateKeyRequest"},"CreatePartnerRequest":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"contact_email":{"type":"string","format":"email","title":"Contact Email"},"revenue_share_bps":{"type":"integer","maximum":10000.0,"minimum":0.0,"title":"Revenue Share Bps","default":7000}},"type":"object","required":["name","contact_email"],"title":"CreatePartnerRequest"},"CreateTeamRequest":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"CreateTeamRequest"},"DataRequestBody":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"organization":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization"},"dataset_title":{"type":"string","title":"Dataset Title"},"countries":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Countries"},"sector":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sector"},"indicators":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Indicators"},"time_range":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Range"},"use_case":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Use Case"},"urgency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Urgency"},"company_website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Website"}},"type":"object","required":["name","email","dataset_title"],"title":"DataRequestBody","description":"Public \"we're missing this data\" form.\n\nStructured so admin can triage a queue of requests by country /\nindicator / sector rather than reading free-text messages. The\nfields mirror the search filters on the observations UI so a\nsubmitted request maps cleanly to what a fulfiller would look for."},"EnterpriseContactRequest":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","title":"Email"},"organization":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organization"},"use_case":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Use Case"},"company_website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Website"}},"type":"object","required":["name","email"],"title":"EnterpriseContactRequest"},"EventIn":{"properties":{"name":{"type":"string","title":"Name"},"path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Path"},"referrer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referrer"},"properties":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Properties"}},"type":"object","required":["name"],"title":"EventIn"},"FirebaseExchangeRequest":{"properties":{"id_token":{"type":"string","minLength":100,"title":"Id Token","description":"Firebase ID token obtained client-side via signInWithPopup (google.com provider) or one of the phone/apple flows."}},"type":"object","required":["id_token"],"title":"FirebaseExchangeRequest"},"ForgotPasswordRequest":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"ForgotPasswordRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoginRequest":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"LoginRequest"},"MCPAuditEvent":{"properties":{"tool":{"type":"string","maxLength":100,"minLength":1,"title":"Tool"},"outcome":{"type":"string","pattern":"^(success|error)$","title":"Outcome"},"duration_ms":{"type":"integer","maximum":600000.0,"minimum":0.0,"title":"Duration Ms"},"metadata":{"type":"object","title":"Metadata"}},"type":"object","required":["tool","outcome","duration_ms"],"title":"MCPAuditEvent"},"OrderBody":{"properties":{"partner_id":{"type":"string","title":"Partner Id"},"dataset_slug":{"type":"string","title":"Dataset Slug"}},"type":"object","required":["partner_id","dataset_slug"],"title":"OrderBody"},"OrgAcceptInviteRequest":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"OrgAcceptInviteRequest"},"OrgInviteRequest":{"properties":{"email":{"type":"string","title":"Email"},"role":{"type":"string","title":"Role","default":"member"}},"type":"object","required":["email"],"title":"OrgInviteRequest"},"RecordEventRequest":{"properties":{"kind":{"type":"string","pattern":"^(view|download|api_call)$","title":"Kind"},"actor_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Actor Email"},"bytes":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Bytes"}},"type":"object","required":["kind"],"title":"RecordEventRequest"},"RefreshRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshRequest"},"ResetPasswordRequest":{"properties":{"token":{"type":"string","title":"Token"},"password":{"type":"string","title":"Password"}},"type":"object","required":["token","password"],"title":"ResetPasswordRequest"},"ResolvedCountry":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["code","name"],"title":"ResolvedCountry"},"ResolvedIndicator":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"unit":{"type":"string","title":"Unit","default":""},"source_label":{"type":"string","title":"Source Label","default":""},"freshness_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Freshness Status"}},"type":"object","required":["id","name"],"title":"ResolvedIndicator"},"SelfCreateOrgRequest":{"properties":{"name":{"type":"string","title":"Name"},"seats":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Seats"}},"type":"object","required":["name"],"title":"SelfCreateOrgRequest"},"SenderConfig":{"properties":{"name":{"type":"string","title":"Name"},"title":{"type":"string","title":"Title","default":""},"email":{"type":"string","title":"Email","default":""}},"type":"object","required":["name"],"title":"SenderConfig"},"SetPasswordRequest":{"properties":{"new_password":{"type":"string","title":"New Password"}},"type":"object","required":["new_password"],"title":"SetPasswordRequest","description":"First-time password set for a user who signed up via an OAuth\nprovider (Google today, more later). Never accepts a\n`current_password` — that's what /auth/change-password is for.\nOnce a password exists on the account, this endpoint 409s and\nthe user must go through the change flow instead."},"SignupRequest":{"properties":{"email":{"type":"string","title":"Email"},"password":{"type":"string","title":"Password"},"name":{"type":"string","title":"Name"},"company":{"type":"string","title":"Company","default":""},"recaptcha_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recaptcha Token"}},"type":"object","required":["email","password","name"],"title":"SignupRequest"},"StatusUpdate":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"StatusUpdate"},"SubscribeBody":{"properties":{"tier":{"type":"string","title":"Tier"},"interval":{"type":"string","title":"Interval","default":"month"}},"type":"object","required":["tier"],"title":"SubscribeBody"},"UnsubscribeRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"UnsubscribeRequest"},"UpdateDatasetRequest":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Title"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"category":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Category"},"unit_price_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Unit Price Cents"},"access_policy":{"anyOf":[{"type":"string","pattern":"^(public|beta|paid)$"},{"type":"null"}],"title":"Access Policy"},"status":{"anyOf":[{"type":"string","pattern":"^(draft|published|retired)$"},{"type":"null"}],"title":"Status"}},"type":"object","title":"UpdateDatasetRequest"},"UpdatePartnerStatusRequest":{"properties":{"status":{"type":"string","pattern":"^(pending|active|suspended)$","title":"Status"}},"type":"object","required":["status"],"title":"UpdatePartnerStatusRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WatchlistAddRequest":{"properties":{"indicator_id":{"type":"string","title":"Indicator Id"},"country_code":{"type":"string","title":"Country Code"}},"type":"object","required":["indicator_id","country_code"],"title":"WatchlistAddRequest"},"WebhookRequest":{"properties":{"indicator_id":{"type":"string","title":"Indicator Id"},"country_code":{"type":"string","title":"Country Code"},"condition":{"type":"string","title":"Condition"},"threshold":{"type":"number","title":"Threshold"},"webhook_url":{"type":"string","title":"Webhook Url"}},"type":"object","required":["indicator_id","country_code","condition","threshold","webhook_url"],"title":"WebhookRequest"}}}}