Skip to content

Companies

A company is the fiscal identity. The OIB, the VAT registration status, the signing certificate and the mode all live here, never on the tenant.

That is forced by the regulation rather than chosen: the Tax Administration rejects any message whose payload OIB differs from the signing certificate’s OIB (s005). Each company has its own OIB, so each company needs its own certificate. A tenant with several companies is routine; a tenant with one is just the common case.

List companies

GET /v1/companies
ParameterNotes
statusactive, suspended, archived
limit1–200, default 50
cursorFrom next_cursor
all_tenantsPlatform operators only, session-authenticated. Ignored for everyone else. See cross-tenant listing.
Terminal window
curl -sS https://api.fiskhub.com/v1/companies \
-H "Authorization: Bearer $FISKHUB_API_KEY"
{
"object": "list",
"data": [
{
"id": "3a5f2b18-7c4d-4e91-9a2b-6d8e0f1c3a57",
"name": "AWAIT 8 J.D.O.O.",
"oib": "25089460814",
"vat_registered": true,
"address": { "street": "Ilica 1", "city": "Zagreb", "postal_code": "10000", "country": "HR" },
"fiscal_config": { "sequence_mode": "P" },
"mode": "live",
"status": "active",
"certificate_status": "valid",
"certificate_expires_at": "2028-09-22T12:00:00+02:00",
"created_at": "2026-06-14T08:20:11+02:00"
}
],
"has_more": false,
"next_cursor": null
}
FieldNotes
oib11 digits with an ISO 7064 MOD 11,10 check digit.
vat_registeredUSustPdv.
fiscal_configCountry-specific defaults — sequence mode, tax defaults, endpoint override.
modetest or live. Decides which Tax Administration endpoint is used.
certificate_statusmissing, valid, expiring (under 60 days), expired.
certificate_expires_atWhen the whole fleet stops being able to fiscalize.

Cross-tenant listing

GET /v1/companies?all_tenants=true

FiskHub platform operators — support and operations staff, not customers — can list companies across every tenant. The same parameter works on GET /v1/devices, and nowhere else.

If you are integrating against FiskHub, this section does not apply to you. Nothing about a tenant’s access has changed: a tenant user, with or without this parameter, sees exactly and only their own tenant’s companies. There is no way to opt in, and no way to be opted in by someone else.

The constraints are worth stating plainly, because they are the point of the design:

Constraint
Session onlyThe caller must be an authenticated dashboard session. An API key is never eligible, whatever it is scoped to. A machine credential that could enumerate every customer is a far larger blast radius than a human session.
Platform admin onlyThe user must hold is_platform_admin. This is not a tenant role — no tenant owner or admin has it, and no tenant can grant it.
Read onlyListing, and only these two collections. There is no cross-tenant write path anywhere, and no cross-tenant read of invoices, certificates or users.
Opt in per requestOmitting the parameter gives a platform admin the ordinary tenant-scoped list. Widening every list an operator opens would make it easy to act on the wrong customer’s data by accident.
AuditedEvery cross-tenant read writes an audit_log entry against the operator who made it.

Anyone else sending all_tenants=true gets the ordinary tenant-scoped list. The parameter is ignored, not rejected — there is no error to probe for, and no difference in response shape that would reveal whether the capability exists. The underlying database functions re-check the capability themselves and return zero rows if it is absent, so a route that forgot to check would leak nothing.

The rows are the same Company objects as the tenant-scoped listing, with no added tenant field. Pagination works the same way.

Create a company

POST /v1/companies
FieldTypeRequiredNotes
namestring 1–200yes
oib11 digitsyesChecksum-validated before anything is stored. Must match the certificate you will upload.
vat_registeredbooleannoDefault true.
addressobjectnoDefault {}.
fiscal_configobjectnoDefault {}.
modetest | livenoDefault test.
Terminal window
curl -sS https://api.fiskhub.com/v1/companies \
-H "Authorization: Bearer $FISKHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "AWAIT 8 J.D.O.O.",
"oib": "25089460814",
"vat_registered": true,
"address": { "street": "Ilica 1", "city": "Zagreb", "postal_code": "10000", "country": "HR" },
"mode": "test"
}'

Returns 201 with the company, certificate_status: "missing".

A new company cannot fiscalize yet. It needs a certificate whose subject OIB equals this one and a device with an assigned ISU number.

Errors

StatusCode
400hr.invalid_oib — the checksum failed
400invalid_requestname missing or too long
409invalid_request — a company with this OIB already exists

Update a company

PATCH /v1/companies/{id}

Only the fields present in the body change.

FieldNotes
name
vat_registered
address, fiscal_configReplaced wholesale, not merged.
modeSwitching to live requires a valid certificate.
statusactive, suspended, archived.
Terminal window
curl -sS -X PATCH \
"https://api.fiskhub.com/v1/companies/3a5f2b18-7c4d-4e91-9a2b-6d8e0f1c3a57" \
-H "Authorization: Bearer $FISKHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "mode": "live" }'

Switching to live without a valid certificate returns company_missing_certificate.