Solutions

Six ways to use data you do not maintain.

Any dataset, however different its content, ends up doing one of a few things inside your product: confirming, suggesting, completing, calculating, grouping, or saying how things were.

This page is about those six shapes. Which dataset solves yours, you pick from the catalog.

The anatomy of any responseidentical across the catalog
GET /{modul}/v1/{resursă}?pagina=1
Authorization: Bearer …

{
  "data":  // the only thing that differs between datasets
  "meta":  // total, pagination, data age
  "links": // the next page, if there is one
}
What you learn once
Authenticationone token
Error formatthe same everywhere
Paginationthe same parameters
Limitsin the headers
Versioningper module
New moduleno new code
01 What you solve

Six shapes. The rest are combinations.

They apply to every dataset in the catalog and to every one still to come. If you recognise one of them in your product, you already have the use case.

A Validation

You confirm that a value the user entered really exists in the official set and is what it claims to be. The check happens at entry, while fixing it costs a click — not later, when it costs something else.

B Suggestion

The field offers results as the user types, from an official set rather than a static list kept locally. What lands in your database is a value chosen from a closed set, not free text.

C Completion

One identifier brings the rest of the information with it. The user types less, the data goes in spelled correctly from the start, and you stop cleaning downstream what was entered wrong upstream.

D Calculation

Sometimes you do not need the record, you need the result. The response arrives already calculated, with the rules applied correctly, so you do not reimplement logic you would then have to keep current.

E Grouping

Reports are built on stable codes, not on hand-typed names. Three spellings of the same thing land on the same row, because you are no longer comparing strings.

F Point-in-time queries

Not just how it is now, but how it was on a given date. For any decision that has to be justified later, the right question is what was true then, not what is true today.

Modifier

Any of them, in bulk.

You send many values in one call instead of one call each. A scheduled job that runs your whole database through the catalog costs tens of requests, not tens of thousands — that is the difference between a monthly check and a daily one.

02 Composition

A useful answer is usually two calls.

The datasets are independent but linked by codes. One result becomes the next call’s parameter, and the real question gets answered without you keeping anything locally.

1 dataset A

You query the set that holds the identifier

You get the full record with all its fields — including the codes that link it to other datasets.

GET /{module-a}/v1/{resource}/{id}
2 from the response

You take the linking code from the response

It is an ordinary field, documented in the module schema. Nothing to build, guess or normalise.

"data": { …, "cod_legatura": … }
3 dataset B · from cache

You use it as a parameter in the second set

The second call is almost always served from cache, so the real cost of composing is negligible.

GET /{module-b}/v1/{resource}?cod=…
Why it matters

Without composition you would have two integrations that do not talk to each other, and you would have to build the bridge yourself — exactly the work you are trying to avoid.

It is not mandatory

You can use a single dataset and ignore the rest of the catalog; nothing forces you to adopt more than you need. But when you do need it, the link is already there.

Got a chain you are not sure about? Tell us what you are trying to find out and we will send you the cheapest version in requests.

Ask us
03 Who it is for

Teams that depend on data someone else maintains.

The same six shapes, seen from the angle of a few kinds of product.

Business software

Fields fill in from an identifier, and whatever the user enters is confirmed before it reaches a document.

Completion Validation
Online retail and marketplaces

Values chosen from suggestions instead of typed freely: fewer blocked orders and reports that need no manual cleanup.

Suggestion Grouping
Financial services

Checks at onboarding, calculations on official data, and the ability to show what was true at the moment of the decision.

Validation Point-in-time queries
Logistics and operations

Values normalised onto stable codes before planning, aggregations on the same official hierarchy as the reports.

Grouping Validation
Consumer apps

A search, a suggestion, a calculated total — simple features resting on a dataset nobody wants to maintain.

Suggestion Calculation
Data and analytics teams

Dimensions normalised ready for the warehouse, with codes that do not shift between runs. Reproducible joins.

Grouping Point-in-time queries
Integrators and agencies

One integration layer, reused across every client. Per-module versioning means an upgrade does not touch the rest.

All six
Which dataset solves your case?

Every module has its own page, with the endpoints, the schema and its specific cases.

See the catalog →
04 The real cost

The cost is not the integration. It is the upkeep.

An import gets written in an afternoon. The trouble starts in month four, when the source changes its format on a Friday evening.

With your own importrecurring cost
A cron job that downloads a file and hopes the format has not changed.
Normalisation code written twice, in two places, slightly differently.
The source’s limits, handled with fixed pauses and crossed fingers.
A local table that falls behind after every upstream change.
No trace of what a field held six months ago.
A colleague who “knows how the import works” and is on holiday.
With oneapione integration
An HTTP client and a token. No mandatory SDK.
The data arrives normalised before you touch it.
The limit, what is left and when it resets, in the headers of every response.
Upstream changes show up in the changelog, not in a production incident.
History is a query, not something you should have saved.
The contract is documented publicly. Anyone on the team can read it.
Milliseconds

Most responses come from cache, not from the database.

304

With conditional validation you spend no quota when the data has not changed.

12 months

How long an old module version stays active, at minimum, after the announcement.

05 Integration

One token and the HTTP client you already have.

You install nothing. If you want a typed client, you generate it from the module’s OpenAPI spec, in your language.

# any module, the same shape
curl "https://oneapi.ro/api/{module}/v1/{resource}" \
  -H "Authorization: Bearer $ONEAPI_TOKEN" \
  -H "Accept: application/json"

# second time round, nothing off your quota
curl "https://oneapi.ro/api/{module}/v1/{resource}" \
  -H "Authorization: Bearer $ONEAPI_TOKEN" \
  -H 'If-None-Match: "a3f9c1e0"'
# → 304 Not Modified
use Illuminate\Support\Facades\Http;

// one client, reused for every module
$oneapi = Http::baseUrl('https://oneapi.ro/api')
    ->withToken(config('services.oneapi.token'))
    ->acceptJson()
    ->retry(2, 200);

$result = $oneapi
    ->get("/{$module}/v1/{$resource}", ['pagina' => 1])
    ->throw()
    ->json('data');
const oneapi = async (path, init = {}) => {
  const res = await fetch(`https://oneapi.ro/api${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.ONEAPI_TOKEN}`,
      Accept: 'application/json',
      ...init.headers,
    },
  });
  // the same rate-limit handling, whichever module it is
  if (res.status === 429) {
    const wait = Number(res.headers.get('Retry-After')) * 1000;
    await new Promise((r) => setTimeout(r, wait));
    return oneapi(path, init);
  }
  return res.json();
};
import os
import httpx

client = httpx.Client(
    base_url="https://oneapi.ro/api",
    headers={"Authorization": f"Bearer {os.environ['ONEAPI_TOKEN']}"},
    timeout=5.0,
)

# the same function, any module
def fetch(module: str, resource: str, **params) -> list:
    r = client.get(f"/{module}/v1/{resource}", params=params)
    r.raise_for_status()
    return r.json()["data"]
When something goes wrong

One error shape, across the whole catalog.

The code is stable and documented, the message is for a human, the field tells you which parameter to fix, and the request id is what you send us if you need help.

HTTP/1.1 422 Unprocessable Content
{ "error": {
    "cod": "parametru_invalid",
    "mesaj": "The value is not accepted.",
    "camp": "…",
    "request_id": "req_01JZQ8M2"
} }
06 Questions

Before you write the first request.

The rest, in the frequently asked questions and in the documentation.

Yes. The consoles on the module pages run real requests, without authentication, with a small per-minute limit. For real volume you need a token, and the free plan does not ask for a card.

From new account to first response, in minutes. 3.000 requests a month, the whole catalog, no card.
Generate a token View the documentation