Bukku Integration

Bukku Integration #

Bukku is a Malaysian cloud accounting platform. tofu connects to Bukku using an API Access Token and Company Subdomain — there is no OAuth redirect flow.

tofu reads accounting reference data (chart of accounts, contacts, tax rates, and similar settings) and publishes documents back to Bukku: AR invoices (sales/invoices), AP bills (purchases/bills), and direct expenses as payment vouchers (banking/expenses). Publishing is gated by the can_publish capability.

Bukku has no in-place update API in this integration, so republishing an already-published document uses delete-before-publish: tofu deletes (draft) or voids (committed) the existing Bukku document, then creates it again. Because publish is not auto-on, a user can edit an extraction after its Bukku document is paid — so deleting a paid/submitted document is blocked with a “please verify the extraction” message.

Prerequisites #

Before a customer can connect Bukku, confirm the following:

Requirement Details
Bukku account Active Bukku company with API access enabled
Admin access in Bukku User can open Control Panel → Integrations → API Access
Entity permissions User has entity-level integration write permission
No existing accounting integration Each entity supports one accounting integration at a time

Get Bukku API Credentials #

The customer (or support on their behalf) must collect two values from Bukku:

1. Access Token #

  1. Log in to Bukku.
  2. Open Control Panel → Integrations → API Access.
  3. If API Access is disabled, turn it on and save.
  4. Copy the Access Token (treat it like a password — do not share in chat or email).

2. Company Subdomain #

The subdomain is the prefix in the Bukku company URL:

https://{subdomain}.bukku.my

Example: if the URL is https://acme.bukku.my, the subdomain is acme.

Note: Enter only the subdomain prefix (acme), not the full URL or domain suffix.

Official Bukku API reference #

Connect Bukku in tofu #

  1. In tofu, select the target entity.
  2. Go to Entity Settings → Integrations.
  3. Click Add integration and choose Bukku.
  4. Enter:
    • Access Token — from Bukku Control Panel
    • Company Subdomain — from the Bukku URL prefix
  5. Click Connect.

On success:

  • tofu validates credentials against Bukku (GET /contacts with Authorization: Bearer <token> and Company-Subdomain: <subdomain>).
  • A new integration record is created in PENDING status.
  • The connected company subdomain (and base currency when available) is shown in the setup dialog.

Activate the Integration #

After connecting, the integration remains PENDING until activated:

  1. Review the connected company subdomain shown in the Bukku dialog.
  2. Click Activate.

Activation marks the integration ACTIVE and completes setup for the entity. At this stage, accounting sync capabilities are still being implemented on the Bukku connector; the UI may show read-only notices for some extraction-type settings.

Landing Status on Publish #

AP bills and AR invoices carry a per-entity landing status, set per document type in the Bukku dialog (Entity Settings → Integrations → Bukku → AP Bills / AR Invoices). It maps onto Bukku’s three save states:

tofu setting Bukku status Effect
Draft draft Lands unposted; the user commits it in Bukku
Pending Approval pending_approval Enters Bukku’s approval queue
Ready ready Committed on arrival — no second approval step

The setting is stored on the entity (accounting_invoice_status_on_publish for bills, ar_invoices_accounting_invoice_status_on_publish for AR invoices) and is applied by bonsai-accounting-sync only for providers where IntegrationProvider::supports_status_on_publish is true (Xero and Bukku).

An entity that never chose a status publishes as Draft. Bukku returns Draft from IntegrationProvider::default_invoice_status_on_publish, which takes priority over the legacy accounting_invoice_status_on_verify fallback that Xero still uses. That column defaults to SUBMITTED, so without the Bukku-specific default every existing entity would have started committing its bills the day this shipped. Opting in is deliberate: the status only changes once someone picks one in the dialog.

Direct expenses have no such setting — accounting-sync hardcodes them to Authorized for every provider, which Bukku publishes as ready. Credit notes have none either, because Bukku lacks the can_publish_credit_note capability.

Publishing as ready interacts with delete-before-publish: a committed document cannot be deleted, so republishing voids it and creates a replacement. Entities that edit after publishing will accumulate voided documents in Bukku.

Managing the Connection #

Action Steps
View status Entity Settings → Integrations → Bukku
Deactivate Open the Bukku integration dialog → Deactivate
Reconnect Deactivate, then add Bukku again with fresh credentials
Change company Deactivate and connect with the other Bukku company’s subdomain and token

Capabilities and Limitations #

Capability Supported
API-key authentication Yes
OAuth sign-in No
Read accounting reference data Yes
Publish AR invoices / AP bills to Bukku Yes
Publish direct expenses (payment vouchers) Yes
Update in place No — republish uses delete-before-publish
Attachment upload on publish Yes — max 10 MB per file. Multi-page documents over the limit are split into several ≤10 MB PDFs by the page-collection pipeline and uploaded as separate attachments; a single file that still exceeds 10 MB is rejected with an error
Create contacts (suppliers/customers) Yes
Multiple accounting integrations per entity No
Self-prompt knowledge setup (AP bill, AR invoice, direct expense) Available during activation flow when enabled for the entity

Troubleshooting #

“Access Token is required” / “Company Subdomain is required” #

  • Cause: One or both fields were left empty.
  • Fix: Enter both values before clicking Connect.

“Failed to connect Bukku integration” / invalid credentials #

  • Cause: Token is wrong, expired, or revoked; subdomain does not match the token’s company; API Access is disabled in Bukku.
  • Fix:
    1. Regenerate the token in Bukku Control Panel → Integrations → API Access.
    2. Confirm the subdomain matches the Bukku login URL prefix exactly.
    3. Retry Connect.

Cannot add Bukku — another accounting integration exists #

  • Cause: The entity already has an active accounting integration (Xero, QBO, Zoho, etc.).
  • Fix: Deactivate the existing accounting integration first, then add Bukku.

Activate button is disabled #

  • Cause: Connect step did not complete or subdomain metadata is missing.
  • Fix: Complete Connect successfully and confirm the connected company subdomain is displayed.

API Reference (Internal) #

For programmatic connection details, see Integration APIs.

Provider code: BUKKU

Create integration:

POST /api/v1/integrations/api-key?entity_id={entity_id}
{
  "provider": "BUKKU",
  "credentials": {
    "access_token": "<bukku-access-token>",
    "subdomain": "<company-subdomain>"
  }
}

Activate integration:

PUT /api/v1/integrations/{integrationId}?entity_id={entity_id}
{
  "status": "PENDING",
  "public_metadata": {
    "provider": "BUKKU",
    "subdomain": "<company-subdomain>"
  }
}