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.
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
}
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.
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.
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.
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.
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.
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.
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.
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.
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.
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}
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": … }
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=…
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.
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 usTeams that depend on data someone else maintains.
The same six shapes, seen from the angle of a few kinds of product.
Fields fill in from an identifier, and whatever the user enters is confirmed before it reaches a document.
Values chosen from suggestions instead of typed freely: fewer blocked orders and reports that need no manual cleanup.
Checks at onboarding, calculations on official data, and the ability to show what was true at the moment of the decision.
Values normalised onto stable codes before planning, aggregations on the same official hierarchy as the reports.
A search, a suggestion, a calculated total — simple features resting on a dataset nobody wants to maintain.
Dimensions normalised ready for the warehouse, with codes that do not shift between runs. Reproducible joins.
One integration layer, reused across every client. Per-module versioning means an upgrade does not touch the rest.
Every module has its own page, with the endpoints, the schema and its specific cases.
See the catalog →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.
Most responses come from cache, not from the database.
With conditional validation you spend no quota when the data has not changed.
How long an old module version stays active, at minimum, after the announcement.
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
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"
} }
Before you write the first request.
The rest, in the frequently asked questions and in the documentation.