{"openapi":"3.1.0","info":{"title":"All Business Africa Public Data API","version":"1.0.0","summary":"Read only access to published African company, capital and procurement data.","description":"A key is not what makes this data reachable. The website's own endpoints, /api/opportunities, /api/businesses, /api/countries and the rest, answer without any credential and always have. What a key buys is a metered allowance that is yours rather than shared with every visitor, a versioned path whose shape will not change under you inside v1, and somebody to write to when it does something you did not expect.\n\nEVERYTHING SERVED HERE IS PUBLISHED. Draft records and soft deleted records are never serialised, because every route below calls the same service the public website calls, with the same visibility rules, rather than querying the tables again with rules of its own.\n\nATTRIBUTION. Anything published from this API must name All Business Africa as the source and link to https://allbusiness.africa. Where a record carries its own source, that source must be named too: this platform aggregates public notices and does not replace the body that issued them.\n\nKEYS ARE ISSUED BY HAND. There is no self service route. Write to data@allbusiness.africa and name the project that needs one.","contact":{"name":"All Business Africa","email":"data@allbusiness.africa","url":"https://allbusiness.africa/developers"}},"servers":[{"url":"https://allbusiness.africa/api/public/v1","description":"Production"}],"security":[{"bearerKey":[]},{"headerKey":[]}],"components":{"securitySchemes":{"bearerKey":{"type":"http","scheme":"bearer","description":"An issued key, beginning \"aba_\", sent as Authorization: Bearer <key>."},"headerKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"The same key, for clients with no bearer field."}},"schemas":{"Paged":{"type":"object","required":["items","total","page","perPage","pageCount","meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"items":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"The records on this page, carrying the same fields the website is served for the same listing."},"total":{"type":"integer","description":"Rows matching the filter, across every page."},"page":{"type":"integer"},"perPage":{"type":"integer","description":"Capped at 100."},"pageCount":{"type":"integer"}}},"Meta":{"type":"object","required":["version","attribution","rateLimit"],"description":"The same four allowance numbers as the X-RateLimit headers, plus the attribution requirement, so a client that never reads a header still knows both.","properties":{"version":{"type":"string"},"attribution":{"type":"string"},"rateLimit":{"type":["object","null"],"description":"Null only on a response served without a key, which no keyed route can be.","properties":{"limit":{"type":"integer"},"usedToday":{"type":"integer"},"remainingToday":{"type":"integer"},"resetsAt":{"type":"string","format":"date-time"}}}}}}},"paths":{"/":{"get":{"summary":"What this API serves, and under what terms.","security":[],"description":"Open without a key on purpose: a developer has to be able to read the terms before asking for one.","responses":{"200":{"description":"The index.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/openapi.json":{"get":{"summary":"This document.","security":[],"responses":{"200":{"description":"The OpenAPI document.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/opportunities":{"get":{"summary":"Funding calls, tenders and programmes.","description":"Defaults to the three types a reader can still act on. Pass type=contract_award for the award archive or type=all for everything.\n\nWHEN THE PLATFORM PAYWALL IS ON, every card in this list loses awardedToName, awardAmount, awardingOrganization, referenceNumber and awardedToRecord, an award card loses minAmount and maxAmount as well because they hold a second copy of the award amount, and summary and organization are masked where they restate a withheld value. The rows themselves are not hidden, none is reordered and the totals do not change: what comes off a card is the product, not the record. The wall is off today, so nothing is withheld and no paywall block is served.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"type","in":"query","schema":{"type":"string"},"description":"funding, tender, program, contract_award, a comma separated list of those, or all."},{"name":"country","in":"query","schema":{"type":"string"},"description":"Country slug."},{"name":"sector","in":"query","schema":{"type":"string"}},{"name":"category","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"},"description":"open, closed, closing_soon, closing_month, cancelled, awarded_completed or all. Each is the same predicate the website filters on, exported from opportunities.module.ts, not a date window written again here."},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"},"description":"newest, oldest, deadline, amount, views or live."}],"responses":{"200":{"description":"A page of opportunities.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/opportunities/{type}/{slug}":{"get":{"summary":"One opportunity.","parameters":[{"name":"type","in":"path","required":true,"schema":{"type":"string","enum":["funding","tender","program","contract_award"]}},{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The record. When the platform paywall is on, the fields it withholds from a signed out reader are absent and a `paywall` block names them. An API key does not lift that wall: a key is a metered allowance, not a membership, and no column on api_keys resolves to a member.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published opportunity of that type with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/contract-awards":{"get":{"summary":"The contract award archive.","description":"The same corpus as /opportunities?type=contract_award, on a path of its own.\n\nWHEN THE PLATFORM PAYWALL IS ON, every card in this list loses awardedToName, awardAmount, awardingOrganization, referenceNumber and awardedToRecord, an award card loses minAmount and maxAmount as well because they hold a second copy of the award amount, and summary and organization are masked where they restate a withheld value. The rows themselves are not hidden, none is reordered and the totals do not change: what comes off a card is the product, not the record. The wall is off today, so nothing is withheld and no paywall block is served.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of awards.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/contract-awards/{slug}":{"get":{"summary":"One contract award.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The award. Walled exactly as /opportunities/contract_award/{slug} is on the website, and an API key does not lift it.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published award with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/buyers":{"get":{"summary":"Public bodies that award contracts.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"q","in":"query","schema":{"type":"string"}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"},"description":"awards, value, recent or name."}],"responses":{"200":{"description":"A page of buyers.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/buyers/{slug}":{"get":{"summary":"One buyer profile.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The buyer. No paywall rule covers buyers, on the website or here, so nothing on this route is withheld even when the wall is up. Note that `recentAwards` carries ten awards per buyer with their winner, amount and reference, which are the same three facts the opportunity listing rule removes, under different names.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No buyer at that slug, or too few awards for a profile.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/companies":{"get":{"summary":"The company directory.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"sector","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of companies.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/companies/{slug}":{"get":{"summary":"One company profile.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The company. Contact fields (email, phone, website, the social links and the address) are withheld when the platform paywall is on, and an API key does not lift that. The entries of the `contractAwards` block are walled on the same terms: each one loses awardAmount, awardingOrganization, referenceNumber and the source links that /contract-awards/{slug} withholds, so a profile cannot hand over in bulk what the award detail withholds one at a time. Measured 2026-09-05: 6,057 published companies carry linked awards and 30,680 award rows are reachable this way.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published company with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/investors":{"get":{"summary":"Capital providers.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"type","in":"query","schema":{"type":"string"}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of investors.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/investors/{slug}":{"get":{"summary":"One investor profile.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The investor. Contact fields (contactEmail, contactPhone, website, linkedin and the address) are withheld when the platform paywall is on, and an API key does not lift that.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published investor with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/countries":{"get":{"summary":"Country profiles.","parameters":[{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"default":1}},{"name":"perPage","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"region","in":"query","schema":{"type":"string"}},{"name":"search","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"},"description":"gdp, population, gdp_growth or title."}],"responses":{"200":{"description":"A page of countries.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Paged"}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/countries/{slug}":{"get":{"summary":"One country, with its indicator series.","description":"The profile the website renders, with the World Bank indicators held against that country attached under `indicators`. Each indicator carries its full series and the latest year that actually carries a measurement, which is not always the latest year present.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The country and its indicators. No paywall rule covers countries.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published country with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}},"/countries/{slug}/indicators":{"get":{"summary":"Only the indicator series for one country.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The indicators.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["meta"],"properties":{"meta":{"$ref":"#/components/schemas/Meta"},"paywall":{"type":"object","description":"Present only when the platform paywall is on AND it withheld something from this record. It names the fields removed, the ungated fields whose prose was masked because it restated a withheld value, and what would unlock them.","properties":{"active":{"type":"boolean"},"ruleId":{"type":"string"},"featureKey":{"type":"string"},"withheldFields":{"type":"array","items":{"type":"string"}},"maskedFields":{"type":"array","items":{"type":"string"}},"withheld":{"type":"string"},"message":{"type":"string"}}}}}}}},"401":{"description":"No key, a key this platform did not issue, or a key that has been revoked. It carries NO X-RateLimit header: there is no key, so there is no daily allowance to describe, and a number under those names would be about the shared burst window rather than about you.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"403":{"description":"A live key whose scope does not carry this resource. It carries this key's own allowance headers, and the refused request is not counted against them.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"404":{"description":"No published country with that slug.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}},"429":{"description":"The daily allowance is spent. The body names the allowance and the moment it resets, and Retry-After carries the seconds until then. A refused request is not counted against the allowance.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"This key's daily allowance."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left today."},"X-RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix seconds at which the allowance resets."},"X-RateLimit-Reset-At":{"schema":{"type":"string","format":"date-time"},"description":"The same moment, ISO 8601."}},"content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string","description":"What was refused, and what to do about it."}}}}}}}}}},"x-resources":[{"key":"opportunities","label":"Opportunities","summary":"Funding calls, tenders and programmes, plus the contract award archive when type=all or type=contract_award is asked for."},{"key":"contract-awards","label":"Contract awards","summary":"Public procurement awards: who bought what, from whom, for how much."},{"key":"buyers","label":"Buyers","summary":"The public bodies behind the awards, with their totals and their categories."},{"key":"companies","label":"Companies","summary":"The company directory: profiles, sectors, countries and contract wins."},{"key":"investors","label":"Investors","summary":"Capital providers held as records of their own, with portfolio and geography."},{"key":"countries","label":"Countries","summary":"Country profiles with the World Bank indicator series held against each one."}],"x-attribution":"Anything published from this API must name All Business Africa as the source and link to https://allbusiness.africa. Where a record carries its own source, that source must be named too: this platform aggregates public notices and does not replace the body that issued them."}