TAŇBA-OOH Developers

Read a statement and check its evidence

A statement tells an operator what was billed for a period and on what evidence. Every figure in it can be traced to stored records, and the records can be checked without trusting the platform. This guide shows how to read the statement and how to check the evidence offline.

Reference pages: Evidence and offline checking and Approval envelope and revocation list formats.

Get the statement

In the console, open Billing, choose the period and download the statement as a PDF in Kazakh, Russian or English. The same figures are in the integration API, with the scope read:billing:

curl -H 'Authorization: Bearer tnbk_EXAMPLE_secret' \
  'https://app.tanba-ooh.kz/api/v1/billing/periods/0b1c3a52-6f0e-4c2e-9d3a-2f5d1e7a9c10'

The statement ends with a basis line, for example basis: 96240 plays, evidence tier: mtls, model: billing-v0. It states how many plays the bill rests on, which evidence tier gave them and which multiplier model turned plays into billing units. Evidence is frozen with its period: a closed period always shows the figures it was closed with.

Read the lines

Each line of the answer is one charge:

FieldMeaning
kindimpression for plays, approval_single and approval_prepaid for approval fees, lab for a laboratory fee
source_refFor a play line, the structure and the hours it covers; for a late line, the structure and the month; for a fee line, the approval number
quantityBilling units. For plays it is the number of plays multiplied by the multiplier of the structure's format in the model; billing-v0 is 1.000 for every format, so units equal plays
amount_kzt, vat_kztThe amount in tenge as a decimal string, without VAT, and the VAT
tiersThe evidence tiers that gave the plays of the line
modelThe multiplier model; empty for a fee line

Two blocks next to the lines keep the picture honest:

A play line named <code> late <yyyy-mm> bills, once, plays of an earlier closed month that arrived after that month was closed, at the tariff of that month.

Evidence tiers

The tier is the channel the plays came on, and it fixes how far they are trusted.

TierChannel
mtlsA player with a client certificate, signing its batches (Send proof of play)
signedA player or agent with a registered key
attestedThe operator's CMS, vouching for its players with a signed batch
nativeA further channel that carries a per-device credential
importRows an operator imported from its own CMS through play import; kept apart and never billed

For one structure, approval and hour, plays are never added across tiers: the tier with the most plays gives the figure, so a screen reported by both its player and a CMS is billed once. The tiers that decide the bill are a setting of the platform owner.

Check the evidence yourself

Everything below needs only tanba-verify, which you can download on the Downloads page, and root.pem, the platform root certificate that approvals, revocation lists, anchors and seals chain to. The root for the test contour comes with the test environment; the set of root certificates will be published on the Downloads page when the production root exists.

1. The daily seal of the received statistics

Every Almaty day, shortly after midnight, the platform seals the statistics batches it received the day before: one Merkle root over the batches, signed with its status key, chained to the seal of the day before and recorded in the public ledger. Only counts and the root are public.

curl -o seal.json https://verify.tanba-ooh.kz/v1/stats-seals/2026-10-13
tanba-verify seal seal.json --ca root.pem

OK means that the signature is the status key's and chains to the root, that the body is the signed one, and that the ledger proof leads from the seal to the root of its ledger day. Exit code 0 is good, 2 means something is bad, and 6 means the seal is sound but no ledger day holds it yet: fetch it again later. A batch among the batches of a seal can be checked with --batch-proof, which takes a file with the Merkle path of that batch; no public call serves such a file yet.

2. The ledger day and Bitcoin

The seal is a leaf of the ledger day on which it was made. That day's digest is timestamped in Bitcoin. Recompute the digest from the inputs and check the proof:

curl -o ledger-2026-10-14.json https://verify.tanba-ooh.kz/v1/ledger-days/2026-10-14
curl -o ledger-2026-10-14.ots https://verify.tanba-ooh.kz/v1/ledger-days/2026-10-14/proof.ots
tanba-verify ledger --day 2026-10-14 --ots ledger-2026-10-14.ots --inputs ledger-2026-10-14.json \
  --btc-header-url https://blockstream.info/api

Exit 0 means the proof carries a Bitcoin block. Exit 2 means the inputs are inconsistent, 3 that the proof is for another digest, 6 that the proof is still pending, and 8 that the public block explorer disagrees. Without --btc-header-url the block header is not checked here; the official ots verify -d DIGEST FILE.ots checks it against your own node.

3. One approval in the ledger

curl -o ledger-proof.json https://verify.tanba-ooh.kz/v1/approval/TNB-2026-000123/ledger-proof
tanba-verify inclusion --proof ledger-proof.json --approval TNB-2026-000123

The proof says that the approval's leaf is in the tree of its day. It is available once the day is closed and recorded.

4. An approval, a revocation list and an anchor

tanba-verify spot.mp4 spot.mp4.p7s --roots root.pem
tanba-verify revocations list.p7s --ca root.pem
tanba-verify anchor anchor-2026-10-05.p7s --ca root.pem

The first command checks a media file against its approval envelope. Its exit codes are 0 OK, 2 BAD_SIGNATURE, 3 HASH_MISMATCH, 4 EXPIRED_APPROVAL, 5 NOT_YET_VALID and 64 for a wrong command or an unreadable file; 6 OUTER_NOT_VERIFIED and 7 OUTER_INVALID concern the state signature. The second prints a signed revocation list and the third checks a daily audit anchor, both with exit 0 or 2. The formats are described in Approval envelope and revocation list formats.

5. A stored batch

Every accepted proof-of-play batch is stored as the bytes received, with the signature and the SHA-256 of the body. Take the batch, hash it, verify its signature with the public key of the device or of the CMS installation, and follow prev_sha256 and seq. How this works is in Send proof of play.

What the evidence does not prove

The ledger shows that a record existed on a day and was not altered afterwards. It does not show that the decision behind a record was right. The seal covers what the platform received; a play that was never reported is not in it, and a missing stretch shows as a gap in the record numbers of the player.