My App

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

HeaderDescription
X-Api-KeyYour 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:

PrefixEnvironment
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

  1. Sign in to the BizCARE dashboard.
  2. Open E-Invoicing Settings → Developers → API keys.
  3. Click New API key.
  4. Choose the environment (test or live) — this is required and cannot be changed later.
  5. Give it a name (e.g. "Production integration").
  6. 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.

On this page