Authentication
API key authentication for the BizCARE Books e-Invoicing API
Every request must include an organization API key in the X-Api-Key header.
Required Header
| Header | Description |
|---|---|
X-Api-Key | Your organization's API key (case-insensitive header name) |
Example Request
curl -X GET https://api.bizcare.my/api/v1/companies \
-H "X-Api-Key: biz_test_a1b2c3d4e5f6g7h8i9j0..."Environments — keys are bound to test or live
Each API key is created for exactly one LHDN environment, and the environment is baked into the key prefix:
| Prefix | Environment |
|---|---|
biz_test_… | Sandbox / pre-production |
biz_live_… | Production |
Environment isolation
A test key can never read or write live data, and vice-versa. Every request is
automatically scoped to its key's environment — you don't pass an environment parameter.
Provision one key per environment.
There is no separate publishable key — the API is server-to-server, so every key is a secret.
Obtaining an API Key
- Sign in to the BizCARE dashboard.
- Open E-Invoicing Settings → Developers → API keys.
- Click New API key.
- Choose the environment (
testorlive) — this is required and cannot be changed later. - Give it a name (e.g. "Production integration").
- Copy the key immediately — it is only displayed once.
Keys are scoped to your organization; the user context is derived from the key's organization membership.
Managing API Keys
- Create — generate a new key for a chosen environment, with optional expiry.
- List — view active keys (only a masked preview is shown; the full key is never returned again).
- Revoke — permanently disable a key.
Key Security
Keys are hashed before storage. The full key is shown only at creation. If you lose one, revoke it and create a new one.
Authentication Errors
Auth failures use the standard error envelope — error, its message mirror, and a
machine-readable code (they omit details).
Missing key — 401 (MISSING_API_KEY)
{ "success": false, "error": "Missing X-Api-Key header", "message": "Missing X-Api-Key header", "code": "MISSING_API_KEY" }Invalid, revoked, expired, or disabled key — 401 (INVALID_API_KEY)
{ "success": false, "error": "Invalid API key.", "message": "Invalid API key.", "code": "INVALID_API_KEY" }The message text for a bad key can differ (for example for an expired key). Branch on code, not on the text.
A key that has no environment recorded (an old key) is treated as test.
Key has no owner user — 401 (NO_ORG_USER)
The key's organization has no member the key can act as.
Key owner no longer a member — 403 (NOT_ORG_MEMBER)
{ "success": false, "error": "API key owner is not a member of the organization", "message": "API key owner is not a member of the organization", "code": "NOT_ORG_MEMBER" }Rate Limiting
Each key is rate-limited to 100 requests per 60 seconds. Requests beyond the limit are
rejected with 429 Too Many Requests (code: RATE_LIMITED); back off and retry after the window.
Rate limits may vary by subscription plan — check the dashboard for your thresholds.
Security Best Practices
- Never expose your API key in client-side code. Call the API only from your server.
- Use separate keys per environment (
biz_test_for sandbox,biz_live_for production). - Rotate keys periodically — revoke old keys and generate new ones.
- Store keys in environment variables, never hardcoded.
- Set expiration dates on keys used for temporary integrations.