Authenticate and make your first request
Get a key, set the one header every endpoint needs, call the API, and read what comes back when something is wrong.
Last updated
Everything in the Business Radar API sits behind one API key and one header. This guide gets you from “no key” to a successful response, and shows what a failure looks like so you can tell an expired key from a typo in a path.
Before you start
- An API key. Request one from support@businessradar.com.
- A place to keep it. The key is a secret — it belongs in an environment variable on a server, never in browser code or a committed file.
- Optionally, a client library. Python, TypeScript and PHP clients are
listed on Client libraries; each reads
BUSINESSRADAR_API_KEYfrom the environment on its own.
Step 1: Get a key and store it
Keys are issued by hand: email support@businessradar.com and say which environment you need one for. The schema names the same address, so there is no self-service key page to look for.
Once you have the key, export it in your shell for the examples below, and use your usual secret manager in production.
export BUSINESSRADAR_API_KEY="your-api-key"
Step 2: Send it on every request
The base URL is https://api.businessradar.com and every endpoint lives under
/ext/v3. Authentication is a single header:
Authorization: Bearer <token>
That is the exact form the OpenAPI schema documents for the tokenAuth scheme
(type: http, scheme: bearer). There is no cookie, no session and no refresh
step — the same header goes on every call.
Step 3: Make a call
GET /ext/v3/portfolios is the cheapest authenticated endpoint in the API — a
short list, no filters required — which makes it the fastest way to prove a key
works.
List portfolios
curl -sS https://api.businessradar.com/ext/v3/portfolios \
-H "Authorization: Bearer $BUSINESSRADAR_API_KEY"import os
from businessradar import BusinessRadar
client = BusinessRadar(api_key=os.environ["BUSINESSRADAR_API_KEY"])
page = client.portfolios.list()
for portfolio in page.results:
print(portfolio.external_id, portfolio.name)import BusinessRadar from '@businessradar/businessradar';
const client = new BusinessRadar({ apiKey: process.env['BUSINESSRADAR_API_KEY'] });
const page = await client.portfolios.list();
for (const portfolio of page.results) {
console.log(portfolio.external_id, portfolio.name);
}<?php
use Businessradar\Client;
$client = new Client(apiKey: getenv('BUSINESSRADAR_API_KEY'));
$page = $client->portfolios->list();
foreach ($page->getItems() as $portfolio) {
echo $portfolio->external_id, ' ', $portfolio->name, PHP_EOL;
}What you get
Every list endpoint returns the same envelope: the rows in results, a
total_results count for the whole query, and a next_key cursor that is
null on the last page.
{
"total_results": 2,
"next_key": null,
"results": [
{
"external_id": "6f1d0b8e-3a1e-4d25-9a54-0b1b2f2f8c10",
"name": "Suppliers EU",
"customer_reference": "erp-suppliers-eu",
"default_permission": "view_only"
},
{
"external_id": "b3b1f8f3-6a15-4a56-8f9a-2c3e9a1f7d44",
"name": "Key accounts",
"customer_reference": null,
"default_permission": "write"
}
]
}
To walk a long list, pass the next_key you were given back as a query
parameter and repeat until it comes back null. The clients do this for you —
iterating the page object fetches further pages as needed.
Page through results
curl -sS "https://api.businessradar.com/ext/v3/portfolios?next_key=eyJvZmZzZXQiOjUwfQ" \
-H "Authorization: Bearer $BUSINESSRADAR_API_KEY"# Iterating the page fetches the next page automatically.
for portfolio in client.portfolios.list():
print(portfolio.name)for await (const portfolio of client.portfolios.list()) {
console.log(portfolio.name);
}<?php
foreach ($client->portfolios->list()->pagingEachItem() as $portfolio) {
echo $portfolio->name, PHP_EOL;
}Step 4: Handle the failures
Errors come back as JSON with the same shapes everywhere in the API.
| Status | Meaning | Body |
|---|---|---|
| 401 | Authentication credentials were not provided, or the key is wrong. | {"detail": "..."} |
| 403 | The key is valid but not permitted to do this. | {"detail": "..."} |
| 404 | No such resource — check the external_id. |
{"detail": "..."} |
| 400 | The request body failed validation. | {"errors": {...}, "non_field_errors": [...]} |
| 429 | You are sending requests faster than your plan allows. | {"detail": "..."} |
| 500 | Something broke on our side. Contact support with the time of the call. | {"detail": "..."} |
A missing or malformed header looks like this:
curl -i -sS https://api.businessradar.com/ext/v3/portfolios
{
"detail": "Authentication credentials were not provided."
}
A rejected body — say a compliance check with no company and no entities — returns the field-level shape instead:
{
"errors": {
"name": ["This field may not be blank."]
},
"non_field_errors": []
}
Rate limits and retries
A 429 means you have exceeded your request rate; the body carries a detail
message and you should back off before trying again.
The official clients already handle this for you. All three retry
connection errors, 408, 409, 429 and 5xx responses twice by default, with
exponential back-off and jitter, and they honour a Retry-After (or
retry-after-ms) header when the response carries one. A RateLimitError /
RateLimitException therefore only reaches your code once the retries are
spent. Change the budget with max_retries (Python), maxRetries (TypeScript
and PHP), per client or per call:
Change the retry budget
client.with_options(max_retries=5).portfolios.list()// Request options are the second argument, after the query.
await client.portfolios.list({}, { maxRetries: 5 });<?php
$client->portfolios->list(requestOptions: ['maxRetries' => 5]);Retrying by hand on top of that only helps for the long pauses — a queue that backs off for minutes, not a loop that hammers the same second.
Catch the errors worth catching
# -f makes curl exit non-zero on 4xx/5xx; -i shows the status line and headers.
curl -fi -sS https://api.businessradar.com/ext/v3/portfolios \
-H "Authorization: Bearer $BUSINESSRADAR_API_KEY" || echo "request failed"import businessradar
try:
page = client.portfolios.list()
except businessradar.AuthenticationError:
print("The API key was rejected (401).")
except businessradar.RateLimitError:
print("429 — back off and retry later.")
except businessradar.APIStatusError as error:
print(error.status_code, error.response)
except businessradar.APIConnectionError as error:
print("The server could not be reached:", error.__cause__)const page = await client.portfolios.list().catch((error) => {
if (error instanceof BusinessRadar.APIError) {
console.log(error.status, error.name);
return undefined;
}
throw error;
});<?php
use Businessradar\Core\Exceptions\APIConnectionException;
use Businessradar\Core\Exceptions\APIStatusException;
use Businessradar\Core\Exceptions\RateLimitException;
try {
$page = $client->portfolios->list();
} catch (RateLimitException $e) {
echo '429 — back off and retry later.', PHP_EOL;
} catch (APIStatusException $e) {
echo $e->getMessage(), PHP_EOL;
} catch (APIConnectionException $e) {
echo 'The server could not be reached.', PHP_EOL;
}The whole thing
Every step above in one file: read the key, walk every page of portfolios, and fail loudly on an authentication problem.
Complete first request
#!/usr/bin/env bash
set -euo pipefail
: "${BUSINESSRADAR_API_KEY:?export your API key first}"
BASE=https://api.businessradar.com/ext/v3
next_key=""
while :; do
url="$BASE/portfolios"
[ -n "$next_key" ] && url="$url?next_key=$next_key"
response=$(curl -fsS "$url" \
-H "Authorization: Bearer $BUSINESSRADAR_API_KEY") || {
echo "request failed — check the key and try again" >&2
exit 1
}
echo "$response" | jq -r '.results[] | "\(.external_id)\t\(.name)"'
next_key=$(echo "$response" | jq -r '.next_key // empty')
[ -z "$next_key" ] && break
doneimport os
import sys
import businessradar
from businessradar import BusinessRadar
client = BusinessRadar(api_key=os.environ["BUSINESSRADAR_API_KEY"])
try:
# The client follows next_key on its own when you iterate the pager.
for portfolio in client.portfolios.list():
print(portfolio.external_id, portfolio.name)
except businessradar.AuthenticationError:
sys.exit("The API key was rejected (401). Check BUSINESSRADAR_API_KEY.")
except businessradar.RateLimitError:
sys.exit("429 — back off and retry later.")
except businessradar.APIStatusError as error:
sys.exit(f"{error.status_code}: {error.response}")import BusinessRadar from '@businessradar/businessradar';
const client = new BusinessRadar({ apiKey: process.env['BUSINESSRADAR_API_KEY'] });
try {
// for await walks every page; no cursor bookkeeping needed.
for await (const portfolio of client.portfolios.list()) {
console.log(portfolio.external_id, portfolio.name);
}
} catch (error) {
if (error instanceof BusinessRadar.APIError) {
console.error(error.status, error.name);
process.exit(1);
}
throw error;
}<?php
require 'vendor/autoload.php';
use Businessradar\Client;
use Businessradar\Core\Exceptions\APIStatusException;
$client = new Client(apiKey: getenv('BUSINESSRADAR_API_KEY'));
try {
// pagingEachItem() requests the next page as you consume the current one.
foreach ($client->portfolios->list()->pagingEachItem() as $portfolio) {
echo $portfolio->external_id, ' ', $portfolio->name, PHP_EOL;
}
} catch (APIStatusException $e) {
fwrite(STDERR, $e->getMessage() . PHP_EOL);
exit(1);
}Next steps
- Run a compliance check on a company — the first thing most integrations do with a key.
- Register a portfolio and receive the right news — bulk registration, webhooks and filtered article feeds.
- Reference: Portfolios, Companies, Compliance, Articles, Webhooks.