Reports
The ledger, how refunds net out, the export, and what is not in it.
Every collected payment leaves one row, every refund leaves a negative one, and the report is that ledger summed over a period. Nothing is recomputed at read time, so a report of last quarter shows the rates that applied then, not the rates that apply now.
What goes into the ledger
A row is written when the payment is credited, not when it is created and not when it is attempted. Four things stop it.
| Condition | Result |
|---|---|
| Tax is off on your account | No row, and no catching up later if you switch it on |
| The payment is a sandbox one | No row, ever |
| The payment is a funding top-up of your own balance | No row |
| The computed tax is zero | No row, so a zero-rated country leaves nothing behind |
The row is written once per payment. A second attempt on the same payment, or a replay of the event, never duplicates it.
A refund writes a negative row
Refund a payment and the ledger reverses the tax in the same proportion. Refund a third of the amount and a third of the tax comes back, at the original rate, against the original country, with both amounts negative.
That proportion is capped at the whole: refunding more than the recorded base still reverses at most one hundred percent of the tax. And when the original payment left no row, because Tax was off at the time, the reversal is computed fresh from today's rate for that country rather than being skipped.
The consequence is the one you want at filing time: the report nets collections against reversals on its own, and you never subtract anything by hand.
The report
https://api.wajub.com/tax/reportsFive query parameters, all optional, and the two filters narrow the whole payload rather than adding a section to it.
periodenumoptionaldefault : 30dstart_datedateoptionalend_datedateoptionalcountrystringoptionalcurrencystringoptionalThe response nests everything under report, and gives you the same figures three times: once as a
total, once per country, once per currency.
Three details matter when you reconcile against your own books. tax_collected counts only
positive rows and tax_reversed only negative ones, so net_tax is their sum and is the figure
you file. transactions counts every row in the group, reversals included, so a country with
three hundred payments and twelve refunds reports three hundred and twelve. And summary.currency
is whatever you filtered on, or the first currency found: on a multi-currency account the summary
adds amounts across currencies, which is only meaningful once you have filtered to one.
File country by country, one currency at a time
You owe tax to a jurisdiction in its own currency, so the report you act on is the one with both
country and currency set. by_country on an unfiltered report is useful for spotting where
you have exposure, not for filling in a return.
The Dashboard report is not the same object
Tax in the Dashboard answers the same question with a different payload, so do not expect the two to line up field for field.
| API | Dashboard | |
|---|---|---|
| Period | start_date and end_date | A period object with start and end |
| Total | summary.total_tax_collected | total_tax |
| Per row | tax_collected and transactions | tax_amount and count |
| Collections and reversals | Split into two fields | Summed into one |
| Across currencies | Not converted | Converted into your base currency as global_total |
| Rates | Absent | The rate table is included alongside |
The Dashboard one nets collections and reversals into a single figure per row, which is why a month
with refunds reads lower there than tax_collected does on the API. Both are right, they answer
slightly different questions.
The CSV export
Tax, then export, downloads the current view as a semicolon-separated CSV with a UTF-8 marker, so Excel opens it correctly in French and Portuguese locales without an import step. It carries the period, the totals, the base currency conversion when you trade in several, then one block per country and one per currency.
Exports count against your plan's monthly quota: ten a month on Pay as you go, unlimited from Growth up. There is no export on the API.
Registration thresholds
Many jurisdictions only require you to register once your local revenue crosses a line.
GET /tax/thresholds lists the thresholds Wajub tracks, with the amount, the currency and the
period each is measured over.
GET /tax/thresholds/alerts compares them against your own recorded revenue for the current
calendar year and returns only what needs attention: approaching from 80 % of the line, and
exceeded at 100 %. An empty array means nothing is close, and it is also what you get before
any tax has been recorded.
The comparison is against what Wajub recorded
Your local revenue here is the sum of taxable_amount on your positive tax rows, for the current
calendar year. Revenue collected before you turned Tax on is not in it, and neither is anything
you invoiced outside Wajub. Treat the alert as a prompt to check, not as a legal position.
What the ledger does not hold
Worth knowing so you do not look for exports that are not there.
No per-jurisdiction breakdown. When several sub-national rates apply, the row carries their total, not the split. The breakdown exists in the calculation and is not persisted.
No mobile money levy and no digital services tax. Both are computed in places and neither is recorded, shown on a payment, or added to anything. Where a country levies one, it is not in your Wajub figures.
Nothing on the payment object. GET /payments/{id} returns no tax field. The ledger is read
through the report endpoint and the Dashboard, nowhere else.
No webhook. No event fires when a row is written or reversed.
Filing stays yours
Wajub computes a rate and keeps a ledger. It does not register you anywhere, does not file a return, and does not remit anything to an authority. Those obligations are yours, and the figures here are a starting point for your accountant rather than a filing.