Developers

The Business.co.za API

Everything the window shows, as JSON: 28 endpoints across the directory, news and trends, the economy, open data, Ask a pro, your own account and the Partner Network. Read-only endpoints work without a key.

Keys and scopes

Create keys in your dashboard. Send one as a bearer token:

curl https://www.business.co.za/api/v1/businesses?industry=construction&city=Durban \
  -H "Authorization: Bearer bcz_xxxxxxxx_…"
ScopeGivesWho can have it
public:readThe directory, news, trends, economy, calendar, data, questionsEveryone — also without a key
data:readOpen datasets at the higher limitAny member
me:read / me:writeYour follows, feed and notifications; follow, unfollow, switch alertsAny member, for their own account
partner:read / partner:writeRequests routed to your business, replies and quotes, webhooksOwners and managers of that business
contacts:readPhone numbers and email addresses on business recordsGranted by Business.co.za staff only, for a stated purpose (POPIA)

Limits

  • Without a key: 60 requests a minute per address.
  • With a key: 120 requests a minute per key (raised on request). Usage per day is shown in your dashboard.
  • Lists take limit (1–100) and return next; pass it back as cursor. The feed pages by before.
  • Over the limit: 429 with Retry-After.

Errors

HTTP/1.1 403
{ "error": { "code": "missing_scope", "message": "This needs a key with the partner:read scope." } }

Codes: bad_key 401 · missing_scope 401/403 · not_found 404 · rate_limited 429 · bad_json 400 · too_large 413 · server_error 500.

Directory

GET/api/v1/businessespublic:read

Businesses on the directory, best-established first. Phone and email need the contacts:read scope.

  • industry — industry slug
  • service — service slug
  • city — town or city
  • q — name contains
  • limit — 1–100 (25)
  • cursor — from the previous page's next

GET/api/v1/businesses/:slugpublic:read

One business: profile, industries, services and per-service ratings.

GET/api/v1/searchpublic:read

Search businesses, guides and news in plain words — the site's own engine.

  • q — what you are looking for, e.g. accountant in Cape Town

GET/api/v1/industriespublic:read

Every industry with the number of listed businesses.

GET/api/v1/industries/:slugpublic:read

An industry's dossier: counts, leaders (with the reasons), what it offers, where, and news coverage.

GET/api/v1/servicespublic:read

Every service with the number of businesses offering it.

GET/api/v1/services/:slugpublic:read

A service: who is rated best for it (3+ ratings), where it is offered, and coverage.

Economy & data

GET/api/v1/indicatorspublic:read

Repo and prime, CPI, petrol, unemployment, GDP and the rand — each with its period and official source.

GET/api/v1/calendarpublic:read

SARS and business deadlines between two dates (default: the next 90 days).

  • from — YYYY-MM-DD
  • to — YYYY-MM-DD (max one year after from)

GET/api/v1/datasets/:keypublic:read

An open dataset (industries, provinces, services, indicators, news-trends). CC BY 4.0.

GET/api/v1/reports/:monthpublic:read

The State of South African Business for a month (YYYY-MM, or 'current').

Ask a pro

GET/api/v1/questionspublic:read

Questions people asked, newest first, with topics and status.

  • topic — service or industry slug
  • filter — open | solved

GET/api/v1/questions/:idpublic:read

One question with its answers.

You

GET/api/v1/me/followsme:read

Everything you follow, and whether alerts are on for each.

POST/api/v1/me/followsme:write

Follow something. Never turns alerts on. Body: { type, id } or { type: 'topic', term }.

DELETE/api/v1/me/followsme:write

Unfollow. Body: { type, id }.

POST/api/v1/me/follows/alertsme:write

Turn alerts on or off for something you follow — the only way alerts change. Body: { type, id, on }.

GET/api/v1/me/feedme:read

Your feed: everything the things you follow produced, newest first, unlimited by paging.

  • only — business | user | industry | service | group | topic
  • before — ISO time from the last item

GET/api/v1/me/notificationsme:read

Your notifications — only the ones you opted into, plus replies and mentions.

Partners

GET/api/v1/partner/profilepartner:read

The business this key acts for and the modules it partners on.

GET/api/v1/partner/requestspartner:read

Requests routed to your business, newest first. The asker's name and email come with consent.

  • status — sent | viewed | quoted | declined | won | lost

POST/api/v1/partner/requests/:id/respondpartner:write

Reply to a request, with an optional quote. Body: { message, quote_cents }. The person is told once.

POST/api/v1/partner/requests/:id/statuspartner:write

Mark a request viewed, declined, won or lost. Body: { status }.

GET/api/v1/partner/webhookspartner:read

Your webhooks.

POST/api/v1/partner/webhookspartner:write

Register an https webhook for request.created / request.updated. Returns the signing secret once.

DELETE/api/v1/partner/webhooks/:idpartner:write

Disable a webhook.

Webhooks

Partners can have requests pushed the moment they arrive. Register an https URL in the workspace (Requests) or with POST /api/v1/partner/webhooks. Each delivery carries a signature you should verify:

X-BusinessCoZa-Signature: t=1792000000,v1=5f2c…

// Node
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;   // 5-minute window
  const want = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(want), Buffer.from(v1));
}

Events: request.created, request.updated. Webhook URLs must be public https addresses.

Terms

  • Credit “Business.co.za” where you show our data. Open datasets are CC BY 4.0.
  • Do not use the API to contact people or businesses in bulk, or to rebuild the directory elsewhere.
  • Personal details reached through partner:* are for answering that request only.
  • Security problem? security.txt.