Data model
Understand company API records, employment context and the separate ownership of personal wallets.
Everything in the Kua API hangs off a single company — the one that owns your API key. You never see or touch another business’s data.
The core objects
Your business. The API key is scoped to exactly one company; every object in this public company API is filtered to that company. Personal identity and wallet ownership are separate.
An employment classification or template (for example Full-time or Contractor). Statutory treatment follows the employee’s authoritative salary/profile settings, company policy and country requirements; the label alone does not switch deductions on or off.
A person on your payroll, tied to an employment type.
A month’s payroll for the company, built from the current roster. Draft preparation is separate from approval, disbursement and individual line outcomes; a partially disbursed run is not fully paid.
Company funding and personal wallets have different owners. Personal wallets belong to a person and currency, not to one employer. The public SDK has no general wallet-management routes.
An immutable record of something that happened (a run disbursed, an employee
was added). Delivered via webhooks and queryable at /v1/events.
How they relate
Company
├── Employment types
├── Employees ───────────── (each references an employment type)
├── Payroll runs ────────── (built from the roster of active employees)
│ └── authorised settlement can credit a person-and-currency wallet
├── Company funding context (separate from personal wallet ownership)
└── Events ──────────────── (emitted as things happen → webhooks)
Identifiers
Company API records use stable id values (UUID strings). IDs are safe to store and
reference. Timestamps are ISO-8601 in UTC (e.g. 2026-07-25T10:30:00+00:00), and
money fields must be interpreted using the specific resource schema and currency. Fields named amountMinor or toSalaryMinor use that currency’s minor units; do not infer a currency from a sample.
The payroll lifecycle
Creating a run gives you a draft — nothing moves money yet. Approval and
disbursement are deliberate, separate steps (handled in the dashboard or via
owner-gated flows), so an API integration can prepare payroll without being able
to release funds on its own. You observe each transition through
events: payroll.run.hr_approved, payroll.run.disbursed,
and so on.
Test mode
A kua_test_… key supports isolated employee creation and payroll draft/list
operations; it is not a sandbox mirror of every API. Payroll listing needs
payroll:read and returns only Test runs. Test records auto-purge after 14 days.
POST /v1/test-data/clear requires test-data:clear (or *) for API keys; either
Live or Test keys may clear only their own company’s Test records.
Events, leave, advances and performance have no isolated Test partition. Their ten
read routes return 409 TEST_MODE_UNSUPPORTED to sufficiently scoped Test keys.
Existing unsupported add-on writes and the independent webhook mode gate retain
400 TEST_MODE_UNSUPPORTED; * does not bypass either restriction. For events/add-on reads, missing scopes
return 403 INSUFFICIENT_SCOPE first. Do not substitute a Live key just to run a
Test-data example. See the scope and upgrade contract.
Use the public boundary
The public SDK creates employee records and payroll drafts and can observe events. Employment-type setup, salary changes, payroll approval/payment, personal wallet actions and employer-context selection use their authorised product flows. A promotion record does not update salary automatically. Do not infer a public execution route from an event name.
Done when: your integration stores IDs with company and key mode, treats personal identity/wallet ownership separately from employment, and distinguishes Draft, queued, partial and settled outcomes. Continue with API coverage.