Skip to content

mode_mismatch

HTTP 403 type: authorization_error param: device_id
{
"error": {
"type": "authorization_error",
"code": "mode_mismatch",
"message": "This is a test key (fh_test_…) but company AWAIT 8 J.D.O.O. is in live mode. Test keys can never reach production tax endpoints.",
"param": "device_id",
"upstream": null,
"doc_url": "https://docs.fiskhub.com/errors/mode_mismatch"
}
}

What happened

The API key’s mode does not match the target company’s mode. An fh_test_ key was used against a company in live mode, or an fh_live_ key against a company in test mode.

Nothing was fiscalized.

Should you retry?

Not with the same key. Either the key or the company is wrong for what you intended.

The fix

Work out which side is wrong.

If you meant to fiscalize for real, use the live key:

Terminal window
curl -sS https://api.fiskhub.com/v1/invoices \
-H "Authorization: Bearer $FISKHUB_LIVE_KEY"

If you meant to test, target a company in test mode. Check which one you hit:

Terminal window
curl -sS "https://api.fiskhub.com/v1/companies" \
-H "Authorization: Bearer $FISKHUB_API_KEY"

Each company’s mode is in the response.

If the company is in the wrong mode — a company that has finished testing and should be live — promote it, which requires a valid certificate:

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" }'

Why the boundary is hard

fh_test_…fh_live_…
Endpointcistest.apis-it.hrcis.porezna-uprava.hr
CertificatesDemoReal
JIRsReal-looking, no legal effectReal fiscal records

There is deliberately no request parameter that switches modes. Swapping the key is the only way.

That is what makes this error valuable. A parameter could be defaulted wrongly in one deployment and file a load-test’s worth of fake sales with the Croatian Tax Administration — or leave a production fleet quietly writing to TEST, producing receipts with no legal standing that nobody notices until an audit. A 403 at the boundary is the cheapest possible version of both problems.

In your own configuration

Keep the two keys in separate variables, not one that changes meaning by environment:

Terminal window
FISKHUB_TEST_KEY=fh_test_…
FISKHUB_LIVE_KEY=fh_live_…

A single FISKHUB_API_KEY whose value depends on the deployment is exactly the ambiguity this error exists to catch — and it catches it at the API, after the deployment has already shipped.