New to Kestra?
Use blueprints to kickstart your first workflows.
Fetch a Pennylane trial balance, sum debits versus credits, alert Slack if the period does not balance, and log the result.
A trial balance that does not net to zero means something is wrong in the books, a missing entry, a sync error from an upstream integration, a manual journal entry that only hit one side of the ledger. Pennylane's own interface shows the trial balance on request; it does not page anyone when debits and credits stop matching. This blueprint fetches the trial balance for a period, sums both sides, and alerts the moment they diverge past a tolerance you set.
This blueprint was created by Mohit Jeswani.
get_trial_balance (io.kestra.plugin.pennylane.accounting.trialbalance.Get) retrieves
every ledger account's debits and credits for period_start to period_end, paginating
up to max_records. Read-only; nothing in Pennylane is written. allowFailure: true
covers an API or auth error without failing the flow outright.evaluate (io.kestra.plugin.core.output.OutputValues) sums debits and credits across
every row with a jq filter (debits/credits are typed loosely by the API, so each value
is coerced with tonumber before summing), and compares the absolute difference to
max_imbalance. get_trial_balance failing outright is also CRITICAL.route (io.kestra.plugin.core.flow.If):summary logs the imbalance and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired API token.accounting.trialbalance.Get used for a governance check rather than a data export.Pennylane computes the trial balance; it does not decide a cadence, compare the two sides, or
notify anyone when they stop matching. Kestra keeps max_imbalance as a flow input instead of
a one-off spreadsheet check, turns the comparison into a Slack page naming the exact imbalance,
and keeps a full execution history of every period checked.
trial_balance:readonly.This flow calls the Pennylane API directly over HTTPS; there is no official local Pennylane
emulator, so get_trial_balance cannot be exercised against a local Docker container. Use a
Pennylane sandbox or test company to validate this end to end.
PENNYLANE_API_TOKEN: the company or firm API token used by get_trial_balance. In Kestra
OSS, provide it as the base64-encoded environment variable SECRET_PENNYLANE_API_TOKEN.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as the
base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Default | Purpose |
|---|---|---|
period_start |
2026-01-01 |
Start of the accounting period |
period_end |
2026-01-31 |
End of the accounting period |
max_imbalance |
0.01 |
Absolute debits-minus-credits tolerance before alerting |
max_records |
5000 |
Safety cap on rows retrieved across all pages |
{{ outputs.get_trial_balance.rows }}: every ledger account row (number,
formatted_number, label, debits, credits).{{ outputs.evaluate.values.total_debits }} / .total_credits / .imbalance: the computed
sums and their signed difference.{{ outputs.evaluate.values.severity }}: OK, OUT_OF_BALANCE, or CRITICAL.debits/credits are typed loosely by the Pennylane API and may arrive as strings; the
jq filter coerces every value with tonumber before summing. A ledger account whose
values are not numeric strings would fail that coercion rather than being silently skipped.Get does not paginate past max_records; a trial balance with more accounts than that cap
is only partially summed, and a true imbalance could be masked by rows that were never
fetched. Set max_records well above the company's actual chart-of-accounts size.account_count in the Slack alert or summary log if that matters to you.PENNYLANE_API_TOKEN and SLACK_WEBHOOK_URL secrets.period_start/period_end to a real closed period and run the flow manually.compliant logs matching totals.max_imbalance below the real rounding noise on a large ledger to confirm alert
fires, then restore it.monthly trigger once the period inputs match your actual closing cadence.io.kestra.plugin.core.flow.Loop to re-check
prior months whenever a new integration or import touches historical data.label (ledger account) instead of a single total, to name which
account is driving the imbalance rather than just the aggregate.