Reference Data

10 views Markdown

The seven lookup endpoints turning raw numbers and codes into readable labels.

Overview

The WISECP API returns raw values: a status code, a country number, a currency number. An interface has to turn those into something a person reads, and the dictionary for that sits in these seven endpoints.

The split is deliberate. The resource endpoints stay raw because a label shifts with language and time, while the dictionary stands apart because it rarely moves and can be fetched once and kept.

Three endpoints form the address chain: country, state and city. The chain runs one way, and each step wants the number from the step before.

Reference

The Currencies

get/api/v1/admin/reference/currencies
Reference/GetCurrencies admin

Returns the currencies defined, with their numbers.

Response fields data[] — 4
idintThe currency number. The currency fields on other endpoints carry it.
codestringThe three-letter code.
namestringThe name shown.
is_defaultboolWhether this is the system default.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/currencies' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/reference/currencies', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const byId = Object.fromEntries(data.map((c) => [c.id, c.code]));
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/currencies');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The numbers are NOT ISO numerics: they belong to the installation and differ between them.
$rows = Api::Reference()->GetCurrencies()['data'];
$code = array_column($rows, 'code', 'id');   // [4 => 'USD']

The Countries

get/api/v1/admin/reference/countries
Reference/GetCountries admin

Returns the countries with a number, a code and a translated name.

Query 1
langstringThe language the labels come back in. The panel's current language stands in when it is left out.
Response fields data[] — 3
idintThe country number. The country fields on other endpoints carry it.
codestringThe two-letter country code.
namestringThe country name. It is translated into the language asked for.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/countries?lang=en' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/reference/countries?lang=en', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const name = Object.fromEntries(data.map((c) => [c.id, c.name]));
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/countries?lang=en');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Other endpoints want the COUNTRY NUMBER and not the two-letter code; build the map here.
$rows = Api::Reference()->GetCountries([], ['lang' => 'en'])['data'];
$idOf = array_column($rows, 'id', 'code');   // ['US' => 840]

The States

get/api/v1/admin/reference/states
Reference/GetStates admin

Returns the states of one country.

Query 1
country_idintreqThe country number.
Response fields data[] — 2
idintThe state number.
namestringThe state name.
Errors 2
country_required422No country number was given.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/states?country_id=840' \
  -H "Authorization: Bearer $API_KEY"
const url = new URL('https://panel.example.com/api/v1/admin/reference/states');
url.searchParams.set('country_id', countryId);

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const { data } = await res.json();
if (! data.length) allowFreeText();
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/states?country_id=' . $countryId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// AN EMPTY list is normal: not every country has states, and the address field is free text there.
$states = Api::Reference()->GetStates([], ['country_id' => $countryId])['data'];
$freeText = ! $states;

The Cities

get/api/v1/admin/reference/cities
Reference/GetCities admin

Returns the cities of one state.

Query 1
state_idintreqThe state number.
Response fields data[] — 2
idintThe city number.
namestringThe city name.
Errors 2
state_required422No state number was given.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/cities?state_id=6' \
  -H "Authorization: Bearer $API_KEY"
const url = new URL('https://panel.example.com/api/v1/admin/reference/cities');
url.searchParams.set('state_id', stateId);

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/cities?state_id=' . $stateId);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The chain runs one way: a city wants the country FIRST and then the state number.
$states = Api::Reference()->GetStates([], ['country_id' => $countryId])['data'];
$cities = Api::Reference()->GetCities([], ['state_id' => $states[0]['id']])['data'];

The Languages

get/api/v1/admin/reference/languages
Reference/GetLanguages admin

Returns the languages open to clients, in order.

Response fields data[] — 2
codestringThe language key. This is what goes into the language parameter of other endpoints.
namestringThe name shown for the language.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/languages' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/reference/languages', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
renderLanguagePicker(data);
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/languages');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The OPEN languages alone come back; the language management endpoint shows the closed ones too.
$open = Api::Reference()->GetLanguages()['data'];
$all  = Api::Languages()->GetLanguages()['data'];

The Billing Cycles

get/api/v1/admin/reference/cycles
Reference/GetCycles admin

Pairs the billing cycle codes with the labels people read.

Query 1
langstringThe language the labels come back in. The panel's current language stands in when it is left out.
Response fields data[] — 2
codestringThe cycle code. The order and service endpoints use it.
labelstringThe translated label.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/cycles?lang=en' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/reference/cycles?lang=en', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const label = Object.fromEntries(data.map((c) => [c.code, c.label]));
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/cycles?lang=en');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The list is a LABEL source and not a gate: which cycles a product sells is a separate question.
$labels = array_column(Api::Reference()->GetCycles()['data'], 'label', 'code');
$sold   = Api::Products()->GetProduct(['id' => $pid])['data']['prices'] ?? [];

The Status Codes

get/api/v1/admin/reference/statuses
Reference/GetStatuses admin

Pairs the status codes of one kind of record with their labels.

Query 2
entitystringWhich kind you want: client or product. The client set stands in when it is left out.
langstringThe language the labels come back in. The panel's current language stands in when it is left out.
Response fields data — 2
entitystringThe kind asked for.
statusesobject[]The code and label pairs.
valuestringThe status code.
labelstringThe translated label.
Errors 2
entity_invalid422An unknown kind. The answer's detail gives the list supported.
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/reference/statuses?entity=client&lang=en' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/reference/statuses?entity=client', {
  headers: { Authorization: `Bearer ${apiKey}` },
});

const { data } = await res.json();
const label = Object.fromEntries(data.statuses.map((s) => [s.value, s.label]));
$ch = curl_init('https://panel.example.com/api/v1/admin/reference/statuses?entity=client');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// TWO kinds exist alone: invoice, order and ticket statuses are absent here and sit in their own articles.
$out = Api::Reference()->GetStatuses([], ['entity' => 'client'])['data'];
$map = array_column($out['statuses'], 'label', 'value');

Pitfalls

The numbers belong to the installation and are not universal

A currency number is the installation's own record, and one currency can carry different numbers on two installations. Resolve it from this list rather than writing it into your code. Country numbers follow the same rule: the code travels and the number does not.

An empty state list is not an error

Not every country has states, and the state endpoint returns an empty list for one that does not. An address form should offer free text there rather than a picker. An interface reading the empty list as a failure blocks address entry for those countries outright.

The status list covers two kinds alone

The status endpoint gives the client and product states. Invoice, order, service and ticket states are absent, and their code lists sit in their own articles. Asking for a kind that is unknown gives an error whose detail shows the list supported.

The label language comes with the request and not with the key

With no language parameter the labels come back in the panel's current language. That language can be hard to predict for a background job or a report builder. Always name the language when you mean to keep the result.

Fetch once, keep it, refresh rarely

These lists are not meant to be fetched on every request. Country and city data hardly ever move, while currencies and languages shift when a setting does. Fetching once at start-up and holding the result is quicker and spends none of your quota.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.